Mon May 14 04:46:06 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"

Include dependency graph for chan_iax2.c:

Go to the source code of this file.

Data Structures

struct  ast_firmware_list
struct  ast_iax2_queue
struct  chan_iax2_pvt
struct  create_addr_info
struct  dpreq_data
struct  iax2_context
struct  iax2_dpcache
struct  iax2_peer
struct  iax2_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)
}
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 acf_iaxvar_read (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int acf_iaxvar_write (struct ast_channel *chan, char *cmd, char *varname, const char *value)
static int apply_context (struct iax2_context *con, const char *context)
static int ast_cli_netstats (struct mansession *s, int fd, int limit_fmt)
static struct ast_channelast_iax2_new (int callno, int state, int capability)
 Create new call, interface with the PBX core.
static AST_LIST_HEAD_STATIC (dynamic_list, iax2_thread)
static AST_LIST_HEAD_STATIC (active_list, iax2_thread)
static AST_LIST_HEAD_STATIC (idle_list, iax2_thread)
static AST_LIST_HEAD_STATIC (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_contextbuild_context (char *context)
static void build_enc_keys (const unsigned char *digest, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx)
static struct iax2_peerbuild_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
 Create peer structure based on configuration.
static struct iax2_userbuild_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
 Create in-memory user structure from configuration.
static int cache_get_callno_locked (const char *data)
static unsigned int calc_rxstamp (struct chan_iax2_pvt *p, unsigned int offset)
static unsigned int calc_timestamp (struct chan_iax2_pvt *p, unsigned int ts, struct ast_frame *f)
static unsigned int calc_txpeerstamp (struct iax2_trunk_peer *tpeer, int sampms, struct timeval *tv)
static int check_access (int callno, struct sockaddr_in *sin, struct iax_ies *ies)
static int check_provisioning (struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver)
static int check_srcaddr (struct sockaddr *sa, socklen_t salen)
 Check if address can be used as packet source.
static int complete_dpreply (struct chan_iax2_pvt *pvt, struct iax_ies *ies)
static char * complete_iax2_show_peer (const char *line, const char *word, int pos, int state)
static int complete_transfer (int callno, struct iax_ies *ies)
static unsigned char compress_subclass (int subclass)
static void construct_rr (struct chan_iax2_pvt *pvt, struct iax_ie_data *iep)
static int create_addr (const char *peername, struct sockaddr_in *sin, struct create_addr_info *cai)
static int decode_frame (aes_decrypt_ctx *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen)
static int decrypt_frame (int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen)
static void 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_dpcachefind_cache (struct ast_channel *chan, const char *data, const char *context, const char *exten, int priority)
static int find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int lockpeer, int sockfd)
static struct iax2_threadfind_idle_thread (void)
static struct iax2_peerfind_peer (const char *name, int realtime)
static struct iax2_trunk_peerfind_tpeer (struct sockaddr_in *sin, int fd)
static unsigned int fix_peerts (struct timeval *tv, int callno, unsigned int ts)
static void free_context (struct iax2_context *con)
static int function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int get_auth_methods (char *value)
static int get_encrypt_methods (const char *s)
static int get_from_jb (void *p)
static 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)
static struct ast_frameiax2_read (struct ast_channel *c)
static int iax2_register (char *value, int lineno)
static int iax2_reload (int fd, int argc, char *argv[])
static struct ast_channeliax2_request (const char *type, int format, void *data, int *cause)
static int iax2_send (struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final)
static int iax2_sendhtml (struct ast_channel *c, int subclass, const char *data, int datalen)
static int iax2_sendimage (struct ast_channel *c, struct ast_frame *img)
static int iax2_sendtext (struct ast_channel *c, const char *text)
static int iax2_setoption (struct ast_channel *c, int option, void *data, int datalen)
static int iax2_show_cache (int fd, int argc, char *argv[])
static int iax2_show_channels (int fd, int argc, char *argv[])
static int iax2_show_firmware (int fd, int argc, char *argv[])
static int iax2_show_netstats (int fd, int argc, char *argv[])
static int iax2_show_peer (int fd, int argc, char *argv[])
 Show one peer in detail.
static int iax2_show_peers (int fd, int argc, char *argv[])
static int iax2_show_registry (int fd, int argc, char *argv[])
static int iax2_show_stats (int fd, int argc, char *argv[])
static int iax2_show_threads (int fd, int argc, char *argv[])
static int iax2_show_users (int fd, int argc, char *argv[])
static int iax2_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly)
static int iax2_test_losspct (int fd, int argc, char *argv[])
static int iax2_transfer (struct ast_channel *c, const char *dest)
static int iax2_transmit (struct iax_frame *fr)
static int iax2_trunk_expired (struct iax2_trunk_peer *tpeer, struct timeval *now)
static int iax2_trunk_queue (struct chan_iax2_pvt *pvt, struct iax_frame *fr)
static int iax2_vnak (int callno)
static int iax2_write (struct ast_channel *c, struct ast_frame *f)
static int iax_check_version (char *dev)
static void iax_debug_output (const char *data)
static void iax_error_output (const char *data)
static int iax_firmware_append (struct iax_ie_data *ied, const unsigned char *dev, unsigned int desc)
static int iax_park (struct ast_channel *chan1, struct ast_channel *chan2)
static void * iax_park_thread (void *stuff)
static struct iax_frameiaxfrdup2 (struct iax_frame *fr)
static void insert_idle_thread (struct iax2_thread *thread)
static void jb_debug_output (const char *fmt,...)
static void jb_error_output (const char *fmt,...)
static void jb_warning_output (const char *fmt,...)
static int load_module (void)
 Load IAX2 module, load configuraiton ---.
static void lock_both (unsigned short callno0, unsigned short callno1)
static int make_trunk (unsigned short callno, int locked)
static int manager_iax2_show_netstats (struct mansession *s, const struct message *m)
static int manager_iax2_show_peers (struct mansession *s, const struct message *m)
static int match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, struct chan_iax2_pvt *cur)
static void memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, aes_decrypt_ctx *dcx)
static void memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, aes_encrypt_ctx *ecx)
static void merge_encryption (struct chan_iax2_pvt *p, unsigned int enc)
static void * network_thread (void *ignore)
static struct chan_iax2_pvtnew_iax (struct sockaddr_in *sin, 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_dpcachedpcache
static int global_rtautoclear = 120
static struct ast_flags globalflags = { 0 }
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH
static int iax2_encryption = 0
enum { ... }  iax2_flags
int(*) iax2_regfunk (const char *username, int onoff) = NULL
static char iax2_reload_usage []
enum { ... }  iax2_state
static struct ast_switch iax2_switch
static struct ast_channel_tech iax2_tech
static char iax2_test_losspct_usage []
static int iaxactivethreadcount = 0
static int iaxcompat = 0
static int iaxdebug = 0
static int iaxdefaultdpcache = 10 * 60
static int iaxdefaulttimeout = 5
static int iaxdynamicthreadcount = 0
static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT
ast_custom_function iaxpeer_function
static struct ast_iax2_queue iaxq
static struct chan_iax2_pvtiaxs [IAX_MAX_CALLS]
static ast_mutex_t iaxsl [IAX_MAX_CALLS]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct ast_custom_function iaxvar_function
static struct io_contextio
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static struct timeval lastused [IAX_MAX_CALLS]
static int max_reg_expire
static int max_retries = 4
static int maxauthreq = 3
static int maxjitterbuffer = 1000
static int maxjitterinterps = 10
static int maxnontrunkcall = 1
static int maxtrunkcall = TRUNK_CALL_START
static int min_reg_expire
static char mohinterpret [MAX_MUSICCLASS]
static char mohsuggest [MAX_MUSICCLASS]
static struct ast_netsock_listnetsock
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_jb_usage []
static char no_debug_trunk_usage []
static char no_debug_usage []
static struct ast_netsock_listoutsock
static char * papp = "IAX2Provision"
static char * pdescrip
static int ping_time = 20
static struct ast_codec_pref prefs
static char prune_realtime_usage []
static char * psyn = "Provision a calling IAXy with a given template"
static char regcontext [AST_MAX_CONTEXT] = ""
static int resyncthreshold = 1000
static struct sched_contextsched
static ast_cond_t sched_cond
static pthread_t schedthreadid = AST_PTHREADT_NULL
static char show_cache_usage []
static char show_channels_usage []
static char show_firmware_usage []
static char show_netstats_usage []
static char show_peer_usage []
static char show_peers_usage []
static char show_prov_usage []
static char show_reg_usage []
static char show_stats_usage []
static char show_threads_usage []
static char show_users_usage []
static const char tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)"
static int test_losspct = 0
static int timingfd = -1
static unsigned int tos = 0
static struct iax2_trunk_peertpeers
static int trunkfreq = 20
static struct 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 642 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 638 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 652 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 640 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 644 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 646 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

Definition at line 648 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 650 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 440 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 361 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 674 of file chan_iax2.c.

#define IAX_IOSTATE_PROCESSING   2

Definition at line 676 of file chan_iax2.c.

#define IAX_IOSTATE_READY   1

Definition at line 675 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 677 of file chan_iax2.c.

Referenced by __schedule_action().

#define IAX_TYPE_DYNAMIC   2

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

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

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

#define MIN_RETRY_TIME   100

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

Referenced by find_callno(), and socket_process().

#define NEW_FORCE   2

Definition at line 1108 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 1106 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 909 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 446 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

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 } 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 392 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 402 of file chan_iax2.c.


Function Documentation

static void __attempt_transmit ( void *  data  )  [static]

Definition at line 1835 of file chan_iax2.c.

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

Referenced by attempt_transmit().

01836 {
01837    /* Attempt to transmit the frame to the remote peer...
01838       Called without iaxsl held. */
01839    struct iax_frame *f = data;
01840    int freeme=0;
01841    int callno = f->callno;
01842    /* Make sure this call is still active */
01843    if (callno) 
01844       ast_mutex_lock(&iaxsl[callno]);
01845    if (callno && iaxs[callno]) {
01846       if ((f->retries < 0) /* Already ACK'd */ ||
01847           (f->retries >= max_retries) /* Too many attempts */) {
01848             /* Record an error if we've transmitted too many times */
01849             if (f->retries >= max_retries) {
01850                if (f->transfer) {
01851                   /* Transfer timeout */
01852                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
01853                } else if (f->final) {
01854                   if (f->final) 
01855                      iax2_destroy(callno);
01856                } else {
01857                   if (iaxs[callno]->owner)
01858                      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);
01859                   iaxs[callno]->error = ETIMEDOUT;
01860                   if (iaxs[callno]->owner) {
01861                      struct ast_frame fr = { 0, };
01862                      /* Hangup the fd */
01863                      fr.frametype = AST_FRAME_CONTROL;
01864                      fr.subclass = AST_CONTROL_HANGUP;
01865                      iax2_queue_frame(callno, &fr);
01866                      /* Remember, owner could disappear */
01867                      if (iaxs[callno]->owner)
01868                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01869                   } else {
01870                      if (iaxs[callno]->reg) {
01871                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
01872                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
01873                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
01874                      }
01875                      iax2_destroy(callno);
01876                   }
01877                }
01878 
01879             }
01880             freeme++;
01881       } else {
01882          /* Update it if it needs it */
01883          update_packet(f);
01884          /* Attempt transmission */
01885          send_packet(f);
01886          f->retries++;
01887          /* Try again later after 10 times as long */
01888          f->retrytime *= 10;
01889          if (f->retrytime > MAX_RETRY_TIME)
01890             f->retrytime = MAX_RETRY_TIME;
01891          /* Transfer messages max out at one second */
01892          if (f->transfer && (f->retrytime > 1000))
01893             f->retrytime = 1000;
01894          f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
01895       }
01896    } else {
01897       /* Make sure it gets freed */
01898       f->retries = -1;
01899       freeme++;
01900    }
01901    if (callno)
01902       ast_mutex_unlock(&iaxsl[callno]);
01903    /* Do not try again */
01904    if (freeme) {
01905       /* Don't attempt delivery, just remove it from the queue */
01906       AST_LIST_LOCK(&iaxq.queue);
01907       AST_LIST_REMOVE(&iaxq.queue, f, list);
01908       iaxq.count--;
01909       AST_LIST_UNLOCK(&iaxq.queue);
01910       f->retrans = -1;
01911       /* Free the IAX frame */
01912       iax2_frame_free(f);
01913    }
01914 }

static void __auth_reject ( void *  nothing  )  [static]

Definition at line 5793 of file chan_iax2.c.

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

Referenced by auth_reject().

05794 {
05795    /* Called from IAX thread only, without iaxs lock */
05796    int callno = (int)(long)(nothing);
05797    struct iax_ie_data ied;
05798    ast_mutex_lock(&iaxsl[callno]);
05799    if (iaxs[callno]) {
05800       memset(&ied, 0, sizeof(ied));
05801       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
05802          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
05803          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
05804       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
05805          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
05806          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
05807       }
05808       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
05809    }
05810    ast_mutex_unlock(&iaxsl[callno]);
05811 }

static void __auto_congest ( void *  nothing  )  [static]

Definition at line 2712 of file chan_iax2.c.

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

Referenced by auto_congest().

02713 {
02714    int callno = PTR_TO_CALLNO(nothing);
02715    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
02716    ast_mutex_lock(&iaxsl[callno]);
02717    if (iaxs[callno]) {
02718       iaxs[callno]->initid = -1;
02719       iax2_queue_frame(callno, &f);
02720       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
02721    }
02722    ast_mutex_unlock(&iaxsl[callno]);
02723 }

static void __auto_hangup ( void *  nothing  )  [static]

Definition at line 5845 of file chan_iax2.c.

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

Referenced by auto_hangup().

05846 {
05847    /* Called from IAX thread only, without iaxs lock */
05848    int callno = (int)(long)(nothing);
05849    struct iax_ie_data ied;
05850    ast_mutex_lock(&iaxsl[callno]);
05851    if (iaxs[callno]) {
05852       memset(&ied, 0, sizeof(ied));
05853       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
05854       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
05855       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
05856    }
05857    ast_mutex_unlock(&iaxsl[callno]);
05858 }

static int __do_deliver ( void *  data  )  [static]

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

01592 {
01593    /* Just deliver the packet by using queueing.  This is called by
01594      the IAX thread with the iaxsl lock held. */
01595    struct iax_frame *fr = data;
01596    fr->retrans = -1;
01597    fr->af.has_timing_info = 0;
01598    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
01599       iax2_queue_frame(fr->callno, &fr->af);
01600    /* Free our iax frame */
01601    iax2_frame_free(fr);
01602    /* And don't run again */
01603    return 0;
01604 }

static void __expire_registry ( void *  data  )  [static]

Definition at line 5518 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, globalflags, iax2_regfunk, IAX_DELME, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, manager_event(), name, prune_peers(), realtime_update_peer(), and register_peer_exten().

Referenced by expire_registry().

05519 {
05520    char *name = data;
05521    struct iax2_peer *p = NULL;
05522 
05523    /* Go through and grab this peer... and if it needs to be removed... then do it */
05524    AST_LIST_LOCK(&peers);
05525    AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, p, entry) {
05526       if (!strcasecmp(p->name, name)) {
05527          p->expire = -1;
05528          break;
05529       }
05530    }
05531    AST_LIST_TRAVERSE_SAFE_END
05532    AST_LIST_UNLOCK(&peers);
05533 
05534    /* Peer is already gone for whatever reason */
05535    if (!p)
05536       return;
05537 
05538    ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", p->name);
05539    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
05540       realtime_update_peer(p->name, &p->addr, 0);
05541    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", p->name);
05542    /* Reset the address */
05543    memset(&p->addr, 0, sizeof(p->addr));
05544    /* Reset expiry value */
05545    p->expiry = min_reg_expire;
05546    if (!ast_test_flag(p, IAX_TEMPONLY))
05547       ast_db_del("IAX/Registry", p->name);
05548    register_peer_exten(p, 0);
05549    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05550    if (iax2_regfunk)
05551       iax2_regfunk(p->name, 0);
05552 
05553    if (ast_test_flag(p, IAX_RTAUTOCLEAR)) {
05554       ast_set_flag(p, IAX_DELME);
05555       prune_peers();
05556    }
05557 }

static void __get_from_jb ( void *  p  )  [static]

Definition at line 2232 of file chan_iax2.c.

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

Referenced by get_from_jb().

02233 {
02234    int callno = PTR_TO_CALLNO(p);
02235    struct chan_iax2_pvt *pvt = NULL;
02236    struct iax_frame *fr;
02237    jb_frame frame;
02238    int ret;
02239    long now;
02240    long next;
02241    struct timeval tv;
02242    
02243    /* Make sure we have a valid private structure before going on */
02244    ast_mutex_lock(&iaxsl[callno]);
02245    pvt = iaxs[callno];
02246    if (!pvt) {
02247       /* No go! */
02248       ast_mutex_unlock(&iaxsl[callno]);
02249       return;
02250    }
02251     
02252     if( pvt->jb == NULL ) {
02253    ast_log( LOG_ERROR, "__get_from_jb(): why p->jb is null?\n" );
02254    ast_backtrace();
02255    return;
02256     }
02257 
02258    pvt->jbid = -1;
02259    
02260    gettimeofday(&tv,NULL);
02261    /* round up a millisecond since ast_sched_runq does; */
02262    /* prevents us from spinning while waiting for our now */
02263    /* to catch up with runq's now */
02264    tv.tv_usec += 1000;
02265    
02266    now = ast_tvdiff_ms(tv, pvt->rxcore);
02267    
02268    if(now >= (next = jb_next(pvt->jb))) {
02269       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02270       switch(ret) {
02271       case JB_OK:
02272          fr = frame.data;
02273          __do_deliver(fr);
02274          break;
02275       case JB_INTERP:
02276       {
02277          struct ast_frame af = { 0, };
02278          
02279          /* create an interpolation frame */
02280          af.frametype = AST_FRAME_VOICE;
02281          af.subclass = pvt->voiceformat;
02282          af.samples  = frame.ms * 8;
02283          af.src  = "IAX2 JB interpolation";
02284          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02285          af.offset = AST_FRIENDLY_OFFSET;
02286          
02287          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02288           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02289          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
02290             iax2_queue_frame(callno, &af);
02291       }
02292       break;
02293       case JB_DROP:
02294          iax2_frame_free(frame.data);
02295          break;
02296       case JB_NOFRAME:
02297       case JB_EMPTY:
02298          /* do nothing */
02299          break;
02300       default:
02301          /* shouldn't happen */
02302          break;
02303       }
02304    }
02305    update_jbsched(pvt);
02306    ast_mutex_unlock(&iaxsl[callno]);
02307 }

static void __iax2_do_register_s ( void *  data  )  [static]

Definition at line 5235 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05236 {
05237    struct iax2_registry *reg = data;
05238    reg->expire = -1;
05239    iax2_do_register(reg);
05240 }

static void __iax2_poke_noanswer ( void *  data  )  [static]

Definition at line 7961 of file chan_iax2.c.

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

Referenced by iax2_poke_noanswer().

07962 {
07963    struct iax2_peer *peer = data;
07964    if (peer->lastms > -1) {
07965       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
07966       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
07967       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07968    }
07969    if (peer->callno > 0) {
07970       ast_mutex_lock(&iaxsl[peer->callno]);
07971       iax2_destroy(peer->callno);
07972       ast_mutex_unlock(&iaxsl[peer->callno]);
07973    }
07974    peer->callno = 0;
07975    peer->lastms = -1;
07976    /* Try again quickly */
07977    peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer);
07978 }

static void __iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 5908 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by iax2_poke_peer_s().

05909 {
05910    struct iax2_peer *peer = data;
05911    iax2_poke_peer(peer, 0);
05912 }

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

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

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04061 {
04062    regex_t regexbuf;
04063    int havepattern = 0;
04064    int total_peers = 0;
04065    int online_peers = 0;
04066    int offline_peers = 0;
04067    int unmonitored_peers = 0;
04068 
04069 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04070 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04071 
04072    struct iax2_peer *peer = NULL;
04073    char name[256];
04074    int registeredonly=0;
04075    char *term = manager ? "\r\n" : "\n";
04076 
04077    switch (argc) {
04078    case 6:
04079       if (!strcasecmp(argv[3], "registered"))
04080          registeredonly = 1;
04081       else
04082          return RESULT_SHOWUSAGE;
04083       if (!strcasecmp(argv[4], "like")) {
04084          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04085             return RESULT_SHOWUSAGE;
04086          havepattern = 1;
04087       } else
04088          return RESULT_SHOWUSAGE;
04089       break;
04090    case 5:
04091       if (!strcasecmp(argv[3], "like")) {
04092          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04093             return RESULT_SHOWUSAGE;
04094          havepattern = 1;
04095       } else
04096          return RESULT_SHOWUSAGE;
04097       break;
04098    case 4:
04099       if (!strcasecmp(argv[3], "registered"))
04100          registeredonly = 1;
04101       else
04102          return RESULT_SHOWUSAGE;
04103       break;
04104    case 3:
04105       break;
04106    default:
04107       return RESULT_SHOWUSAGE;
04108    }
04109 
04110 
04111    if (s)
04112       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04113    else
04114       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04115 
04116    AST_LIST_LOCK(&peers);
04117    AST_LIST_TRAVERSE(&peers, peer, entry) {
04118       char nm[20];
04119       char status[20];
04120       char srch[2000];
04121       int retstatus;
04122 
04123       if (registeredonly && !peer->addr.sin_addr.s_addr)
04124          continue;
04125       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04126          continue;
04127 
04128       if (!ast_strlen_zero(peer->username))
04129          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04130       else
04131          ast_copy_string(name, peer->name, sizeof(name));
04132       
04133       retstatus = peer_status(peer, status, sizeof(status));
04134       if (retstatus > 0)
04135          online_peers++;
04136       else if (!retstatus)
04137          offline_peers++;
04138       else
04139          unmonitored_peers++;
04140       
04141       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04142       
04143       snprintf(srch, sizeof(srch), FORMAT, name, 
04144           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04145           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04146           nm,
04147           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04148           peer->encmethods ? "(E)" : "   ", status, term);
04149       
04150       if (s)
04151          astman_append(s, FORMAT, name, 
04152                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04153                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04154                   nm,
04155                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04156                   peer->encmethods ? "(E)" : "   ", status, term);
04157       else
04158          ast_cli(fd, FORMAT, name, 
04159             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04160             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04161             nm,
04162             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04163             peer->encmethods ? "(E)" : "   ", status, term);
04164       total_peers++;
04165    }
04166    AST_LIST_UNLOCK(&peers);
04167 
04168    if (s)
04169       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04170    else
04171       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04172 
04173    if (havepattern)
04174       regfree(&regexbuf);
04175 
04176    return RESULT_SUCCESS;
04177 #undef FORMAT
04178 #undef FORMAT2
04179 }

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

Definition at line 884 of file chan_iax2.c.

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

00885 {
00886    struct iax2_thread *thread = NULL;
00887    static time_t lasterror;
00888    static time_t t;
00889 
00890    thread = find_idle_thread();
00891 
00892    if (thread != NULL) {
00893       thread->schedfunc = func;
00894       thread->scheddata = data;
00895       thread->iostate = IAX_IOSTATE_SCHEDREADY;
00896 #ifdef DEBUG_SCHED_MULTITHREAD
00897       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
00898 #endif
00899       signal_condition(&thread->lock, &thread->cond);
00900       return 0;
00901    }
00902    time(&t);
00903    if (t != lasterror) 
00904       ast_log(LOG_NOTICE, "Out of idle IAX2 threads for scheduling!\n");
00905    lasterror = t;
00906 
00907    return -1;
00908 }

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

References f, and iax2_send().

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

04561 {
04562    struct ast_frame f = { 0, };
04563 
04564    f.frametype = type;
04565    f.subclass = command;
04566    f.datalen = datalen;
04567    f.src = __FUNCTION__;
04568    f.data = (void *) data;
04569 
04570    return iax2_send(i, &f, ts, seqno, now, transfer, final);
04571 }

static void __send_lagrq ( void *  data  )  [static]

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

Referenced by send_lagrq().

00949 {
00950    int callno = (long)data;
00951    /* Ping only if it's real not if it's bridged */
00952    ast_mutex_lock(&iaxsl[callno]);
00953    if (iaxs[callno] && iaxs[callno]->lagid != -1) {
00954       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
00955       iaxs[callno]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
00956    }
00957    ast_mutex_unlock(&iaxsl[callno]);
00958 }

static void __send_ping ( void *  data  )  [static]

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

Referenced by send_ping().

00915 {
00916    int callno = (long)data;
00917    ast_mutex_lock(&iaxsl[callno]);
00918    if (iaxs[callno] && iaxs[callno]->pingid != -1) {
00919       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
00920       iaxs[callno]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, data);
00921    }
00922    ast_mutex_unlock(&iaxsl[callno]);
00923 }

static int __unload_module ( void   )  [static]

Definition at line 10057 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_provision_unload(), iaxactivethreadcount, iaxq, iaxs, iaxsl, ast_firmware_list::lock, netsock, outsock, sched, sched_context_destroy(), thread, and waresl.

Referenced by load_module(), and unload_module().

10058 {
10059    struct iax2_thread *thread = NULL;
10060    int x;
10061 
10062    /* Make sure threads do not hold shared resources when they are canceled */
10063    
10064    /* Grab the sched lock resource to keep it away from threads about to die */
10065    /* Cancel the network thread, close the net socket */
10066    if (netthreadid != AST_PTHREADT_NULL) {
10067       AST_LIST_LOCK(&iaxq.queue);
10068       ast_mutex_lock(&sched_lock);
10069       pthread_cancel(netthreadid);
10070       ast_cond_signal(&sched_cond);
10071       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10072       AST_LIST_UNLOCK(&iaxq.queue);
10073       pthread_join(netthreadid, NULL);
10074    }
10075    if (schedthreadid != AST_PTHREADT_NULL) {
10076       ast_mutex_lock(&sched_lock);  
10077       pthread_cancel(schedthreadid);
10078       ast_cond_signal(&sched_cond);
10079       ast_mutex_unlock(&sched_lock);   
10080       pthread_join(schedthreadid, NULL);
10081    }
10082    
10083    /* Call for all threads to halt */
10084    AST_LIST_LOCK(&idle_list);
10085    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10086       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10087       pthread_cancel(thread->threadid);
10088    }
10089    AST_LIST_TRAVERSE_SAFE_END
10090    AST_LIST_UNLOCK(&idle_list);
10091 
10092    AST_LIST_LOCK(&active_list);
10093    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10094       AST_LIST_REMOVE_CURRENT(&active_list, list);
10095       pthread_cancel(thread->threadid);
10096    }
10097    AST_LIST_TRAVERSE_SAFE_END
10098    AST_LIST_UNLOCK(&active_list);
10099 
10100    AST_LIST_LOCK(&dynamic_list);
10101         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
10102       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
10103       pthread_cancel(thread->threadid);
10104         }
10105    AST_LIST_TRAVERSE_SAFE_END
10106         AST_LIST_UNLOCK(&dynamic_list);
10107 
10108    AST_LIST_HEAD_DESTROY(&iaxq.queue);
10109 
10110    /* Wait for threads to exit */
10111    while(0 < iaxactivethreadcount)
10112       usleep(10000);
10113    
10114    ast_netsock_release(netsock);
10115    ast_netsock_release(outsock);
10116    for (x=0;x<IAX_MAX_CALLS;x++)
10117       if (iaxs[x])
10118          iax2_destroy(x);
10119    ast_manager_unregister( "IAXpeers" );
10120    ast_manager_unregister( "IAXnetstats" );
10121    ast_unregister_application(papp);
10122    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10123    ast_unregister_switch(&iax2_switch);
10124    ast_channel_unregister(&iax2_tech);
10125    delete_users();
10126    iax_provision_unload();
10127    sched_context_destroy(sched);
10128 
10129    ast_mutex_destroy(&waresl.lock);
10130 
10131    for (x = 0; x < IAX_MAX_CALLS; x++)
10132       ast_mutex_destroy(&iaxsl[x]);
10133 
10134    return 0;
10135 }

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

Definition at line 6290 of file chan_iax2.c.

References pbx_builtin_getvar_helper().

06291 {
06292    const char *value;
06293    char tmp[256];
06294    snprintf(tmp, sizeof(tmp), "~IAX2~%s", data);
06295    value = pbx_builtin_getvar_helper(chan, tmp);
06296    ast_copy_string(buf, value ? value : "", len);
06297    return 0;
06298 }

static int acf_iaxvar_write ( struct ast_channel chan,
char *  cmd,
char *  varname,
const char *  value 
) [static]

Definition at line 6300 of file chan_iax2.c.

References pbx_builtin_setvar_helper().

06301 {
06302    char tmp[256];
06303    /* Inherit forever */
06304    snprintf(tmp, sizeof(tmp), "__~IAX2~%s", varname);
06305    pbx_builtin_setvar_helper(chan, tmp, value);
06306    return 0;
06307 }

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

Definition at line 4604 of file chan_iax2.c.

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

Referenced by check_access().

04605 {
04606    while(con) {
04607       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
04608          return -1;
04609       con = con->next;
04610    }
04611    return 0;
04612 }

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

Definition at line 4387 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_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), iax_rr::jitter, jb_info::jitter, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, chan_iax2_pvt::remote_rr, and s.

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04388 {
04389    int x;
04390    int numchans = 0;
04391    for (x=0;x<IAX_MAX_CALLS;x++) {
04392       ast_mutex_lock(&iaxsl[x]);
04393       if (iaxs[x]) {
04394          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04395          char *fmt;
04396          jb_info jbinfo;
04397          
04398          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04399             jb_getinfo(iaxs[x]->jb, &jbinfo);
04400             localjitter = jbinfo.jitter;
04401             localdelay = jbinfo.current - jbinfo.min;
04402             locallost = jbinfo.frames_lost;
04403             locallosspct = jbinfo.losspct/1000;
04404             localdropped = jbinfo.frames_dropped;
04405             localooo = jbinfo.frames_ooo;
04406          } else {
04407             localjitter = -1;
04408             localdelay = 0;
04409             locallost = -1;
04410             locallosspct = -1;
04411             localdropped = 0;
04412             localooo = -1;
04413          }
04414          if (limit_fmt)
04415             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04416          else
04417             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04418          if (s)
04419             
04420             astman_append(s, fmt,
04421                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04422                      iaxs[x]->pingtime,
04423                      localjitter, 
04424                      localdelay,
04425                      locallost,
04426                      locallosspct,
04427                      localdropped,
04428                      localooo,
04429                      iaxs[x]->frames_received/1000,
04430                      iaxs[x]->remote_rr.jitter,
04431                      iaxs[x]->remote_rr.delay,
04432                      iaxs[x]->remote_rr.losscnt,
04433                      iaxs[x]->remote_rr.losspct,
04434                      iaxs[x]->remote_rr.dropped,
04435                      iaxs[x]->remote_rr.ooo,
04436                      iaxs[x]->remote_rr.packets/1000);
04437          else
04438             ast_cli(fd, fmt,
04439                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04440                iaxs[x]->pingtime,
04441                localjitter, 
04442                localdelay,
04443                locallost,
04444                locallosspct,
04445                localdropped,
04446                localooo,
04447                iaxs[x]->frames_received/1000,
04448                iaxs[x]->remote_rr.jitter,
04449                iaxs[x]->remote_rr.delay,
04450                iaxs[x]->remote_rr.losscnt,
04451                iaxs[x]->remote_rr.losspct,
04452                iaxs[x]->remote_rr.dropped,
04453                iaxs[x]->remote_rr.ooo,
04454                iaxs[x]->remote_rr.packets/1000
04455                );
04456          numchans++;
04457       }
04458       ast_mutex_unlock(&iaxsl[x]);
04459    }
04460    return numchans;
04461 }

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

Create new call, interface with the PBX core.

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

03300 {
03301    struct ast_channel *tmp;
03302    struct chan_iax2_pvt *i;
03303    struct ast_variable *v = NULL;
03304 
03305    if (!(i = iaxs[callno])) {
03306       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03307       return NULL;
03308    }
03309 
03310    /* Don't hold call lock */
03311    ast_mutex_unlock(&iaxsl[callno]);
03312    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);
03313    ast_mutex_lock(&iaxsl[callno]);
03314    if (!tmp)
03315       return NULL;
03316    tmp->tech = &iax2_tech;
03317    /* We can support any format by default, until we get restricted */
03318    tmp->nativeformats = capability;
03319    tmp->readformat = ast_best_codec(capability);
03320    tmp->writeformat = ast_best_codec(capability);
03321    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03322 
03323    /* Don't use ast_set_callerid() here because it will
03324     * generate a NewCallerID event before the NewChannel event */
03325    tmp->cid.cid_num = ast_strdup(i->cid_num);
03326    tmp->cid.cid_name = ast_strdup(i->cid_name);
03327    if (!ast_strlen_zero(i->ani))
03328       tmp->cid.cid_ani = ast_strdup(i->ani);
03329    else
03330       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03331    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03332    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03333    tmp->cid.cid_pres = i->calling_pres;
03334    tmp->cid.cid_ton = i->calling_ton;
03335    tmp->cid.cid_tns = i->calling_tns;
03336    if (!ast_strlen_zero(i->language))
03337       ast_string_field_set(tmp, language, i->language);
03338    if (!ast_strlen_zero(i->accountcode))
03339       ast_string_field_set(tmp, accountcode, i->accountcode);
03340    if (i->amaflags)
03341       tmp->amaflags = i->amaflags;
03342    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03343    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03344    if (i->adsi)
03345       tmp->adsicpe = i->peeradsicpe;
03346    else
03347       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03348    i->owner = tmp;
03349    i->capability = capability;
03350    if (state != AST_STATE_DOWN) {
03351       if (ast_pbx_start(tmp)) {
03352          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03353          ast_hangup(tmp);
03354          i->owner = NULL;
03355          return NULL;
03356       }
03357    }
03358 
03359    for (v = i->vars ; v ; v = v->next)
03360       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03361 
03362    ast_module_ref(ast_module_info->self);
03363    
03364    return tmp;
03365 }

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

01917 {
01918 #ifdef SCHED_MULTITHREADED
01919    if (schedule_action(__attempt_transmit, data))
01920 #endif      
01921       __attempt_transmit(data);
01922    return 0;
01923 }

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

Definition at line 5827 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, iaxsl, and sched.

Referenced by socket_process().

05828 {
05829    /* Schedule sending the authentication failure in one second, to prevent
05830       guessing */
05831    ast_mutex_lock(&iaxsl[callno]);
05832    if (iaxs[callno]) {
05833       iaxs[callno]->authfail = failcode;
05834       if (delayreject) {
05835          if (iaxs[callno]->authid > -1)
05836             ast_sched_del(sched, iaxs[callno]->authid);
05837          iaxs[callno]->authid = ast_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
05838       } else
05839          auth_reject((void *)(long)callno);
05840    }
05841    ast_mutex_unlock(&iaxsl[callno]);
05842    return 0;
05843 }

static int auth_reject ( void *  data  )  [static]

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

05814 {
05815    int callno = (int)(long)(data);
05816    ast_mutex_lock(&iaxsl[callno]);
05817    if (iaxs[callno])
05818       iaxs[callno]->authid = -1;
05819    ast_mutex_unlock(&iaxsl[callno]);
05820 #ifdef SCHED_MULTITHREADED
05821    if (schedule_action(__auth_reject, data))
05822 #endif      
05823       __auth_reject(data);
05824    return 0;
05825 }

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

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

05123 {
05124    int res = -1;
05125    int x;
05126    if (!ast_strlen_zero(keyn)) {
05127       if (!(authmethods & IAX_AUTH_RSA)) {
05128          if (ast_strlen_zero(secret)) 
05129             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));
05130       } else if (ast_strlen_zero(challenge)) {
05131          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05132       } else {
05133          char sig[256];
05134          struct ast_key *key;
05135          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05136          if (!key) {
05137             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05138          } else {
05139             if (ast_sign(key, (char*)challenge, sig)) {
05140                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05141                res = -1;
05142             } else {
05143                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05144                res = 0;
05145             }
05146          }
05147       }
05148    } 
05149    /* Fall back */
05150    if (res && !ast_strlen_zero(secret)) {
05151       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05152          struct MD5Context md5;
05153          unsigned char digest[16];
05154          char digres[128];
05155          MD5Init(&md5);
05156          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05157          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05158          MD5Final(digest, &md5);
05159          /* If they support md5, authenticate with it.  */
05160          for (x=0;x<16;x++)
05161             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05162          if (ecx && dcx)
05163             build_enc_keys(digest, ecx, dcx);
05164          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05165          res = 0;
05166       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05167          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05168          res = 0;
05169       } else
05170          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05171    }
05172    return res;
05173 }

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 5175 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(), destroy_peer(), IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, IAX_TEMPONLY, ies, iax2_peer::mask, merge_encryption(), realtime_peer(), and send_command().

Referenced by socket_process().

05176 {
05177    struct iax2_peer *peer = NULL;
05178    /* Start pessimistic */
05179    int res = -1;
05180    int authmethods = 0;
05181    struct iax_ie_data ied;
05182    
05183    memset(&ied, 0, sizeof(ied));
05184    
05185    if (ies->username)
05186       ast_string_field_set(p, username, ies->username);
05187    if (ies->challenge)
05188       ast_string_field_set(p, challenge, ies->challenge);
05189    if (ies->authmethods)
05190       authmethods = ies->authmethods;
05191    if (authmethods & IAX_AUTH_MD5)
05192       merge_encryption(p, ies->encmethods);
05193    else
05194       p->encmethods = 0;
05195 
05196    /* Check for override RSA authentication first */
05197    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05198       /* Normal password authentication */
05199       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05200    } else {
05201       AST_LIST_LOCK(&peers);
05202       AST_LIST_TRAVERSE(&peers, peer, entry) {
05203          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05204              /* No peer specified at our end, or this is the peer */
05205              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05206              /* No username specified in peer rule, or this is the right username */
05207              && (!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)))
05208              /* No specified host, or this is our host */
05209             ) {
05210             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05211             if (!res)
05212                break;   
05213          }
05214       }
05215       AST_LIST_UNLOCK(&peers);
05216       if (!peer) {
05217          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05218             that we're trying to authenticate *to* a realtime peer */
05219          if ((peer = realtime_peer(p->peer, NULL))) {
05220             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05221             if (ast_test_flag(peer, IAX_TEMPONLY))
05222                destroy_peer(peer);
05223          }
05224       }
05225    }
05226    if (ies->encmethods)
05227       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05228    if (!res)
05229       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05230    return res;
05231 }

static int authenticate_request ( struct chan_iax2_pvt p  )  [static]

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

Referenced by socket_process().

04848 {
04849    struct iax2_user *user = NULL;
04850    struct iax_ie_data ied;
04851    int res = -1, authreq_restrict = 0;
04852    char challenge[10];
04853 
04854    memset(&ied, 0, sizeof(ied));
04855 
04856    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
04857    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
04858       AST_LIST_LOCK(&users);
04859       AST_LIST_TRAVERSE(&users, user, entry) {
04860          if (!strcmp(user->name, p->username)) {
04861             if (user->curauthreq == user->maxauthreq)
04862                authreq_restrict = 1;
04863             else
04864                user->curauthreq++;
04865             break;
04866          }
04867       }
04868       AST_LIST_UNLOCK(&users);
04869    }
04870 
04871    /* If the AUTHREQ limit test failed, send back an error */
04872    if (authreq_restrict) {
04873       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
04874       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
04875       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
04876       return 0;
04877    }
04878 
04879    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
04880    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
04881       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
04882       ast_string_field_set(p, challenge, challenge);
04883       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
04884       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
04885    }
04886    if (p->encmethods)
04887       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
04888 
04889    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
04890 
04891    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
04892 
04893    if (p->encmethods)
04894       ast_set_flag(p, IAX_ENCRYPTED);
04895 
04896    return res;
04897 }

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

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

Referenced by socket_process().

04900 {
04901    char requeststr[256];
04902    char md5secret[256] = "";
04903    char secret[256] = "";
04904    char rsasecret[256] = "";
04905    int res = -1; 
04906    int x;
04907    struct iax2_user *user = NULL;
04908 
04909    AST_LIST_LOCK(&users);
04910    AST_LIST_TRAVERSE(&users, user, entry) {
04911       if (!strcmp(user->name, p->username))
04912          break;
04913    }
04914    if (user) {
04915       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
04916          user->curauthreq--;
04917          ast_clear_flag(p, IAX_MAXAUTHREQ);
04918       }
04919       ast_string_field_set(p, host, user->name);
04920    }
04921    AST_LIST_UNLOCK(&users);
04922 
04923    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
04924       return res;
04925    if (ies->password)
04926       ast_copy_string(secret, ies->password, sizeof(secret));
04927    if (ies->md5_result)
04928       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
04929    if (ies->rsa_result)
04930       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
04931    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
04932       struct ast_key *key;
04933       char *keyn;
04934       char tmpkey[256];
04935       char *stringp=NULL;
04936       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
04937       stringp=tmpkey;
04938       keyn = strsep(&stringp, ":");
04939       while(keyn) {
04940          key = ast_key_get(keyn, AST_KEY_PUBLIC);
04941          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
04942             res = 0;
04943             break;
04944          } else if (!key)
04945             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
04946          keyn = strsep(&stringp, ":");
04947       }
04948    } else if (p->authmethods & IAX_AUTH_MD5) {
04949       struct MD5Context md5;
04950       unsigned char digest[16];
04951       char *tmppw, *stringp;
04952       
04953       tmppw = ast_strdupa(p->secret);
04954       stringp = tmppw;
04955       while((tmppw = strsep(&stringp, ";"))) {
04956          MD5Init(&md5);
04957          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
04958          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04959          MD5Final(digest, &md5);
04960          /* If they support md5, authenticate with it.  */
04961          for (x=0;x<16;x++)
04962             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
04963          if (!strcasecmp(requeststr, md5secret)) {
04964             res = 0;
04965             break;
04966          }
04967       }
04968    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
04969       if (!strcmp(secret, p->secret))
04970          res = 0;
04971    }
04972    return res;
04973 }

static int auto_congest ( void *  data  )  [static]

Definition at line 2725 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

02726 {
02727 #ifdef SCHED_MULTITHREADED
02728    if (schedule_action(__auto_congest, data))
02729 #endif      
02730       __auto_congest(data);
02731    return 0;
02732 }

static int auto_hangup ( void *  data  )  [static]

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

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

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

Definition at line 8255 of file chan_iax2.c.

References ast_calloc.

Referenced by build_user().

08256 {
08257    struct iax2_context *con;
08258 
08259    if ((con = ast_calloc(1, sizeof(*con))))
08260       ast_copy_string(con->context, context, sizeof(con->context));
08261    
08262    return con;
08263 }

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

Definition at line 3659 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

03660 {
03661    aes_encrypt_key128(digest, ecx);
03662    aes_decrypt_key128(digest, dcx);
03663 }

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

Create peer structure based on configuration.

Definition at line 8380 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, free, get_auth_methods(), get_encrypt_methods(), globalflags, iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_set_srcaddr(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_peer::prefs, prefs, sched, iax2_peer::smoothing, and ast_variable::value.

08381 {
08382    struct iax2_peer *peer = NULL;
08383    struct ast_ha *oldha = NULL;
08384    int maskfound=0;
08385    int found=0;
08386    int firstpass=1;
08387 
08388    AST_LIST_LOCK(&peers);
08389    if (!temponly) {
08390       AST_LIST_TRAVERSE(&peers, peer, entry) {
08391          if (!strcmp(peer->name, name)) { 
08392             if (!ast_test_flag(peer, IAX_DELME))
08393                firstpass = 0;
08394             break;
08395          }
08396       }
08397    } else
08398       peer = NULL;   
08399    if (peer) {
08400       found++;
08401       if (firstpass) {
08402          oldha = peer->ha;
08403          peer->ha = NULL;
08404       }
08405       AST_LIST_REMOVE(&peers, peer, entry);
08406       AST_LIST_UNLOCK(&peers);
08407    } else {
08408       AST_LIST_UNLOCK(&peers);
08409       if ((peer = ast_calloc(1, sizeof(*peer)))) {
08410          peer->expire = -1;
08411          peer->pokeexpire = -1;
08412          peer->sockfd = defaultsockfd;
08413          if (ast_string_field_init(peer, 32)) {
08414             free(peer);
08415             peer = NULL;
08416          }
08417       }
08418    }
08419    if (peer) {
08420       if (firstpass) {
08421          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08422          peer->encmethods = iax2_encryption;
08423          peer->adsi = adsi;
08424          ast_string_field_set(peer,secret,"");
08425          if (!found) {
08426             ast_string_field_set(peer, name, name);
08427             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
08428             peer->expiry = min_reg_expire;
08429          }
08430          peer->prefs = prefs;
08431          peer->capability = iax2_capability;
08432          peer->smoothing = 0;
08433          peer->pokefreqok = DEFAULT_FREQ_OK;
08434          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
08435          ast_string_field_set(peer,context,"");
08436          ast_string_field_set(peer,peercontext,"");
08437          ast_clear_flag(peer, IAX_HASCALLERID);
08438          ast_string_field_set(peer, cid_name, "");
08439          ast_string_field_set(peer, cid_num, "");
08440       }
08441 
08442       if (!v) {
08443          v = alt;
08444          alt = NULL;
08445       }
08446       while(v) {
08447          if (!strcasecmp(v->name, "secret")) {
08448             ast_string_field_set(peer, secret, v->value);
08449          } else if (!strcasecmp(v->name, "mailbox")) {
08450             ast_string_field_set(peer, mailbox, v->value);
08451          } else if (!strcasecmp(v->name, "mohinterpret")) {
08452             ast_string_field_set(peer, mohinterpret, v->value);
08453          } else if (!strcasecmp(v->name, "mohsuggest")) {
08454             ast_string_field_set(peer, mohsuggest, v->value);
08455          } else if (!strcasecmp(v->name, "dbsecret")) {
08456             ast_string_field_set(peer, dbsecret, v->value);
08457          } else if (!strcasecmp(v->name, "trunk")) {
08458             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
08459             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
08460                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name);
08461                ast_clear_flag(peer, IAX_TRUNK);
08462             }
08463          } else if (!strcasecmp(v->name, "auth")) {
08464             peer->authmethods = get_auth_methods(v->value);
08465          } else if (!strcasecmp(v->name, "encryption")) {
08466             peer->encmethods = get_encrypt_methods(v->value);
08467          } else if (!strcasecmp(v->name, "notransfer")) {
08468             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
08469             ast_clear_flag(peer, IAX_TRANSFERMEDIA);  
08470             ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 
08471          } else if (!strcasecmp(v->name, "transfer")) {
08472             if (!strcasecmp(v->value, "mediaonly")) {
08473                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
08474             } else if (ast_true(v->value)) {
08475                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
08476             } else 
08477                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
08478          } else if (!strcasecmp(v->name, "jitterbuffer")) {
08479             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
08480          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
08481             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
08482          } else if (!strcasecmp(v->name, "host")) {
08483             if (!strcasecmp(v->value, "dynamic")) {
08484                /* They'll register with us */
08485                ast_set_flag(peer, IAX_DYNAMIC); 
08486                if (!found) {
08487                   /* Initialize stuff iff we're not found, otherwise
08488                      we keep going with what we had */
08489                   memset(&peer->addr.sin_addr, 0, 4);
08490                   if (peer->addr.sin_port) {
08491                      /* If we've already got a port, make it the default rather than absolute */
08492                      peer->defaddr.sin_port = peer->addr.sin_port;
08493                      peer->addr.sin_port = 0;
08494                   }
08495                }
08496             } else {
08497                /* Non-dynamic.  Make sure we become that way if we're not */
08498                if (peer->expire > -1)
08499                   ast_sched_del(sched, peer->expire);
08500                peer->expire = -1;
08501                ast_clear_flag(peer, IAX_DYNAMIC);
08502                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) {
08503                   ast_string_field_free_pools(peer);
08504                   free(peer);
08505                   return NULL;
08506                }
08507                if (!peer->addr.sin_port)
08508                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
08509             }
08510             if (!maskfound)
08511                inet_aton("255.255.255.255", &peer->mask);
08512          } else if (!strcasecmp(v->name, "defaultip")) {
08513             if (ast_get_ip(&peer->defaddr, v->value)) {
08514                ast_string_field_free_pools(peer);
08515                free(peer);
08516                return NULL;
08517             }
08518          } else if (!strcasecmp(v->name, "sourceaddress")) {
08519             peer_set_srcaddr(peer, v->value);
08520          } else if (!strcasecmp(v->name, "permit") ||
08521                   !strcasecmp(v->name, "deny")) {
08522             peer->ha = ast_append_ha(v->name, v->value, peer->ha);
08523          } else if (!strcasecmp(v->name, "mask")) {
08524             maskfound++;
08525             inet_aton(v->value, &peer->mask);
08526          } else if (!strcasecmp(v->name, "context")) {
08527             ast_string_field_set(peer, context, v->value);
08528          } else if (!strcasecmp(v->name, "regexten")) {
08529             ast_string_field_set(peer, regexten, v->value);
08530          } else if (!strcasecmp(v->name, "peercontext")) {
08531             ast_string_field_set(peer, peercontext, v->value);
08532          } else if (!strcasecmp(v->name, "port")) {
08533             if (ast_test_flag(peer, IAX_DYNAMIC))
08534                peer->defaddr.sin_port = htons(atoi(v->value));
08535             else
08536                peer->addr.sin_port = htons(atoi(v->value));
08537          } else if (!strcasecmp(v->name, "username")) {
08538             ast_string_field_set(peer, username, v->value);
08539          } else if (!strcasecmp(v->name, "allow")) {
08540             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
08541          } else if (!strcasecmp(v->name, "disallow")) {
08542             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
08543          } else if (!strcasecmp(v->name, "callerid")) {
08544             if (!ast_strlen_zero(v->value)) {
08545                char name2[80];
08546                char num2[80];
08547                ast_callerid_split(v->value, name2, 80, num2, 80);
08548                ast_string_field_set(peer, cid_name, name2);
08549                ast_string_field_set(peer, cid_num, num2);
08550                ast_set_flag(peer, IAX_HASCALLERID);
08551             } else {
08552                ast_clear_flag(peer, IAX_HASCALLERID);
08553                ast_string_field_set(peer, cid_name, "");
08554                ast_string_field_set(peer, cid_num, "");
08555             }
08556          } else if (!strcasecmp(v->name, "fullname")) {
08557             if (!ast_strlen_zero(v->value)) {
08558                ast_string_field_set(peer, cid_name, v->value);
08559                ast_set_flag(peer, IAX_HASCALLERID);
08560             } else {
08561                ast_string_field_set(peer, cid_name, "");
08562                if (ast_strlen_zero(peer->cid_num))
08563                   ast_clear_flag(peer, IAX_HASCALLERID);
08564             }
08565          } else if (!strcasecmp(v->name, "cid_number")) {
08566             if (!ast_strlen_zero(v->value)) {
08567                ast_string_field_set(peer, cid_num, v->value);
08568                ast_set_flag(peer, IAX_HASCALLERID);
08569             } else {
08570                ast_string_field_set(peer, cid_num, "");
08571                if (ast_strlen_zero(peer->cid_name))
08572                   ast_clear_flag(peer, IAX_HASCALLERID);
08573             }
08574          } else if (!strcasecmp(v->name, "sendani")) {
08575             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
08576          } else if (!strcasecmp(v->name, "inkeys")) {
08577             ast_string_field_set(peer, inkeys, v->value);
08578          } else if (!strcasecmp(v->name, "outkey")) {
08579             ast_string_field_set(peer, outkey, v->value);
08580          } else if (!strcasecmp(v->name, "qualify")) {
08581             if (!strcasecmp(v->value, "no")) {
08582                peer->maxms = 0;
08583             } else if (!strcasecmp(v->value, "yes")) {
08584                peer->maxms = DEFAULT_MAXMS;
08585             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
08586                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);
08587                peer->maxms = 0;
08588             }
08589          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
08590             peer->smoothing = ast_true(v->value);
08591          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
08592             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
08593                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);
08594             }
08595          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
08596             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
08597                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);
08598             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
08599          } else if (!strcasecmp(v->name, "timezone")) {
08600             ast_string_field_set(peer, zonetag, v->value);
08601          } else if (!strcasecmp(v->name, "adsi")) {
08602             peer->adsi = ast_true(v->value);
08603          }/* else if (strcasecmp(v->name,"type")) */
08604          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
08605          v = v->next;
08606          if (!v) {
08607             v = alt;
08608             alt = NULL;
08609          }
08610       }
08611       if (!peer->authmethods)
08612          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
08613       ast_clear_flag(peer, IAX_DELME); 
08614       /* Make sure these are IPv4 addresses */
08615       peer->addr.sin_family = AF_INET;
08616    }
08617    if (oldha)
08618       ast_free_ha(oldha);
08619    return peer;
08620 }

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

Create in-memory user structure from configuration.

Definition at line 8623 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(), globalflags, iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_user::prefs, prefs, ast_variable::value, and iax2_user::vars.

08624 {
08625    struct iax2_user *user = NULL;
08626    struct iax2_context *con, *conl = NULL;
08627    struct ast_ha *oldha = NULL;
08628    struct iax2_context *oldcon = NULL;
08629    int format;
08630    int firstpass=1;
08631    int oldcurauthreq = 0;
08632    char *varname = NULL, *varval = NULL;
08633    struct ast_variable *tmpvar = NULL;
08634    
08635    AST_LIST_LOCK(&users);
08636    if (!temponly) {
08637       AST_LIST_TRAVERSE(&users, user, entry) {
08638          if (!strcmp(user->name, name)) { 
08639             if (!ast_test_flag(user, IAX_DELME))
08640                firstpass = 0;
08641             break;
08642          }
08643       }
08644    } else
08645       user = NULL;
08646 
08647    if (user) {
08648       if (firstpass) {
08649          oldcurauthreq = user->curauthreq;
08650          oldha = user->ha;
08651          oldcon = user->contexts;
08652          user->ha = NULL;
08653          user->contexts = NULL;
08654       }
08655       /* Already in the list, remove it and it will be added back (or FREE'd) */
08656       AST_LIST_REMOVE(&users, user, entry);
08657       AST_LIST_UNLOCK(&users);
08658    } else {
08659       AST_LIST_UNLOCK(&users);
08660       /* This is going to memset'd to 0 in the next block */
08661       user = ast_calloc(sizeof(*user),1);
08662    }
08663    
08664    if (user) {
08665       if (firstpass) {
08666          ast_string_field_free_pools(user);
08667          memset(user, 0, sizeof(struct iax2_user));
08668          if (ast_string_field_init(user, 32)) {
08669             free(user);
08670             user = NULL;
08671          }
08672          user->maxauthreq = maxauthreq;
08673          user->curauthreq = oldcurauthreq;
08674          user->prefs = prefs;
08675          user->capability = iax2_capability;
08676          user->encmethods = iax2_encryption;
08677          user->adsi = adsi;
08678          ast_string_field_set(user, name, name);
08679          ast_string_field_set(user, language, language);
08680          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
08681          ast_clear_flag(user, IAX_HASCALLERID);
08682          ast_string_field_set(user, cid_name, "");
08683          ast_string_field_set(user, cid_num, "");
08684       }
08685       if (!v) {
08686          v = alt;
08687          alt = NULL;
08688       }
08689       while(v) {
08690          if (!strcasecmp(v->name, "context")) {
08691             con = build_context(v->value);
08692             if (con) {
08693                if (conl)
08694                   conl->next = con;
08695                else
08696                   user->contexts = con;
08697                conl = con;
08698             }
08699          } else if (!strcasecmp(v->name, "permit") ||
08700                   !strcasecmp(v->name, "deny")) {
08701             user->ha = ast_append_ha(v->name, v->value, user->ha);
08702          } else if (!strcasecmp(v->name, "setvar")) {
08703             varname = ast_strdupa(v->value);
08704             if (varname && (varval = strchr(varname,'='))) {
08705                *varval = '\0';
08706                varval++;
08707                if((tmpvar = ast_variable_new(varname, varval))) {
08708                   tmpvar->next = user->vars; 
08709                   user->vars = tmpvar;
08710                }
08711             }
08712          } else if (!strcasecmp(v->name, "allow")) {
08713             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
08714          } else if (!strcasecmp(v->name, "disallow")) {
08715             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
08716          } else if (!strcasecmp(v->name, "trunk")) {
08717             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
08718             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
08719                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name);
08720                ast_clear_flag(user, IAX_TRUNK);
08721             }
08722          } else if (!strcasecmp(v->name, "auth")) {
08723             user->authmethods = get_auth_methods(v->value);
08724          } else if (!strcasecmp(v->name, "encryption")) {
08725             user->encmethods = get_encrypt_methods(v->value);
08726          } else if (!strcasecmp(v->name, "notransfer")) {
08727             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
08728             ast_clear_flag(user, IAX_TRANSFERMEDIA);  
08729             ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 
08730          } else if (!strcasecmp(v->name, "transfer")) {
08731             if (!strcasecmp(v->value, "mediaonly")) {
08732                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
08733             } else if (ast_true(v->value)) {
08734                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
08735             } else 
08736                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
08737          } else if (!strcasecmp(v->name, "codecpriority")) {
08738             if(!strcasecmp(v->value, "caller"))
08739                ast_set_flag(user, IAX_CODEC_USER_FIRST);
08740             else if(!strcasecmp(v->value, "disabled"))
08741                ast_set_flag(user, IAX_CODEC_NOPREFS);
08742             else if(!strcasecmp(v->value, "reqonly")) {
08743                ast_set_flag(user, IAX_CODEC_NOCAP);
08744                ast_set_flag(user, IAX_CODEC_NOPREFS);
08745             }
08746          } else if (!strcasecmp(v->name, "jitterbuffer")) {
08747             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
08748          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
08749             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
08750          } else if (!strcasecmp(v->name, "dbsecret")) {
08751             ast_string_field_set(user, dbsecret, v->value);
08752          } else if (!strcasecmp(v->name, "secret")) {
08753             if (!ast_strlen_zero(user->secret)) {
08754                char *old = ast_strdupa(user->secret);
08755 
08756                ast_string_field_build(user, secret, "%s;%s", old, v->value);
08757             } else
08758                ast_string_field_set(user, secret, v->value);
08759          } else if (!strcasecmp(v->name, "callerid")) {
08760             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
08761                char name2[80];
08762                char num2[80];
08763                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
08764                ast_string_field_set(user, cid_name, name2);
08765                ast_string_field_set(user, cid_num, num2);
08766                ast_set_flag(user, IAX_HASCALLERID);
08767             } else {
08768                ast_clear_flag(user, IAX_HASCALLERID);
08769                ast_string_field_set(user, cid_name, "");
08770                ast_string_field_set(user, cid_num, "");
08771             }
08772          } else if (!strcasecmp(v->name, "fullname")) {
08773             if (!ast_strlen_zero(v->value)) {
08774                ast_string_field_set(user, cid_name, v->value);
08775                ast_set_flag(user, IAX_HASCALLERID);
08776             } else {
08777                ast_string_field_set(user, cid_name, "");
08778                if (ast_strlen_zero(user->cid_num))
08779                   ast_clear_flag(user, IAX_HASCALLERID);
08780             }
08781          } else if (!strcasecmp(v->name, "cid_number")) {
08782             if (!ast_strlen_zero(v->value)) {
08783                ast_string_field_set(user, cid_num, v->value);
08784                ast_set_flag(user, IAX_HASCALLERID);
08785             } else {
08786                ast_string_field_set(user, cid_num, "");
08787                if (ast_strlen_zero(user->cid_name))
08788                   ast_clear_flag(user, IAX_HASCALLERID);
08789             }
08790          } else if (!strcasecmp(v->name, "accountcode")) {
08791             ast_string_field_set(user, accountcode, v->value);
08792          } else if (!strcasecmp(v->name, "mohinterpret")) {
08793             ast_string_field_set(user, mohinterpret, v->value);
08794          } else if (!strcasecmp(v->name, "mohsuggest")) {
08795             ast_string_field_set(user, mohsuggest, v->value);
08796          } else if (!strcasecmp(v->name, "language")) {
08797             ast_string_field_set(user, language, v->value);
08798          } else if (!strcasecmp(v->name, "amaflags")) {
08799             format = ast_cdr_amaflags2int(v->value);
08800             if (format < 0) {
08801                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
08802             } else {
08803                user->amaflags = format;
08804             }
08805          } else if (!strcasecmp(v->name, "inkeys")) {
08806             ast_string_field_set(user, inkeys, v->value);
08807          } else if (!strcasecmp(v->name, "maxauthreq")) {
08808             user->maxauthreq = atoi(v->value);
08809             if (user->maxauthreq < 0)
08810                user->maxauthreq = 0;
08811          } else if (!strcasecmp(v->name, "adsi")) {
08812             user->adsi = ast_true(v->value);
08813          }/* else if (strcasecmp(v->name,"type")) */
08814          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
08815          v = v->next;
08816          if (!v) {
08817             v = alt;
08818             alt = NULL;
08819          }
08820       }
08821       if (!user->authmethods) {
08822          if (!ast_strlen_zero(user->secret)) {
08823             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
08824             if (!ast_strlen_zero(user->inkeys))
08825                user->authmethods |= IAX_AUTH_RSA;
08826          } else if (!ast_strlen_zero(user->inkeys)) {
08827             user->authmethods = IAX_AUTH_RSA;
08828          } else {
08829             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
08830          }
08831       }
08832       ast_clear_flag(user, IAX_DELME);
08833    }
08834    if (oldha)
08835       ast_free_ha(oldha);
08836    if (oldcon)
08837       free_context(oldcon);
08838    return user;
08839 }

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

Definition at line 9363 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, chan_iax2_pvt::capability, create_addr(), find_callno(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, iaxs, iaxsl, LOG_WARNING, NEW_FORCE, parse_dial_string(), and send_command().

Referenced by find_cache().

09364 {
09365    struct sockaddr_in sin;
09366    int x;
09367    int callno;
09368    struct iax_ie_data ied;
09369    struct create_addr_info cai;
09370    struct parsed_dial_string pds;
09371    char *tmpstr;
09372 
09373    for (x=0; x<IAX_MAX_CALLS; x++) {
09374       /* Look for an *exact match* call.  Once a call is negotiated, it can only
09375          look up entries for a single context */
09376       if (!ast_mutex_trylock(&iaxsl[x])) {
09377          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
09378             return x;
09379          ast_mutex_unlock(&iaxsl[x]);
09380       }
09381    }
09382 
09383    /* No match found, we need to create a new one */
09384 
09385    memset(&cai, 0, sizeof(cai));
09386    memset(&ied, 0, sizeof(ied));
09387    memset(&pds, 0, sizeof(pds));
09388 
09389    tmpstr = ast_strdupa(data);
09390    parse_dial_string(tmpstr, &pds);
09391 
09392    /* Populate our address from the given */
09393    if (create_addr(pds.peer, &sin, &cai))
09394       return -1;
09395 
09396    ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
09397       pds.peer, pds.username, pds.password, pds.context);
09398 
09399    callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd);
09400    if (callno < 1) {
09401       ast_log(LOG_WARNING, "Unable to create call\n");
09402       return -1;
09403    }
09404 
09405    ast_mutex_lock(&iaxsl[callno]);
09406    ast_string_field_set(iaxs[callno], dproot, data);
09407    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
09408 
09409    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
09410    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
09411    /* the string format is slightly different from a standard dial string,
09412       because the context appears in the 'exten' position
09413    */
09414    if (pds.exten)
09415       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
09416    if (pds.username)
09417       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
09418    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
09419    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
09420    /* Keep password handy */
09421    if (pds.password)
09422       ast_string_field_set(iaxs[callno], secret, pds.password);
09423    if (pds.key)
09424       ast_string_field_set(iaxs[callno], outkey, pds.key);
09425    /* Start the call going */
09426    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
09427 
09428    return callno;
09429 }

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

Definition at line 3529 of file chan_iax2.c.

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

03530 {
03531    /* Returns where in "receive time" we are.  That is, how many ms
03532       since we received (or would have received) the frame with timestamp 0 */
03533    int ms;
03534 #ifdef IAXTESTS
03535    int jit;
03536 #endif /* IAXTESTS */
03537    /* Setup rxcore if necessary */
03538    if (ast_tvzero(p->rxcore)) {
03539       p->rxcore = ast_tvnow();
03540       if (option_debug && iaxdebug)
03541          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
03542                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
03543       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
03544 #if 1
03545       if (option_debug && iaxdebug)
03546          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
03547                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
03548 #endif
03549    }
03550 
03551    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
03552 #ifdef IAXTESTS
03553    if (test_jit) {
03554       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
03555          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
03556          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
03557             jit = -jit;
03558          ms += jit;
03559       }
03560    }
03561    if (test_late) {
03562       ms += test_late;
03563       test_late = 0;
03564    }
03565 #endif /* IAXTESTS */
03566    return ms;
03567 }

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

Definition at line 3411 of file chan_iax2.c.

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

Referenced by iax2_send(), and socket_process().

03412 {
03413    int ms;
03414    int voice = 0;
03415    int genuine = 0;
03416    int adjust;
03417    struct timeval *delivery = NULL;
03418 
03419 
03420    /* What sort of frame do we have?: voice is self-explanatory
03421       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
03422       non-genuine frames are CONTROL frames [ringing etc], DTMF
03423       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
03424       the others need a timestamp slaved to the voice frames so that they go in sequence
03425    */
03426    if (f) {
03427       if (f->frametype == AST_FRAME_VOICE) {
03428          voice = 1;
03429          delivery = &f->delivery;
03430       } else if (f->frametype == AST_FRAME_IAX) {
03431          genuine = 1;
03432       } else if (f->frametype == AST_FRAME_CNG) {
03433          p->notsilenttx = 0;  
03434       }
03435    }
03436    if (ast_tvzero(p->offset)) {
03437       gettimeofday(&p->offset, NULL);
03438       /* Round to nearest 20ms for nice looking traces */
03439       p->offset.tv_usec -= p->offset.tv_usec % 20000;
03440    }
03441    /* If the timestamp is specified, just send it as is */
03442    if (ts)
03443       return ts;
03444    /* If we have a time that the frame arrived, always use it to make our timestamp */
03445    if (delivery && !ast_tvzero(*delivery)) {
03446       ms = ast_tvdiff_ms(*delivery, p->offset);
03447       if (option_debug > 2 && iaxdebug)
03448          ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
03449    } else {
03450       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
03451       if (ms < 0)
03452          ms = 0;
03453       if (voice) {
03454          /* On a voice frame, use predicted values if appropriate */
03455          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
03456             /* Adjust our txcore, keeping voice and non-voice synchronized */
03457             /* AN EXPLANATION:
03458                When we send voice, we usually send "calculated" timestamps worked out
03459                on the basis of the number of samples sent. When we send other frames,
03460                we usually send timestamps worked out from the real clock.
03461                The problem is that they can tend to drift out of step because the 
03462                   source channel's clock and our clock may not be exactly at the same rate.
03463                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
03464                for this call.  Moving it adjusts timestamps for non-voice frames.
03465                We make the adjustment in the style of a moving average.  Each time we
03466                adjust p->offset by 10% of the difference between our clock-derived
03467                timestamp and the predicted timestamp.  That's why you see "10000"
03468                below even though IAX2 timestamps are in milliseconds.
03469                The use of a moving average avoids offset moving too radically.
03470                Generally, "adjust" roams back and forth around 0, with offset hardly
03471                changing at all.  But if a consistent different starts to develop it
03472                will be eliminated over the course of 10 frames (200-300msecs) 
03473             */
03474             adjust = (ms - p->nextpred);
03475             if (adjust < 0)
03476                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
03477             else if (adjust > 0)
03478                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
03479 
03480             if (!p->nextpred) {
03481                p->nextpred = ms; /*f->samples / 8;*/
03482                if (p->nextpred <= p->lastsent)
03483                   p->nextpred = p->lastsent + 3;
03484             }
03485             ms = p->nextpred;
03486          } else {
03487                 /* in this case, just use the actual
03488             * time, since we're either way off
03489             * (shouldn't happen), or we're  ending a
03490             * silent period -- and seed the next
03491             * predicted time.  Also, round ms to the
03492             * next multiple of frame size (so our
03493             * silent periods are multiples of
03494             * frame size too) */
03495 
03496             if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
03497                ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
03498                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
03499 
03500             if (f->samples >= 8) /* check to make sure we dont core dump */
03501             {
03502                int diff = ms % (f->samples / 8);
03503                if (diff)
03504                    ms += f->samples/8 - diff;
03505             }
03506 
03507             p->nextpred = ms;
03508             p->notsilenttx = 1;
03509          }
03510       } else {
03511          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
03512             it's a genuine frame */
03513          if (genuine) {
03514             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
03515             if (ms <= p->lastsent)
03516                ms = p->lastsent + 3;
03517          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
03518             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
03519             ms = p->lastsent + 3;
03520          }
03521       }
03522    }
03523    p->lastsent = ms;
03524    if (voice)
03525       p->nextpred = p->nextpred + f->samples / 8;
03526    return ms;
03527 }

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

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

03368 {
03369    unsigned long int mssincetx; /* unsigned to handle overflows */
03370    long int ms, pred;
03371 
03372    tpeer->trunkact = *tv;
03373    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03374    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03375       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03376       tpeer->txtrunktime = *tv;
03377       tpeer->lastsent = 999999;
03378    }
03379    /* Update last transmit time now */
03380    tpeer->lasttxtime = *tv;
03381    
03382    /* Calculate ms offset */
03383    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03384    /* Predict from last value */
03385    pred = tpeer->lastsent + sampms;
03386    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03387       ms = pred;
03388    
03389    /* We never send the same timestamp twice, so fudge a little if we must */
03390    if (ms == tpeer->lastsent)
03391       ms = tpeer->lastsent + 1;
03392    tpeer->lastsent = ms;
03393    return ms;
03394 }

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

Definition at line 4615 of file chan_iax2.c.

References iax2_user::adsi, chan_iax2_pvt::adsi, 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, chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, cid_name, cid_num, iax2_context::context, iax2_user::contexts, destroy_user(), iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax2_user::ha, iax2_getpeertrunk(), IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TEMPONLY, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, ies, key(), LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, chan_iax2_pvt::peeradsicpe, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_user::prefs, chan_iax2_pvt::prefs, prefs, realtime_user(), ast_variable::value, chan_iax2_pvt::vars, and iax2_user::vars.

Referenced by socket_process().

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

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

Definition at line 6210 of file chan_iax2.c.

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

Referenced by socket_process().

06211 {
06212    unsigned int ourver;
06213    char rsi[80];
06214    snprintf(rsi, sizeof(rsi), "si-%s", si);
06215    if (iax_provision_version(&ourver, rsi, 1))
06216       return 0;
06217    if (option_debug)
06218       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06219    if (ourver != ver) 
06220       iax2_provision(sin, sockfd, NULL, rsi, 1);
06221    return 0;
06222 }

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

References ast_log(), and LOG_ERROR.

Referenced by peer_set_srcaddr().

08282 {
08283    int sd;
08284    int res;
08285    
08286    sd = socket(AF_INET, SOCK_DGRAM, 0);
08287    if (sd < 0) {
08288       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
08289       return -1;
08290    }
08291 
08292    res = bind(sd, sa, salen);
08293    if (res < 0) {
08294       ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
08295       close(sd);
08296       return 1;
08297    }
08298 
08299    close(sd);
08300    return 0;
08301 }

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

Definition at line 5280 of file chan_iax2.c.

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

Referenced by socket_process().

05281 {
05282    char exten[256] = "";
05283    int status = CACHE_FLAG_UNKNOWN;
05284    int expiry = iaxdefaultdpcache;
05285    int x;
05286    int matchmore = 0;
05287    struct iax2_dpcache *dp, *prev;
05288    
05289    if (ies->called_number)
05290       ast_copy_string(exten, ies->called_number, sizeof(exten));
05291 
05292    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05293       status = CACHE_FLAG_EXISTS;
05294    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05295       status = CACHE_FLAG_CANEXIST;
05296    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05297       status = CACHE_FLAG_NONEXISTENT;
05298 
05299    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05300       /* Don't really do anything with this */
05301    }
05302    if (ies->refresh)
05303       expiry = ies->refresh;
05304    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05305       matchmore = CACHE_FLAG_MATCHMORE;
05306    ast_mutex_lock(&dpcache_lock);
05307    prev = NULL;
05308    dp = pvt->dpentries;
05309    while(dp) {
05310       if (!strcmp(dp->exten, exten)) {
05311          /* Let them go */
05312          if (prev)
05313             prev->peer = dp->peer;
05314          else
05315             pvt->dpentries = dp->peer;
05316          dp->peer = NULL;
05317          dp->callno = 0;
05318          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05319          if (dp->flags & CACHE_FLAG_PENDING) {
05320             dp->flags &= ~CACHE_FLAG_PENDING;
05321             dp->flags |= status;
05322             dp->flags |= matchmore;
05323          }
05324          /* Wake up waiters */
05325          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05326             if (dp->waiters[x] > -1)
05327                write(dp->waiters[x], "asdf", 4);
05328       }
05329       prev = dp;
05330       dp = dp->peer;
05331    }
05332    ast_mutex_unlock(&dpcache_lock);
05333    return 0;
05334 }

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

Definition at line 2078 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_strdup.

02079 {
02080    int which = 0;
02081    struct iax2_peer *p = NULL;
02082    char *res = NULL;
02083    int wordlen = strlen(word);
02084 
02085    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02086    if (pos == 3) {
02087       AST_LIST_LOCK(&peers);
02088       AST_LIST_TRAVERSE(&peers, p, entry) {
02089          if (!strncasecmp(p->name, word, wordlen) && ++which > state) {
02090             res = ast_strdup(p->name);
02091             break;
02092          }
02093       }
02094       AST_LIST_UNLOCK(&peers);
02095    }
02096 
02097    return res;
02098 }

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

Definition at line 5336 of file chan_iax2.c.

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

Referenced by socket_process().

05337 {
05338    int peercallno = 0;
05339    struct chan_iax2_pvt *pvt = iaxs[callno];
05340    struct iax_frame *cur;
05341    jb_frame frame;
05342 
05343    if (ies->callno)
05344       peercallno = ies->callno;
05345 
05346    if (peercallno < 1) {
05347       ast_log(LOG_WARNING, "Invalid transfer request\n");
05348       return -1;
05349    }
05350    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05351    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05352    /* Reset sequence numbers */
05353    pvt->oseqno = 0;
05354    pvt->rseqno = 0;
05355    pvt->iseqno = 0;
05356    pvt->aseqno = 0;
05357    pvt->peercallno = peercallno;
05358    pvt->transferring = TRANSFER_NONE;
05359    pvt->svoiceformat = -1;
05360    pvt->voiceformat = 0;
05361    pvt->svideoformat = -1;
05362    pvt->videoformat = 0;
05363    pvt->transfercallno = -1;
05364    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05365    memset(&pvt->offset, 0, sizeof(pvt->offset));
05366    /* reset jitterbuffer */
05367    while(jb_getall(pvt->jb,&frame) == JB_OK)
05368       iax2_frame_free(frame.data);
05369    jb_reset(pvt->jb);
05370    pvt->lag = 0;
05371    pvt->last = 0;
05372    pvt->lastsent = 0;
05373    pvt->nextpred = 0;
05374    pvt->pingtime = DEFAULT_RETRY_TIME;
05375    AST_LIST_LOCK(&iaxq.queue);
05376    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05377       /* We must cancel any packets that would have been transmitted
05378          because now we're talking to someone new.  It's okay, they
05379          were transmitted to someone that didn't care anyway. */
05380       if (callno == cur->callno) 
05381          cur->retries = -1;
05382    }
05383    AST_LIST_UNLOCK(&iaxq.queue);
05384    return 0; 
05385 }

static unsigned char compress_subclass ( int  subclass  )  [static]

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

00970 {
00971    int x;
00972    int power=-1;
00973    /* If it's 128 or smaller, just return it */
00974    if (subclass < IAX_FLAG_SC_LOG)
00975       return subclass;
00976    /* Otherwise find its power */
00977    for (x = 0; x < IAX_MAX_SHIFT; x++) {
00978       if (subclass & (1 << x)) {
00979          if (power > -1) {
00980             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
00981             return 0;
00982          } else
00983             power = x;
00984       }
00985    }
00986    return power | IAX_FLAG_SC_LOG;
00987 }

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

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

06225 {
06226    jb_info stats;
06227    jb_getinfo(pvt->jb, &stats);
06228    
06229    memset(iep, 0, sizeof(*iep));
06230 
06231    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06232    if(stats.frames_in == 0) stats.frames_in = 1;
06233    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06234    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06235    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06236    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06237    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06238 }

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

Definition at line 2623 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ahp, ast_clear_flag, ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), 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, prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.

02624 {
02625    struct ast_hostent ahp;
02626    struct hostent *hp;
02627    struct iax2_peer *peer;
02628 
02629    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
02630    cai->sockfd = defaultsockfd;
02631    cai->maxtime = 0;
02632    sin->sin_family = AF_INET;
02633 
02634    if (!(peer = find_peer(peername, 1))) {
02635       cai->found = 0;
02636 
02637       hp = ast_gethostbyname(peername, &ahp);
02638       if (hp) {
02639          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
02640          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
02641          /* use global iax prefs for unknown peer/user */
02642          ast_codec_pref_convert(&prefs, cai->prefs, sizeof(cai->prefs), 1);
02643          return 0;
02644       } else {
02645          ast_log(LOG_WARNING, "No such host: %s\n", peername);
02646          return -1;
02647       }
02648    }
02649 
02650    cai->found = 1;
02651    
02652    /* if the peer has no address (current or default), return failure */
02653    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) {
02654       if (ast_test_flag(peer, IAX_TEMPONLY))
02655          destroy_peer(peer);
02656       return -1;
02657    }
02658 
02659    /* if the peer is being monitored and is currently unreachable, return failure */
02660    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) {
02661       if (ast_test_flag(peer, IAX_TEMPONLY))
02662          destroy_peer(peer);
02663       return -1;
02664    }
02665 
02666    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
02667    cai->maxtime = peer->maxms;
02668    cai->capability = peer->capability;
02669    cai->encmethods = peer->encmethods;
02670    cai->sockfd = peer->sockfd;
02671    cai->adsi = peer->adsi;
02672    ast_codec_pref_convert(&peer->prefs, cai->prefs, sizeof(cai->prefs), 1);
02673    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
02674    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
02675    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
02676    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
02677    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
02678    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
02679    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
02680    if (ast_strlen_zero(peer->dbsecret)) {
02681       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
02682    } else {
02683       char *family;
02684       char *key = NULL;
02685 
02686       family = ast_strdupa(peer->dbsecret);
02687       key = strchr(family, '/');
02688       if (key)
02689          *key++ = '\0';
02690       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
02691          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
02692          if (ast_test_flag(peer, IAX_TEMPONLY))
02693             destroy_peer(peer);
02694          return -1;
02695       }
02696    }
02697 
02698    if (peer->addr.sin_addr.s_addr) {
02699       sin->sin_addr = peer->addr.sin_addr;
02700       sin->sin_port = peer->addr.sin_port;
02701    } else {
02702       sin->sin_addr = peer->defaddr.sin_addr;
02703       sin->sin_port = peer->defaddr.sin_port;
02704    }
02705 
02706    if (ast_test_flag(peer, IAX_TEMPONLY))
02707       destroy_peer(peer);
02708 
02709    return 0;
02710 }

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

Definition at line 3713 of file chan_iax2.c.

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

Referenced by decrypt_frame().

03714 {
03715    int padding;
03716    unsigned char *workspace;
03717 
03718    workspace = alloca(*datalen);
03719    memset(f, 0, sizeof(*f));
03720    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
03721       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
03722       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
03723          return -1;
03724       /* Decrypt */
03725       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
03726 
03727       padding = 16 + (workspace[15] & 0xf);
03728       if (option_debug && iaxdebug)
03729          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
03730       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
03731          return -1;
03732 
03733       *datalen -= padding;
03734       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
03735       f->frametype = fh->type;
03736       if (f->frametype == AST_FRAME_VIDEO) {
03737          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
03738       } else {
03739          f->subclass = uncompress_subclass(fh->csub);
03740       }
03741    } else {
03742       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
03743       if (option_debug && iaxdebug)
03744          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
03745       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
03746          return -1;
03747       /* Decrypt */
03748       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
03749       padding = 16 + (workspace[15] & 0x0f);
03750       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
03751          return -1;
03752       *datalen -= padding;
03753       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
03754    }
03755    return 0;
03756 }

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

Definition at line 3799 of file chan_iax2.c.

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

Referenced by socket_process().

03800 {
03801    int res=-1;
03802    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
03803       /* Search for possible keys, given secrets */
03804       struct MD5Context md5;
03805       unsigned char digest[16];
03806       char *tmppw, *stringp;
03807       
03808       tmppw = ast_strdupa(iaxs[callno]->secret);
03809       stringp = tmppw;
03810       while ((tmppw = strsep(&stringp, ";"))) {
03811          MD5Init(&md5);
03812          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
03813          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
03814          MD5Final(digest, &md5);
03815          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
03816          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
03817          if (!res) {
03818             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
03819             break;
03820          }
03821       }
03822    } else 
03823       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
03824    return res;
03825 }

static void delete_users ( void   )  [static]

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

08842 {
08843    struct iax2_user *user;
08844    struct iax2_peer *peer;
08845    struct iax2_registry *reg;
08846 
08847    AST_LIST_LOCK(&users);
08848    AST_LIST_TRAVERSE(&users, user, entry)
08849       ast_set_flag(user, IAX_DELME);
08850    AST_LIST_UNLOCK(&users);
08851 
08852    AST_LIST_LOCK(&registrations);
08853    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
08854       if (reg->expire > -1)
08855          ast_sched_del(sched, reg->expire);
08856       if (reg->callno) {
08857          ast_mutex_lock(&iaxsl[reg->callno]);
08858          if (iaxs[reg->callno]) {
08859             iaxs[reg->callno]->reg = NULL;
08860             iax2_destroy(reg->callno);
08861          }
08862          ast_mutex_unlock(&iaxsl[reg->callno]);
08863       }
08864       if (reg->dnsmgr)
08865          ast_dnsmgr_release(reg->dnsmgr);
08866       free(reg);
08867    }
08868    AST_LIST_UNLOCK(&registrations);
08869 
08870    AST_LIST_LOCK(&peers);
08871    AST_LIST_TRAVERSE(&peers, peer, entry)
08872       ast_set_flag(peer, IAX_DELME);
08873    AST_LIST_UNLOCK(&peers);
08874 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1329 of file chan_iax2.c.

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

Referenced by reload_firmware().

01330 {
01331    /* Close firmware */
01332    if (cur->fwh) {
01333       munmap(cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01334    }
01335    close(cur->fd);
01336    free(cur);
01337 }

static void destroy_peer ( struct iax2_peer peer  )  [static]

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

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

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

static void destroy_user ( struct iax2_user user  )  [static]

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

08877 {
08878    ast_free_ha(user->ha);
08879    free_context(user->contexts);
08880    if(user->vars) {
08881       ast_variables_destroy(user->vars);
08882       user->vars = NULL;
08883    }
08884    ast_string_field_free_pools(user);
08885    free(user);
08886 }

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

Definition at line 6058 of file chan_iax2.c.

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

Referenced by dp_lookup_thread(), and socket_process().

06059 {
06060    unsigned short dpstatus = 0;
06061    struct iax_ie_data ied1;
06062    int mm;
06063 
06064    memset(&ied1, 0, sizeof(ied1));
06065    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06066    /* Must be started */
06067    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06068       dpstatus = IAX_DPSTATUS_EXISTS;
06069    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06070       dpstatus = IAX_DPSTATUS_CANEXIST;
06071    } else {
06072       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06073    }
06074    if (ast_ignore_pattern(context, callednum))
06075       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06076    if (mm)
06077       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06078    if (!skiplock)
06079       ast_mutex_lock(&iaxsl[callno]);
06080    if (iaxs[callno]) {
06081       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06082       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06083       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06084       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06085    }
06086    if (!skiplock)
06087       ast_mutex_unlock(&iaxsl[callno]);
06088 }

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

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

06091 {
06092    /* Look up for dpreq */
06093    struct dpreq_data *dpr = data;
06094    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06095    if (dpr->callerid)
06096       free(dpr->callerid);
06097    free(dpr);
06098    return NULL;
06099 }

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

Definition at line 3758 of file chan_iax2.c.

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

Referenced by iax2_send().

03759 {
03760    int padding;
03761    unsigned char *workspace;
03762    workspace = alloca(*datalen + 32);
03763    if (!workspace)
03764       return -1;
03765    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
03766       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
03767       if (option_debug && iaxdebug)
03768          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
03769       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
03770       padding = 16 + (padding & 0xf);
03771       memcpy(workspace, poo, padding);
03772       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
03773       workspace[15] &= 0xf0;
03774       workspace[15] |= (padding & 0xf);
03775       if (option_debug && iaxdebug)
03776          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]);
03777       *datalen += padding;
03778       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
03779       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
03780          memcpy(poo, workspace + *datalen - 32, 32);
03781    } else {
03782       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
03783       if (option_debug && iaxdebug)
03784          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
03785       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
03786       padding = 16 + (padding & 0xf);
03787       memcpy(workspace, poo, padding);
03788       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
03789       workspace[15] &= 0xf0;
03790       workspace[15] |= (padding & 0x0f);
03791       *datalen += padding;
03792       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
03793       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
03794          memcpy(poo, workspace + *datalen - 32, 32);
03795    }
03796    return 0;
03797 }

static int expire_registry ( void *  data  )  [static]

Definition at line 5559 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

05560 {
05561 #ifdef SCHED_MULTITHREADED
05562    if (schedule_action(__expire_registry, data))
05563 #endif      
05564       __expire_registry(data);
05565    return 0;
05566 }

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

Definition at line 9431 of file chan_iax2.c.

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

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

09432 {
09433    struct iax2_dpcache *dp, *prev = NULL, *next;
09434    struct timeval tv;
09435    int x;
09436    int com[2];
09437    int timeout;
09438    int old=0;
09439    int outfd;
09440    int abort;
09441    int callno;
09442    struct ast_channel *c;
09443    struct ast_frame *f;
09444    gettimeofday(&tv, NULL);
09445    dp = dpcache;
09446    while(dp) {
09447       next = dp->next;
09448       /* Expire old caches */
09449       if (ast_tvcmp(tv, dp->expiry) > 0) {
09450             /* It's expired, let it disappear */
09451             if (prev)
09452                prev->next = dp->next;
09453             else
09454                dpcache = dp->next;
09455             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
09456                /* Free memory and go again */
09457                free(dp);
09458             } else {
09459                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);
09460             }
09461             dp = next;
09462             continue;
09463       }
09464       /* We found an entry that matches us! */
09465       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
09466          break;
09467       prev = dp;
09468       dp = next;
09469    }
09470    if (!dp) {
09471       /* No matching entry.  Create a new one. */
09472       /* First, can we make a callno? */
09473       callno = cache_get_callno_locked(data);
09474       if (callno < 0) {
09475          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
09476          return NULL;
09477       }
09478       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
09479          ast_mutex_unlock(&iaxsl[callno]);
09480          return NULL;
09481       }
09482       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
09483       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
09484       gettimeofday(&dp->expiry, NULL);
09485       dp->orig = dp->expiry;
09486       /* Expires in 30 mins by default */
09487       dp->expiry.tv_sec += iaxdefaultdpcache;
09488       dp->next = dpcache;
09489       dp->flags = CACHE_FLAG_PENDING;
09490       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
09491          dp->waiters[x] = -1;
09492       dpcache = dp;
09493       dp->peer = iaxs[callno]->dpentries;
09494       iaxs[callno]->dpentries = dp;
09495       /* Send the request if we're already up */
09496       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
09497          iax2_dprequest(dp, callno);
09498       ast_mutex_unlock(&iaxsl[callno]);
09499    }
09500    /* By here we must have a dp */
09501    if (dp->flags & CACHE_FLAG_PENDING) {
09502       /* Okay, here it starts to get nasty.  We need a pipe now to wait
09503          for a reply to come back so long as it's pending */
09504       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
09505          /* Find an empty slot */
09506          if (dp->waiters[x] < 0)
09507             break;
09508       }
09509       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
09510          ast_log(LOG_WARNING, "No more waiter positions available\n");
09511          return NULL;
09512       }
09513       if (pipe(com)) {
09514          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
09515          return NULL;
09516       }
09517       dp->waiters[x] = com[1];
09518       /* Okay, now we wait */
09519       timeout = iaxdefaulttimeout * 1000;
09520       /* Temporarily unlock */
09521       ast_mutex_unlock(&dpcache_lock);
09522       /* Defer any dtmf */
09523       if (chan)
09524          old = ast_channel_defer_dtmf(chan);
09525       abort = 0;
09526       while(timeout) {
09527          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
09528          if (outfd > -1) {
09529             break;
09530          }
09531          if (c) {
09532             f = ast_read(c);
09533             if (f)
09534                ast_frfree(f);
09535             else {
09536                /* Got hung up on, abort! */
09537                break;
09538                abort = 1;
09539             }
09540          }
09541       }
09542       if (!timeout) {
09543          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
09544       }
09545       ast_mutex_lock(&dpcache_lock);
09546       dp->waiters[x] = -1;
09547       close(com[1]);
09548       close(com[0]);
09549       if (abort) {
09550          /* Don't interpret anything, just abort.  Not sure what th epoint
09551            of undeferring dtmf on a hung up channel is but hey whatever */
09552          if (!old && chan)
09553             ast_channel_undefer_dtmf(chan);
09554          return NULL;
09555       }
09556       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
09557          /* Now to do non-independent analysis the results of our wait */
09558          if (dp->flags & CACHE_FLAG_PENDING) {
09559             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
09560                pending.  Don't let it take as long to timeout. */
09561             dp->flags &= ~CACHE_FLAG_PENDING;
09562             dp->flags |= CACHE_FLAG_TIMEOUT;
09563             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
09564                systems without leaving it unavailable once the server comes back online */
09565             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
09566             for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
09567                if (dp->waiters[x] > -1)
09568                   write(dp->waiters[x], "asdf", 4);
09569          }
09570       }
09571       /* Our caller will obtain the rest */
09572       if (!old && chan)
09573          ast_channel_undefer_dtmf(chan);
09574    }
09575    return dp;  
09576 }

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

Todo:
XXX Note that this function contains a very expensive operation that happens for *every* incoming media frame. It iterates through every possible call number, locking and unlocking each one, to try to match the incoming frame to an active call. Call numbers can be up to 2^15, 32768. So, for an call with a local call number of 20000, every incoming audio frame would require 20000 mutex lock and unlock operations. Ouch.
It's a shame that IAX2 media frames carry the source call number instead of the destination call number. If they did, this lookup wouldn't be needed. However, it's too late to change that now. Instead, we need to come up with a better way of indexing active calls so that these frequent lookups are not so expensive.

Definition at line 1219 of file chan_iax2.c.

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

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

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

static struct iax2_thread* find_idle_thread ( void   )  [static]

Definition at line 844 of file chan_iax2.c.

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

Referenced by __schedule_action(), and socket_read().

00845 {
00846    pthread_attr_t attr;
00847    struct iax2_thread *thread = NULL;
00848 
00849    /* Pop the head of the list off */
00850    AST_LIST_LOCK(&idle_list);
00851    thread = AST_LIST_REMOVE_HEAD(&idle_list, list);
00852    AST_LIST_UNLOCK(&idle_list);
00853 
00854    /* If no idle thread is available from the regular list, try dynamic */
00855    if (thread == NULL) {
00856       AST_LIST_LOCK(&dynamic_list);
00857       thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list);
00858       /* Make sure we absolutely have a thread... if not, try to make one if allowed */
00859       if (thread == NULL && iaxmaxthreadcount > iaxdynamicthreadcount) {
00860          /* We need to MAKE a thread! */
00861          if ((thread = ast_calloc(1, sizeof(*thread)))) {
00862             thread->threadnum = iaxdynamicthreadcount;
00863             thread->type = IAX_TYPE_DYNAMIC;
00864             ast_mutex_init(&thread->lock);
00865             ast_cond_init(&thread->cond, NULL);
00866             pthread_attr_init(&attr);
00867             pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
00868             if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
00869                free(thread);
00870                thread = NULL;
00871             } else {
00872                /* All went well and the thread is up, so increment our count */
00873                iaxdynamicthreadcount++;
00874             }
00875          }
00876       }
00877       AST_LIST_UNLOCK(&dynamic_list);
00878    }
00879 
00880    return thread;
00881 }

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

Definition at line 1003 of file chan_iax2.c.

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

01004 {
01005    struct iax2_peer *peer = NULL;
01006 
01007    /* Grab peer from linked list */
01008    AST_LIST_LOCK(&peers);
01009    AST_LIST_TRAVERSE(&peers, peer, entry) {
01010       if (!strcasecmp(peer->name, name)) {
01011          break;
01012       }
01013    }
01014    AST_LIST_UNLOCK(&peers);
01015 
01016    /* Now go for realtime if applicable */
01017    if(!peer && realtime)
01018       peer = realtime_peer(name, NULL);
01019    return peer;
01020 }

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

Definition at line 3569 of file chan_iax2.c.

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

Referenced by iax2_trunk_queue(), and socket_process().

03570 {
03571    struct iax2_trunk_peer *tpeer;
03572    
03573    /* Finds and locks trunk peer */
03574    ast_mutex_lock(&tpeerlock);
03575    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
03576       /* We don't lock here because tpeer->addr *never* changes */
03577       if (!inaddrcmp(&tpeer->addr, sin)) {
03578          ast_mutex_lock(&tpeer->lock);
03579          break;
03580       }
03581    }
03582    if (!tpeer) {
03583       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
03584          ast_mutex_init(&tpeer->lock);
03585          tpeer->lastsent = 9999;
03586          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
03587          tpeer->trunkact = ast_tvnow();
03588          ast_mutex_lock(&tpeer->lock);
03589          tpeer->next = tpeers;
03590          tpeer->sockfd = fd;
03591          tpeers = tpeer;
03592 #ifdef SO_NO_CHECK
03593          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
03594 #endif
03595          ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
03596       }
03597    }
03598    ast_mutex_unlock(&tpeerlock);
03599    return tpeer;
03600 }

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

Definition at line 3396 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03397 {
03398    long ms; /* NOT unsigned */
03399    if (ast_tvzero(iaxs[callno]->rxcore)) {
03400       /* Initialize rxcore time if appropriate */
03401       gettimeofday(&iaxs[callno]->rxcore, NULL);
03402       /* Round to nearest 20ms so traces look pretty */
03403       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03404    }
03405    /* Calculate difference between trunk and channel */
03406    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03407    /* Return as the sum of trunk time and the difference between trunk and real time */
03408    return ms + ts;
03409 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8039 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and destroy_user().

08040 {
08041    struct iax2_context *conl;
08042    while(con) {
08043       conl = con;
08044       con = con->next;
08045       free(conl);
08046    }
08047 }

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

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

09701 {
09702    struct iax2_peer *peer;
09703    char *peername, *colname;
09704 
09705    peername = ast_strdupa(data);
09706 
09707    /* if our channel, return the IP address of the endpoint of current channel */
09708    if (!strcmp(peername,"CURRENTCHANNEL")) {
09709            unsigned short callno;
09710       if (chan->tech != &iax2_tech)
09711          return -1;
09712       callno = PTR_TO_CALLNO(chan->tech_pvt);   
09713       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
09714       return 0;
09715    }
09716 
09717    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
09718       *colname++ = '\0';
09719    else if ((colname = strchr(peername, '|')))
09720       *colname++ = '\0';
09721    else
09722       colname = "ip";
09723 
09724    if (!(peer = find_peer(peername, 1)))
09725       return -1;
09726 
09727    if (!strcasecmp(colname, "ip")) {
09728       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
09729    } else  if (!strcasecmp(colname, "status")) {
09730       peer_status(peer, buf, len); 
09731    } else  if (!strcasecmp(colname, "mailbox")) {
09732       ast_copy_string(buf, peer->mailbox, len);
09733    } else  if (!strcasecmp(colname, "context")) {
09734       ast_copy_string(buf, peer->context, len);
09735    } else  if (!strcasecmp(colname, "expire")) {
09736       snprintf(buf, len, "%d", peer->expire);
09737    } else  if (!strcasecmp(colname, "dynamic")) {
09738       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
09739    } else  if (!strcasecmp(colname, "callerid_name")) {
09740       ast_copy_string(buf, peer->cid_name, len);
09741    } else  if (!strcasecmp(colname, "callerid_num")) {
09742       ast_copy_string(buf, peer->cid_num, len);
09743    } else  if (!strcasecmp(colname, "codecs")) {
09744       ast_getformatname_multiple(buf, len -1, peer->capability);
09745    } else  if (!strncasecmp(colname, "codec[", 6)) {
09746       char *codecnum, *ptr;
09747       int index = 0, codec = 0;
09748       
09749       codecnum = strchr(colname, '[');
09750       *codecnum = '\0';
09751       codecnum++;
09752       if ((ptr = strchr(codecnum, ']'))) {
09753          *ptr = '\0';
09754       }
09755       index = atoi(codecnum);
09756       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
09757          ast_copy_string(buf, ast_getformatname(codec), len);
09758       }
09759    }
09760 
09761    return 0;
09762 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 8265 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

08266 {
08267    int methods = 0;
08268    if (strstr(value, "rsa"))
08269       methods |= IAX_AUTH_RSA;
08270    if (strstr(value, "md5"))
08271       methods |= IAX_AUTH_MD5;
08272    if (strstr(value, "plaintext"))
08273       methods |= IAX_AUTH_PLAINTEXT;
08274    return methods;
08275 }

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

Definition at line 934 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

00935 {
00936    int e;
00937    if (!strcasecmp(s, "aes128"))
00938       e = IAX_ENCRYPT_AES128;
00939    else if (ast_true(s))
00940       e = IAX_ENCRYPT_AES128;
00941    else
00942       e = 0;
00943    return e;
00944 }

static int get_from_jb ( void *  p  )  [static]

Definition at line 2309 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02310 {
02311 #ifdef SCHED_MULTITHREADED
02312    if (schedule_action(__get_from_jb, data))
02313 #endif      
02314       __get_from_jb(data);
02315    return 0;
02316 }

static int handle_error ( void   )  [static]

Definition at line 1606 of file chan_iax2.c.

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

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

01607 {
01608    /* XXX Ideally we should figure out why an error occured and then abort those
01609       rather than continuing to try.  Unfortunately, the published interface does
01610       not seem to work XXX */
01611 #if 0
01612    struct sockaddr_in *sin;
01613    int res;
01614    struct msghdr m;
01615    struct sock_extended_err e;
01616    m.msg_name = NULL;
01617    m.msg_namelen = 0;
01618    m.msg_iov = NULL;
01619    m.msg_control = &e;
01620    m.msg_controllen = sizeof(e);
01621    m.msg_flags = 0;
01622    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
01623    if (res < 0)
01624       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
01625    else {
01626       if (m.msg_controllen) {
01627          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
01628          if (sin) 
01629             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
01630          else
01631             ast_log(LOG_WARNING, "No address detected??\n");
01632       } else {
01633          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
01634       }
01635    }
01636 #endif
01637    return 0;
01638 }

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

Acknowledgment received for OUR registration.

Definition at line 5388 of file chan_iax2.c.

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

Referenced by socket_process().

05389 {
05390    struct iax2_registry *reg;
05391    /* Start pessimistic */
05392    char peer[256] = "";
05393    char msgstatus[60];
05394    int refresh = 60;
05395    char ourip[256] = "<Unspecified>";
05396    struct sockaddr_in oldus;
05397    struct sockaddr_in us;
05398    int oldmsgs;
05399 
05400    memset(&us, 0, sizeof(us));
05401    if (ies->apparent_addr)
05402       bcopy(ies->apparent_addr, &us, sizeof(us));
05403    if (ies->username)
05404       ast_copy_string(peer, ies->username, sizeof(peer));
05405    if (ies->refresh)
05406       refresh = ies->refresh;
05407    if (ies->calling_number) {
05408       /* We don't do anything with it really, but maybe we should */
05409    }
05410    reg = iaxs[callno]->reg;
05411    if (!reg) {
05412       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05413       return -1;
05414    }
05415    memcpy(&oldus, &reg->us, sizeof(oldus));
05416    oldmsgs = reg->messages;
05417    if (inaddrcmp(&reg->addr, sin)) {
05418       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05419       return -1;
05420    }
05421    memcpy(&reg->us, &us, sizeof(reg->us));
05422    if (ies->msgcount >= 0)
05423       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05424    /* always refresh the registration at the interval requested by the server
05425       we are registering to
05426    */
05427    reg->refresh = refresh;
05428    if (reg->expire > -1)
05429       ast_sched_del(sched, reg->expire);
05430    reg->expire = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05431    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05432       if (option_verbose > 2) {
05433          if (reg->messages > 255)
05434             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
05435          else if (reg->messages > 1)
05436             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
05437          else if (reg->messages > 0)
05438             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
05439          else
05440             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
05441          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05442          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
05443       }
05444       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
05445    }
05446    reg->regstate = REG_STATE_REGISTERED;
05447    return 0;
05448 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3219 of file chan_iax2.c.

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

03220 {
03221    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03222    if (option_debug)
03223       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03224    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03225 }

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

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

03076 {
03077    struct ast_channel *cs[3];
03078    struct ast_channel *who, *other;
03079    int to = -1;
03080    int res = -1;
03081    int transferstarted=0;
03082    struct ast_frame *f;
03083    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03084    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03085    struct timeval waittimer = {0, 0}, tv;
03086 
03087    lock_both(callno0, callno1);
03088    /* Put them in native bridge mode */
03089    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
03090       iaxs[callno0]->bridgecallno = callno1;
03091       iaxs[callno1]->bridgecallno = callno0;
03092    }
03093    unlock_both(callno0, callno1);
03094 
03095    /* If not, try to bridge until we can execute a transfer, if we can */
03096    cs[0] = c0;
03097    cs[1] = c1;
03098    for (/* ever */;;) {
03099       /* Check in case we got masqueraded into */
03100       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
03101          if (option_verbose > 2)
03102             ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
03103          /* Remove from native mode */
03104          if (c0->tech == &iax2_tech) {
03105             ast_mutex_lock(&iaxsl[callno0]);
03106             iaxs[callno0]->bridgecallno = 0;
03107             ast_mutex_unlock(&iaxsl[callno0]);
03108          }
03109          if (c1->tech == &iax2_tech) {
03110             ast_mutex_lock(&iaxsl[callno1]);
03111             iaxs[callno1]->bridgecallno = 0;
03112             ast_mutex_unlock(&iaxsl[callno1]);
03113          }
03114          return AST_BRIDGE_FAILED_NOWARN;
03115       }
03116       if (c0->nativeformats != c1->nativeformats) {
03117          if (option_verbose > 2) {
03118             char buf0[255];
03119             char buf1[255];
03120             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
03121             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
03122             ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
03123          }
03124          /* Remove from native mode */
03125          lock_both(callno0, callno1);
03126          iaxs[callno0]->bridgecallno = 0;
03127          iaxs[callno1]->bridgecallno = 0;
03128          unlock_both(callno0, callno1);
03129          return AST_BRIDGE_FAILED_NOWARN;
03130       }
03131       /* check if transfered and if we really want native bridging */
03132       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
03133          /* Try the transfer */
03134          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
03135                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
03136             ast_log(LOG_WARNING, "Unable to start the transfer\n");
03137          transferstarted = 1;
03138       }
03139       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
03140          /* Call has been transferred.  We're no longer involved */
03141          gettimeofday(&tv, NULL);
03142          if (ast_tvzero(waittimer)) {
03143             waittimer = tv;
03144          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
03145             c0->_softhangup |= AST_SOFTHANGUP_DEV;
03146             c1->_softhangup |= AST_SOFTHANGUP_DEV;
03147             *fo = NULL;
03148             *rc = c0;
03149             res = AST_BRIDGE_COMPLETE;
03150             break;
03151          }
03152       }
03153       to = 1000;
03154       who = ast_waitfor_n(cs, 2, &to);
03155       if (timeoutms > -1) {
03156          timeoutms -= (1000 - to);
03157          if (timeoutms < 0)
03158             timeoutms = 0;
03159       }
03160       if (!who) {
03161          if (!timeoutms) {
03162             res = AST_BRIDGE_RETRY;
03163             break;
03164          }
03165          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03166             res = AST_BRIDGE_FAILED;
03167             break;
03168          }
03169          continue;
03170       }
03171       f = ast_read(who);
03172       if (!f) {
03173          *fo = NULL;
03174          *rc = who;
03175          res = AST_BRIDGE_COMPLETE;
03176          break;
03177       }
03178       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03179          *fo = f;
03180          *rc = who;
03181          res =  AST_BRIDGE_COMPLETE;
03182          break;
03183       }
03184       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
03185       if ((f->frametype == AST_FRAME_VOICE) ||
03186           (f->frametype == AST_FRAME_TEXT) ||
03187           (f->frametype == AST_FRAME_VIDEO) || 
03188           (f->frametype == AST_FRAME_IMAGE) ||
03189           (f->frametype == AST_FRAME_DTMF)) {
03190          /* monitored dtmf take out of the bridge.
03191           * check if we monitor the specific source.
03192           */
03193          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
03194          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
03195             *rc = who;
03196             *fo = f;
03197             res = AST_BRIDGE_COMPLETE;
03198             /* Remove from native mode */
03199             break;
03200          }
03201          /* everything else goes to the other side */
03202          ast_write(other, f);
03203       }
03204       ast_frfree(f);
03205       /* Swap who gets priority */
03206       cs[2] = cs[0];
03207       cs[0] = cs[1];
03208       cs[1] = cs[2];
03209    }
03210    lock_both(callno0, callno1);
03211    if(iaxs[callno0])
03212       iaxs[callno0]->bridgecallno = 0;
03213    if(iaxs[callno1])
03214       iaxs[callno1]->bridgecallno = 0;
03215    unlock_both(callno0, callno1);
03216    return res;
03217 }

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

Definition at line 2821 of file chan_iax2.c.

References ast_channel::_state, chan_iax2_pvt::adsi, ast_channel::adsicpe, AST_FRAME_IAX, AST_LIST_TRAVERSE, 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, ast_var_name(), ast_var_value(), auto_congest(), 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, ast_channel::context, create_addr(), chan_iax2_pvt::encmethods, iax2_datetime(), IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VARIABLE, IAX_IE_VERSION, IAX_PROTO_VERSION, IAX_SENDANI, iaxs, iaxsl, chan_iax2_pvt::initid, LOG_WARNING, chan_iax2_pvt::maxtime, ast_channel::nativeformats, parse_dial_string(), chan_iax2_pvt::pingtime, PTR_TO_CALLNO, sched, send_command(), chan_iax2_pvt::sockfd, ast_channel::tech_pvt, var, and ast_channel::varshead.

02822 {
02823    struct sockaddr_in sin;
02824    char *l=NULL, *n=NULL, *tmpstr;
02825    struct iax_ie_data ied;
02826    char *defaultrdest = "s";
02827    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
02828    struct parsed_dial_string pds;
02829    struct create_addr_info cai;
02830    struct ast_var_t *var;
02831 
02832    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
02833       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
02834       return -1;
02835    }
02836 
02837    memset(&cai, 0, sizeof(cai));
02838    cai.encmethods = iax2_encryption;
02839 
02840    memset(&pds, 0, sizeof(pds));
02841    tmpstr = ast_strdupa(dest);
02842    parse_dial_string(tmpstr, &pds);
02843 
02844    if (!pds.exten)
02845       pds.exten = defaultrdest;
02846 
02847    if (create_addr(pds.peer, &sin, &cai)) {
02848       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
02849       return -1;
02850    }
02851 
02852    if (!pds.username && !ast_strlen_zero(cai.username))
02853       pds.username = cai.username;
02854    if (!pds.password && !ast_strlen_zero(cai.secret))
02855       pds.password = cai.secret;
02856    if (!pds.key && !ast_strlen_zero(cai.outkey))
02857       pds.key = cai.outkey;
02858    if (!pds.context && !ast_strlen_zero(cai.peercontext))
02859       pds.context = cai.peercontext;
02860 
02861    /* Keep track of the context for outgoing calls too */
02862    ast_copy_string(c->context, cai.context, sizeof(c->context));
02863 
02864    if (pds.port)
02865       sin.sin_port = htons(atoi(pds.port));
02866 
02867    l = c->cid.cid_num;
02868    n = c->cid.cid_name;
02869 
02870    /* Now build request */ 
02871    memset(&ied, 0, sizeof(ied));
02872 
02873    /* On new call, first IE MUST be IAX version of caller */
02874    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
02875    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
02876    if (pds.options && strchr(pds.options, 'a')) {
02877       /* Request auto answer */
02878       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
02879    }
02880 
02881    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
02882 
02883    if (l) {
02884       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
02885       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
02886    } else {
02887       if (n)
02888          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
02889       else
02890          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
02891    }
02892 
02893    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
02894    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
02895 
02896    if (n)
02897       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
02898    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
02899       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
02900 
02901    if (!ast_strlen_zero(c->language))
02902       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
02903    if (!ast_strlen_zero(c->cid.cid_dnid))
02904       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
02905    if (!ast_strlen_zero(c->cid.cid_rdnis))
02906       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
02907 
02908    if (pds.context)
02909       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
02910 
02911    if (pds.username)
02912       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
02913 
02914    if (cai.encmethods)
02915       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
02916 
02917    ast_mutex_lock(&iaxsl[callno]);
02918 
02919    if (!ast_strlen_zero(c->context))
02920       ast_string_field_set(iaxs[callno], context, c->context);
02921 
02922    if (pds.username)
02923       ast_string_field_set(iaxs[callno], username, pds.username);
02924 
02925    iaxs[callno]->encmethods = cai.encmethods;
02926 
02927    iaxs[callno]->adsi = cai.adsi;
02928    
02929    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
02930    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
02931 
02932    if (pds.key)
02933       ast_string_field_set(iaxs[callno], outkey, pds.key);
02934    if (pds.password)
02935       ast_string_field_set(iaxs[callno], secret, pds.password);
02936 
02937    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
02938    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
02939    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
02940    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
02941 
02942    if (iaxs[callno]->maxtime) {
02943       /* Initialize pingtime and auto-congest time */
02944       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
02945       iaxs[callno]->initid = ast_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
02946    } else if (autokill) {
02947       iaxs[callno]->pingtime = autokill / 2;
02948       iaxs[callno]->initid = ast_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
02949    }
02950 
02951    /* Add remote vars */
02952    AST_LIST_TRAVERSE(&c->varshead, var, entries) {
02953       if (!strncmp(ast_var_name(var), "~IAX2~", strlen("~IAX2~"))) {
02954          char tmp[256];
02955          snprintf(tmp, sizeof(tmp), "%s=%s", ast_var_name(var) + strlen("~IAX2~"), ast_var_value(var));
02956          iax_ie_append_str(&ied, IAX_IE_VARIABLE, tmp);
02957       }
02958    }
02959 
02960    /* send the command using the appropriate socket for this peer */
02961    iaxs[callno]->sockfd = cai.sockfd;
02962 
02963    /* Transmit the string in a "NEW" request */
02964    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
02965 
02966    ast_mutex_unlock(&iaxsl[callno]);
02967    ast_setstate(c, AST_STATE_RINGING);
02968    
02969    return 0;
02970 }

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

09603 {
09604    int res = 0;
09605    struct iax2_dpcache *dp;
09606 #if 0
09607    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
09608 #endif
09609    if ((priority != 1) && (priority != 2))
09610       return 0;
09611    ast_mutex_lock(&dpcache_lock);
09612    dp = find_cache(chan, data, context, exten, priority);
09613    if (dp) {
09614       if (dp->flags & CACHE_FLAG_CANEXIST)
09615          res= 1;
09616    }
09617    ast_mutex_unlock(&dpcache_lock);
09618    if (!dp) {
09619       ast_log(LOG_WARNING, "Unable to make DP cache\n");
09620    }
09621    return res;
09622 }

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

Definition at line 2734 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

02735 {
02736    time_t t;
02737    struct tm tm;
02738    unsigned int tmp;
02739    time(&t);
02740    localtime_r(&t, &tm);
02741    if (!ast_strlen_zero(tz))
02742       ast_localtime(&t, &tm, tz);
02743    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
02744    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
02745    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
02746    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
02747    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
02748    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
02749    return tmp;
02750 }

static void iax2_destroy ( int  callno  )  [static]

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

01754 {
01755    struct chan_iax2_pvt *pvt;
01756    struct iax_frame *cur;
01757    struct ast_channel *owner;
01758 
01759 retry:
01760    pvt = iaxs[callno];
01761    gettimeofday(&lastused[callno], NULL);
01762    
01763    owner = pvt ? pvt->owner : NULL;
01764 
01765    if (owner) {
01766       if (ast_mutex_trylock(&owner->lock)) {
01767          ast_log(LOG_NOTICE, "Avoiding IAX destroy deadlock\n");
01768          ast_mutex_unlock(&iaxsl[callno]);
01769          usleep(1);
01770          ast_mutex_lock(&iaxsl[callno]);
01771          goto retry;
01772       }
01773    }
01774    if (!owner)
01775       iaxs[callno] = NULL;
01776    if (pvt) {
01777       if (!owner)
01778          pvt->owner = NULL;
01779       iax2_destroy_helper(pvt);
01780 
01781       /* Already gone */
01782       ast_set_flag(pvt, IAX_ALREADYGONE); 
01783 
01784       if (owner) {
01785          /* If there's an owner, prod it to give up */
01786          owner->_softhangup |= AST_SOFTHANGUP_DEV;
01787          ast_queue_hangup(owner);
01788       }
01789 
01790       AST_LIST_LOCK(&iaxq.queue);
01791       AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
01792          /* Cancel any pending transmissions */
01793          if (cur->callno == pvt->callno) 
01794             cur->retries = -1;
01795       }
01796       AST_LIST_UNLOCK(&iaxq.queue);
01797 
01798       if (pvt->reg)
01799          pvt->reg->callno = 0;
01800       if (!owner) {
01801          jb_frame frame;
01802          if (pvt->vars) {
01803              ast_variables_destroy(pvt->vars);
01804              pvt->vars = NULL;
01805          }
01806 
01807          while (jb_getall(pvt->jb, &frame) == JB_OK)
01808             iax2_frame_free(frame.data);
01809          jb_destroy(pvt->jb);
01810          /* gotta free up the stringfields */
01811          ast_string_field_free_pools(pvt);
01812          free(pvt);
01813       }
01814    }
01815    if (owner) {
01816       ast_mutex_unlock(&owner->lock);
01817    }
01818    if (callno & 0x4000)
01819       update_max_trunk();
01820 }

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

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

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

01695 {
01696    struct iax2_user *user = NULL;
01697 
01698    /* Decrement AUTHREQ count if needed */
01699    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01700       AST_LIST_LOCK(&users);
01701       AST_LIST_TRAVERSE(&users, user, entry) {
01702          if (!strcmp(user->name, pvt->username)) {
01703             user->curauthreq--;
01704             break;
01705          }
01706       }
01707       AST_LIST_UNLOCK(&users);
01708       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01709    }
01710    /* No more pings or lagrq's */
01711    if (pvt->pingid > -1)
01712       ast_sched_del(sched, pvt->pingid);
01713    pvt->pingid = -1;
01714    if (pvt->lagid > -1)
01715       ast_sched_del(sched, pvt->lagid);
01716    pvt->lagid = -1;
01717    if (pvt->autoid > -1)
01718       ast_sched_del(sched, pvt->autoid);
01719    pvt->autoid = -1;
01720    if (pvt->authid > -1)
01721       ast_sched_del(sched, pvt->authid);
01722    pvt->authid = -1;
01723    if (pvt->initid > -1)
01724       ast_sched_del(sched, pvt->initid);
01725    pvt->initid = -1;
01726    if (pvt->jbid > -1)
01727       ast_sched_del(sched, pvt->jbid);
01728    pvt->jbid = -1;
01729 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

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

09788 {
09789    struct parsed_dial_string pds;
09790    char *tmp = ast_strdupa(data);
09791    struct iax2_peer *p;
09792    int res = AST_DEVICE_INVALID;
09793 
09794    memset(&pds, 0, sizeof(pds));
09795    parse_dial_string(tmp, &pds);
09796    if (ast_strlen_zero(pds.peer))
09797       return res;
09798    
09799    if (option_debug > 2)
09800       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
09801 
09802    /* SLD: FIXME: second call to find_peer during registration */
09803    if (!(p = find_peer(pds.peer, 1)))
09804       return res;
09805 
09806    res = AST_DEVICE_UNAVAILABLE;
09807    if (option_debug > 2) 
09808       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
09809          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
09810    
09811    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
09812        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
09813       /* Peer is registered, or have default IP address
09814          and a valid registration */
09815       if (p->historicms == 0 || p->historicms <= p->maxms)
09816          /* let the core figure out whether it is in use or not */
09817          res = AST_DEVICE_UNKNOWN;  
09818    }
09819 
09820    if (ast_test_flag(p, IAX_TEMPONLY))
09821       destroy_peer(p);
09822 
09823    return res;
09824 }

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

Definition at line 2418 of file chan_iax2.c.

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

02419 {
02420    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02421 }

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

Definition at line 2423 of file chan_iax2.c.

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

02424 {
02425    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02426 }

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

Definition at line 4475 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04476 {
04477    if (argc < 2 || argc > 3)
04478       return RESULT_SHOWUSAGE;
04479    iaxdebug = 1;
04480    ast_cli(fd, "IAX2 Debugging Enabled\n");
04481    return RESULT_SUCCESS;
04482 }

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

Definition at line 4493 of file chan_iax2.c.

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

04494 {
04495    if (argc < 3 || argc > 4)
04496       return RESULT_SHOWUSAGE;
04497    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04498    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04499    return RESULT_SUCCESS;
04500 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 7784 of file chan_iax2.c.

References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno(), iax2_destroy(), iax2_do_register_s(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_WARNING, NEW_FORCE, option_debug, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), and iax2_registry::username.

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

07785 {
07786    struct iax_ie_data ied;
07787    if (option_debug && iaxdebug)
07788       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
07789 
07790    if (reg->dnsmgr && 
07791        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
07792       /* Maybe the IP has changed, force DNS refresh */
07793       ast_dnsmgr_refresh(reg->dnsmgr);
07794    }
07795    
07796    /*
07797     * if IP has Changed, free allocated call to create a new one with new IP
07798     * call has the pointer to IP and must be updated to the new one
07799     */
07800    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
07801       ast_mutex_lock(&iaxsl[reg->callno]);
07802       iax2_destroy(reg->callno);
07803       ast_mutex_unlock(&iaxsl[reg->callno]);
07804       reg->callno = 0;
07805    }
07806    if (!reg->addr.sin_addr.s_addr) {
07807       if (option_debug && iaxdebug)
07808          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
07809       /* Setup the next registration attempt */
07810       if (reg->expire > -1)
07811          ast_sched_del(sched, reg->expire);
07812       reg->expire  = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
07813       return -1;
07814    }
07815 
07816    if (!reg->callno) {
07817       if (option_debug)
07818          ast_log(LOG_DEBUG, "Allocate call number\n");
07819       reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE, 1, defaultsockfd);
07820       if (reg->callno < 1) {
07821          ast_log(LOG_WARNING, "Unable to create call for registration\n");
07822          return -1;
07823       } else if (option_debug)
07824          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
07825       iaxs[reg->callno]->reg = reg;
07826    }
07827    /* Schedule the next registration attempt */
07828    if (reg->expire > -1)
07829       ast_sched_del(sched, reg->expire);
07830    /* Setup the next registration a little early */
07831    reg->expire  = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
07832    /* Send the request */
07833    memset(&ied, 0, sizeof(ied));
07834    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
07835    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
07836    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
07837    reg->regstate = REG_STATE_REGSENT;
07838    return 0;
07839 }

static int iax2_do_register_s ( void *  data  )  [static]

Definition at line 5242 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05243 {
05244 #ifdef SCHED_MULTITHREADED
05245    if (schedule_action(__iax2_do_register_s, data))
05246 #endif      
05247       __iax2_do_register_s(data);
05248    return 0;
05249 }

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

Definition at line 4484 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04485 {
04486    if (argc < 3 || argc > 4)
04487       return RESULT_SHOWUSAGE;
04488    iaxtrunkdebug = 1;
04489    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04490    return RESULT_SUCCESS;
04491 }

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

Definition at line 5875 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

05876 {
05877    struct iax_ie_data ied;
05878    /* Auto-hangup with 30 seconds of inactivity */
05879    if (iaxs[callno]->autoid > -1)
05880       ast_sched_del(sched, iaxs[callno]->autoid);
05881    iaxs[callno]->autoid = ast_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
05882    memset(&ied, 0, sizeof(ied));
05883    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
05884    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
05885    dp->flags |= CACHE_FLAG_TRANSMITTED;
05886 }

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

09649 {
09650    char odata[256];
09651    char req[256];
09652    char *ncontext;
09653    struct iax2_dpcache *dp;
09654    struct ast_app *dial;
09655 #if 0
09656    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);
09657 #endif
09658    if (priority == 2) {
09659       /* Indicate status, can be overridden in dialplan */
09660       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
09661       if (dialstatus) {
09662          dial = pbx_findapp(dialstatus);
09663          if (dial) 
09664             pbx_exec(chan, dial, "");
09665       }
09666       return -1;
09667    } else if (priority != 1)
09668       return -1;
09669    ast_mutex_lock(&dpcache_lock);
09670    dp = find_cache(chan, data, context, exten, priority);
09671    if (dp) {
09672       if (dp->flags & CACHE_FLAG_EXISTS) {
09673          ast_copy_string(odata, data, sizeof(odata));
09674          ncontext = strchr(odata, '/');
09675          if (ncontext) {
09676             *ncontext = '\0';
09677             ncontext++;
09678             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
09679          } else {
09680             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
09681          }
09682          if (option_verbose > 2)
09683             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
09684       } else {
09685          ast_mutex_unlock(&dpcache_lock);
09686          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
09687          return -1;
09688       }
09689    }
09690    ast_mutex_unlock(&dpcache_lock);
09691    dial = pbx_findapp("Dial");
09692    if (dial) {
09693       return pbx_exec(chan, dial, req);
09694    } else {
09695       ast_log(LOG_WARNING, "No dial application registered\n");
09696    }
09697    return -1;
09698 }

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

09580 {
09581    struct iax2_dpcache *dp;
09582    int res = 0;
09583 #if 0
09584    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
09585 #endif
09586    if ((priority != 1) && (priority != 2))
09587       return 0;
09588    ast_mutex_lock(&dpcache_lock);
09589    dp = find_cache(chan, data, context, exten, priority);
09590    if (dp) {
09591       if (dp->flags & CACHE_FLAG_EXISTS)
09592          res= 1;
09593    }
09594    ast_mutex_unlock(&dpcache_lock);
09595    if (!dp) {
09596       ast_log(LOG_WARNING, "Unable to make DP cache\n");
09597    }
09598    return res;
09599 }

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

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

02446 {
02447    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02448    ast_mutex_lock(&iaxsl[callno]);
02449    if (iaxs[callno])
02450       iaxs[callno]->owner = newchan;
02451    else
02452       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02453    ast_mutex_unlock(&iaxsl[callno]);
02454    return 0;
02455 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1301 of file chan_iax2.c.

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

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

01302 {
01303    if (fr->retrans > -1)
01304       ast_sched_del(sched, fr->retrans);
01305    iax_frame_free(fr);
01306 }

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

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

01023 {
01024    struct iax2_peer *peer = NULL;
01025    int res = 0;
01026 
01027    if (lockpeer)
01028       AST_LIST_LOCK(&peers);
01029    AST_LIST_TRAVERSE(&peers, peer, entry) {
01030       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01031           (peer->addr.sin_port == sin.sin_port)) {
01032          ast_copy_string(host, peer->name, len);
01033          res = 1;
01034          break;
01035       }
01036    }
01037    if (lockpeer)
01038       AST_LIST_UNLOCK(&peers);
01039    if (!peer) {
01040       peer = realtime_peer(NULL, &sin);
01041       if (peer) {
01042          ast_copy_string(host, peer->name, len);
01043          if (ast_test_flag(peer, IAX_TEMPONLY))
01044             destroy_peer(peer);
01045          res = 1;
01046       }
01047    }
01048 
01049    return res;
01050 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03281 {
03282    struct iax2_peer *peer = NULL;
03283    int res = 0;
03284 
03285    AST_LIST_LOCK(&peers);
03286    AST_LIST_TRAVERSE(&peers, peer, entry) {
03287       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03288           (peer->addr.sin_port == sin.sin_port)) {
03289          res = ast_test_flag(peer, IAX_TRUNK);
03290          break;
03291       }
03292    }
03293    AST_LIST_UNLOCK(&peers);
03294 
03295    return res;
03296 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 2972 of file chan_iax2.c.

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

02973 {
02974    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
02975    int alreadygone;
02976    struct iax_ie_data ied;
02977    memset(&ied, 0, sizeof(ied));
02978    ast_mutex_lock(&iaxsl[callno]);
02979    if (callno && iaxs[callno]) {
02980       ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
02981       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
02982       /* Send the hangup unless we have had a transmission error or are already gone */
02983       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
02984       if (!iaxs[callno]->error && !alreadygone) 
02985          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
02986       /* Explicitly predestroy it */
02987       iax2_predestroy(callno);
02988       /* If we were already gone to begin with, destroy us now */
02989       if (alreadygone) {
02990          ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
02991          iax2_destroy(callno);
02992       }
02993    }
02994    ast_mutex_unlock(&iaxsl[callno]);
02995    if (option_verbose > 2) 
02996       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
02997    return 0;
02998 }

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

Definition at line 3227 of file chan_iax2.c.

References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, option_debug, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.

03228 {
03229    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03230    struct chan_iax2_pvt *pvt;
03231    int res = 0;
03232 
03233    if (option_debug && iaxdebug)
03234       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03235 
03236    ast_mutex_lock(&iaxsl[callno]);
03237    pvt = iaxs[callno];
03238    if (!strcasecmp(pvt->mohinterpret, "passthrough")) {
03239       res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03240       ast_mutex_unlock(&iaxsl[callno]);
03241       return res;
03242    }
03243 
03244    switch (condition) {
03245    case AST_CONTROL_HOLD:
03246       ast_moh_start(c, data, pvt->mohinterpret);
03247       break;
03248    case AST_CONTROL_UNHOLD:
03249       ast_moh_stop(c);
03250       break;
03251    default:
03252       res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03253    }
03254 
03255    ast_mutex_unlock(&iaxsl[callno]);
03256 
03257    return res;
03258 }

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

09626 {
09627    int res = 0;
09628    struct iax2_dpcache *dp;
09629 #if 0
09630    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
09631 #endif
09632    if ((priority != 1) && (priority != 2))
09633       return 0;
09634    ast_mutex_lock(&dpcache_lock);
09635    dp = find_cache(chan, data, context, exten, priority);
09636    if (dp) {
09637       if (dp->flags & CACHE_FLAG_MATCHMORE)
09638          res= 1;
09639    }
09640    ast_mutex_unlock(&dpcache_lock);
09641    if (!dp) {
09642       ast_log(LOG_WARNING, "Unable to make DP cache\n");
09643    }
09644    return res;
09645 }

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

Definition at line 4502 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04503 {
04504    if (argc < 3 || argc > 4)
04505       return RESULT_SHOWUSAGE;
04506    iaxdebug = 0;
04507    ast_cli(fd, "IAX2 Debugging Disabled\n");
04508    return RESULT_SUCCESS;
04509 }

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

Definition at line 4520 of file chan_iax2.c.

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

04521 {
04522    if (argc < 4 || argc > 5)
04523       return RESULT_SHOWUSAGE;
04524    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04525    jb_debug_output("\n");
04526    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04527    return RESULT_SUCCESS;
04528 }

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

Definition at line 4511 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04512 {
04513    if (argc < 4 || argc > 5)
04514       return RESULT_SHOWUSAGE;
04515    iaxtrunkdebug = 0;
04516    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
04517    return RESULT_SUCCESS;
04518 }

static int iax2_poke_noanswer ( void *  data  )  [static]

Definition at line 7980 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

07981 {
07982    struct iax2_peer *peer = data;
07983    peer->pokeexpire = -1;
07984 #ifdef SCHED_MULTITHREADED
07985    if (schedule_action(__iax2_poke_noanswer, data))
07986 #endif      
07987       __iax2_poke_noanswer(data);
07988    return 0;
07989 }

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

Definition at line 7991 of file chan_iax2.c.

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

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

07992 {
07993    if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
07994       /* IF we have no IP, or this isn't to be monitored, return
07995         immediately after clearing things out */
07996       peer->lastms = 0;
07997       peer->historicms = 0;
07998       peer->pokeexpire = -1;
07999       peer->callno = 0;
08000       return 0;
08001    }
08002    if (peer->callno > 0) {
08003       ast_log(LOG_NOTICE, "Still have a callno...\n");
08004       ast_mutex_lock(&iaxsl[peer->callno]);
08005       iax2_destroy(peer->callno);
08006       ast_mutex_unlock(&iaxsl[peer->callno]);
08007    }
08008    if (heldcall)
08009       ast_mutex_unlock(&iaxsl[heldcall]);
08010    peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, 0, peer->sockfd);
08011    if (heldcall)
08012       ast_mutex_lock(&iaxsl[heldcall]);
08013    if (peer->callno < 1) {
08014       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08015       return -1;
08016    }
08017 
08018    /* Speed up retransmission times for this qualify call */
08019    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08020    iaxs[peer->callno]->peerpoke = peer;
08021    
08022    /* Remove any pending pokeexpire task */
08023    if (peer->pokeexpire > -1)
08024       ast_sched_del(sched, peer->pokeexpire);
08025 
08026    /* Queue up a new task to handle no reply */
08027    /* If the host is already unreachable then use the unreachable interval instead */
08028    if (peer->lastms < 0) {
08029       peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer);
08030    } else
08031       peer->pokeexpire = ast_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer);
08032 
08033    /* And send the poke */
08034    send_command(iaxs[peer->callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08035 
08036    return 0;
08037 }

static int iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 5914 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

05915 {
05916    struct iax2_peer *peer = data;
05917    peer->pokeexpire = -1;
05918 #ifdef SCHED_MULTITHREADED
05919    if (schedule_action(__iax2_poke_peer_s, data))
05920 #endif      
05921       __iax2_poke_peer_s(data);
05922    return 0;
05923 }

static int iax2_predestroy ( int  callno  )  [static]

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

01732 {
01733    struct ast_channel *c;
01734    struct chan_iax2_pvt *pvt = iaxs[callno];
01735 
01736    if (!pvt)
01737       return -1;
01738    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
01739       iax2_destroy_helper(pvt);
01740       ast_set_flag(pvt, IAX_ALREADYGONE); 
01741    }
01742    c = pvt->owner;
01743    if (c) {
01744       c->_softhangup |= AST_SOFTHANGUP_DEV;
01745       c->tech_pvt = NULL;
01746       ast_queue_hangup(c);
01747       pvt->owner = NULL;
01748       ast_module_unref(ast_module_info->self);
01749    }
01750    return 0;
01751 }

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

Definition at line 7706 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

07707 {
07708    struct iax2_thread *thread = data;
07709    struct timeval tv;
07710    struct timespec ts;
07711    int put_into_idle = 0;
07712 
07713    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
07714    pthread_cleanup_push(iax2_process_thread_cleanup, data);
07715    for(;;) {
07716       /* Wait for something to signal us to be awake */
07717       ast_mutex_lock(&thread->lock);
07718 
07719       /* Put into idle list if applicable */
07720       if (put_into_idle)
07721          insert_idle_thread(thread);
07722 
07723       if (thread->type == IAX_TYPE_DYNAMIC) {
07724          /* Wait to be signalled or time out */
07725          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
07726          ts.tv_sec = tv.tv_sec;
07727          ts.tv_nsec = tv.tv_usec * 1000;
07728          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
07729             ast_mutex_unlock(&thread->lock);
07730             AST_LIST_LOCK(&dynamic_list);
07731             AST_LIST_REMOVE(&dynamic_list, thread, list);
07732             iaxdynamicthreadcount--;
07733             AST_LIST_UNLOCK(&dynamic_list);
07734             break;      /* exiting the main loop */
07735          }
07736       } else {
07737          ast_cond_wait(&thread->cond, &thread->lock);
07738       }
07739       ast_mutex_unlock(&thread->lock);
07740 
07741       /* Add ourselves to the active list now */
07742       AST_LIST_LOCK(&active_list);
07743       AST_LIST_INSERT_HEAD(&active_list, thread, list);
07744       AST_LIST_UNLOCK(&active_list);
07745 
07746       /* See what we need to do */
07747       switch(thread->iostate) {
07748       case IAX_IOSTATE_READY:
07749          thread->actions++;
07750          thread->iostate = IAX_IOSTATE_PROCESSING;
07751          socket_process(thread);
07752          break;
07753       case IAX_IOSTATE_SCHEDREADY:
07754          thread->actions++;
07755          thread->iostate = IAX_IOSTATE_PROCESSING;
07756 #ifdef SCHED_MULTITHREADED
07757          thread->schedfunc(thread->scheddata);
07758 #endif      
07759          break;
07760       }
07761       time(&thread->checktime);
07762       thread->iostate = IAX_IOSTATE_IDLE;
07763 #ifdef DEBUG_SCHED_MULTITHREAD
07764       thread->curfunc[0]='\0';
07765 #endif      
07766 
07767       /* Now... remove ourselves from the active list, and return to the idle list */
07768       AST_LIST_LOCK(&active_list);
07769       AST_LIST_REMOVE(&active_list, thread, list);
07770       AST_LIST_UNLOCK(&active_list);
07771 
07772       /* Go back into our respective list */
07773       put_into_idle = 1;
07774    }
07775 
07776    /* I am exiting here on my own volition, I need to clean up my own data structures
07777    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
07778    */
07779    pthread_cleanup_pop(1);
07780 
07781    return NULL;
07782 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 7697 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

07698 {
07699    struct iax2_thread *thread = data;
07700    ast_mutex_destroy(&thread->lock);
07701    ast_cond_destroy(&thread->cond);
07702    free(thread);
07703    ast_atomic_dec_and_test(&iaxactivethreadcount);
07704 }

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

Definition at line 7939 of file chan_iax2.c.

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

07940 {
07941    int force = 0;
07942    int res;
07943    if (argc < 4)
07944       return RESULT_SHOWUSAGE;
07945    if ((argc > 4)) {
07946       if (!strcasecmp(argv[4], "forced"))
07947          force = 1;
07948       else
07949          return RESULT_SHOWUSAGE;
07950    }
07951    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
07952    if (res < 0)
07953       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
07954    else if (res < 1)
07955       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
07956    else
07957       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
07958    return RESULT_SUCCESS;
07959 }

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

Definition at line 7841 of file chan_iax2.c.

References iax_prov_complete_template().

07842 {
07843    if (pos != 3)
07844       return NULL;
07845    return iax_prov_complete_template(line, word, pos, state);
07846 }

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

Definition at line 7848 of file chan_iax2.c.

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

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

07849 {
07850    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
07851       is found for template */
07852    struct iax_ie_data provdata;
07853    struct iax_ie_data ied;
07854    unsigned int sig;
07855    struct sockaddr_in sin;
07856    int callno;
07857    struct create_addr_info cai;
07858 
07859    memset(&cai, 0, sizeof(cai));
07860 
07861    if (option_debug)
07862       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
07863 
07864    if (iax_provision_build(&provdata, &sig, template, force)) {
07865       ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
07866       return 0;
07867    }
07868 
07869    if (end) {
07870       memcpy(&sin, end, sizeof(sin));
07871       cai.sockfd = sockfd;
07872    } else if (create_addr(dest, &sin, &cai))
07873       return -1;
07874 
07875    /* Build the rest of the message */
07876    memset(&ied, 0, sizeof(ied));
07877    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
07878 
07879    callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd);
07880    if (!callno)
07881       return -1;
07882 
07883    ast_mutex_lock(&iaxsl[callno]);
07884    if (iaxs[callno]) {
07885       /* Schedule autodestruct in case they don't ever give us anything back */
07886       if (iaxs[callno]->autoid > -1)
07887          ast_sched_del(sched, iaxs[callno]->autoid);
07888       iaxs[callno]->autoid = ast_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
07889       ast_set_flag(iaxs[callno], IAX_PROVISION);
07890       /* Got a call number now, so go ahead and send the provisioning information */
07891       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
07892    }
07893    ast_mutex_unlock(&iaxsl[callno]);
07894 
07895    return 1;
07896 }

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

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

01926 {
01927    struct iax2_peer *peer;
01928 
01929    if (argc != 4)
01930         return RESULT_SHOWUSAGE;
01931    if (!strcmp(argv[3],"all")) {
01932       reload_config();
01933       ast_cli(fd, "OK cache is flushed.\n");
01934    } else if ((peer = find_peer(argv[3], 0))) {
01935       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
01936          ast_set_flag(peer, IAX_RTAUTOCLEAR);
01937          expire_registry((void*)peer->name);
01938          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
01939       } else {
01940          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
01941       }
01942    } else {
01943       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
01944    }
01945    
01946    return RESULT_SUCCESS;
01947 }

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

Definition at line 1308 of file chan_iax2.c.

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

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

01309 {
01310    /* Assumes lock for callno is already held... */
01311    for (;;) {
01312       if (iaxs[callno] && iaxs[callno]->owner) {
01313          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01314             /* Avoid deadlock by pausing and trying again */
01315             ast_mutex_unlock(&iaxsl[callno]);
01316             usleep(1);
01317             ast_mutex_lock(&iaxsl[callno]);
01318          } else {
01319             ast_queue_frame(iaxs[callno]->owner, f);
01320             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01321             break;
01322          }
01323       } else
01324          break;
01325    }
01326    return 0;
01327 }

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

Definition at line 3026 of file chan_iax2.c.

References ast_log(), ast_null_frame, and LOG_NOTICE.

03027 {
03028    ast_log(LOG_NOTICE, "I should never be called!\n");
03029    return &ast_null_frame;
03030 }

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

Definition at line 5450 of file chan_iax2.c.

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

Referenced by set_config().

05451 {
05452    struct iax2_registry *reg;
05453    char copy[256];
05454    char *username, *hostname, *secret;
05455    char *porta;
05456    char *stringp=NULL;
05457    
05458    if (!value)
05459       return -1;
05460    ast_copy_string(copy, value, sizeof(copy));
05461    stringp=copy;
05462    username = strsep(&stringp, "@");
05463    hostname = strsep(&stringp, "@");
05464    if (!hostname) {
05465       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
05466       return -1;
05467    }
05468    stringp=username;
05469    username = strsep(&stringp, ":");
05470    secret = strsep(&stringp, ":");
05471    stringp=hostname;
05472    hostname = strsep(&stringp, ":");
05473    porta = strsep(&stringp, ":");
05474    
05475    if (porta && !atoi(porta)) {
05476       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
05477       return -1;
05478    }
05479    if (!(reg = ast_calloc(1, sizeof(*reg))))
05480       return -1;
05481    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
05482       free(reg);
05483       return -1;
05484    }
05485    ast_copy_string(reg->username, username, sizeof(reg->username));
05486    if (secret)
05487       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
05488    reg->expire = -1;
05489    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
05490    reg->addr.sin_family = AF_INET;
05491    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
05492    AST_LIST_LOCK(&registrations);
05493    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
05494    AST_LIST_UNLOCK(&registrations);
05495    
05496    return 0;
05497 }

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

Definition at line 9353 of file chan_iax2.c.

References reload_config().

09354 {
09355    return reload_config();
09356 }

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

Definition at line 8049 of file chan_iax2.c.

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

08050 {
08051    int callno;
08052    int res;
08053    int fmt, native;
08054    struct sockaddr_in sin;
08055    struct ast_channel *c;
08056    struct parsed_dial_string pds;
08057    struct create_addr_info cai;
08058    char *tmpstr;
08059 
08060    memset(&pds, 0, sizeof(pds));
08061    tmpstr = ast_strdupa(data);
08062    parse_dial_string(tmpstr, &pds);
08063 
08064    memset(&cai, 0, sizeof(cai));
08065    cai.capability = iax2_capability;
08066 
08067    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08068 
08069    if (!pds.peer) {
08070       ast_log(LOG_WARNING, "No peer given\n");
08071       return NULL;
08072    }
08073           
08074    
08075    /* Populate our address from the given */
08076    if (create_addr(pds.peer, &sin, &cai)) {
08077       *cause = AST_CAUSE_UNREGISTERED;
08078       return NULL;
08079    }
08080 
08081    if (pds.port)
08082       sin.sin_port = htons(atoi(pds.port));
08083 
08084    callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd);
08085    if (callno < 1) {
08086       ast_log(LOG_WARNING, "Unable to create call\n");
08087       *cause = AST_CAUSE_CONGESTION;
08088       return NULL;
08089    }
08090 
08091    ast_mutex_lock(&iaxsl[callno]);
08092 
08093    /* If this is a trunk, update it now */
08094    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08095    if (ast_test_flag(&cai, IAX_TRUNK))
08096       callno = make_trunk(callno, 1);
08097    iaxs[callno]->maxtime = cai.maxtime;
08098    if (cai.found)
08099       ast_string_field_set(iaxs[callno], host, pds.peer);
08100 
08101    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08102 
08103    ast_mutex_unlock(&iaxsl[callno]);
08104 
08105    if (c) {
08106       /* Choose a format we can live with */
08107       if (c->nativeformats & format) 
08108          c->nativeformats &= format;
08109       else {
08110          native = c->nativeformats;
08111          fmt = format;
08112          res = ast_translator_best_choice(&fmt, &native);
08113          if (res < 0) {
08114             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
08115                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
08116             ast_hangup(c);
08117             return NULL;
08118          }
08119          c->nativeformats = native;
08120       }
08121       c->readformat = ast_best_codec(c->nativeformats);
08122       c->writeformat = c->readformat;
08123    }
08124 
08125    return c;
08126 }

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

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

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

03828 {
03829    /* Queue a packet for delivery on a given private structure.  Use "ts" for
03830       timestamp, or calculate if ts is 0.  Send immediately without retransmission
03831       or delayed, with retransmission */
03832    struct ast_iax2_full_hdr *fh;
03833    struct ast_iax2_mini_hdr *mh;
03834    struct ast_iax2_video_hdr *vh;
03835    struct {
03836       struct iax_frame fr2;
03837       unsigned char buffer[4096];
03838    } frb;
03839    struct iax_frame *fr;
03840    int res;
03841    int sendmini=0;
03842    unsigned int lastsent;
03843    unsigned int fts;
03844       
03845    if (!pvt) {
03846       ast_log(LOG_WARNING, "No private structure for packet?\n");
03847       return -1;
03848    }
03849    
03850    lastsent = pvt->lastsent;
03851 
03852    /* Calculate actual timestamp */
03853    fts = calc_timestamp(pvt, ts, f);
03854 
03855    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
03856     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
03857     * increment the "predicted timestamps" for voice, if we're predecting */
03858    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
03859        return 0;
03860 
03861 
03862    if ((ast_test_flag(pvt, IAX_TRUNK) || 
03863          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
03864          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
03865       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
03866        (f->frametype == AST_FRAME_VOICE) 
03867       /* is a voice frame */ &&
03868       (f->subclass == pvt->svoiceformat) 
03869       /* is the same type */ ) {
03870          /* Force immediate rather than delayed transmission */
03871          now = 1;
03872          /* Mark that mini-style frame is appropriate */
03873          sendmini = 1;
03874    }
03875    if (((fts & 0xFFFF8000L) == (lastsent & 0xFFFF8000L)) && 
03876       (f->frametype == AST_FRAME_VIDEO) &&
03877       ((f->subclass & ~0x1) == pvt->svideoformat)) {
03878          now = 1;
03879          sendmini = 1;
03880    }
03881    /* Allocate an iax_frame */
03882    if (now) {
03883       fr = &frb.fr2;
03884    } else
03885       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));
03886    if (!fr) {
03887       ast_log(LOG_WARNING, "Out of memory\n");
03888       return -1;
03889    }
03890    /* Copy our prospective frame into our immediate or retransmitted wrapper */
03891    iax_frame_wrap(fr, f);
03892 
03893    fr->ts = fts;
03894    fr->callno = pvt->callno;
03895    fr->transfer = transfer;
03896    fr->final = final;
03897    if (!sendmini) {
03898       /* We need a full frame */
03899       if (seqno > -1)
03900          fr->oseqno = seqno;
03901       else
03902          fr->oseqno = pvt->oseqno++;
03903       fr->iseqno = pvt->iseqno;
03904       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
03905       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
03906       fh->ts = htonl(fr->ts);
03907       fh->oseqno = fr->oseqno;
03908       if (transfer) {
03909          fh->iseqno = 0;
03910       } else
03911          fh->iseqno = fr->iseqno;
03912       /* Keep track of the last thing we've acknowledged */
03913       if (!transfer)
03914          pvt->aseqno = fr->iseqno;
03915       fh->type = fr->af.frametype & 0xFF;
03916       if (fr->af.frametype == AST_FRAME_VIDEO)
03917          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
03918       else
03919          fh->csub = compress_subclass(fr->af.subclass);
03920       if (transfer) {
03921          fr->dcallno = pvt->transfercallno;
03922       } else
03923          fr->dcallno = pvt->peercallno;
03924       fh->dcallno = htons(fr->dcallno);
03925       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
03926       fr->data = fh;
03927       fr->retries = 0;
03928       /* Retry after 2x the ping time has passed */
03929       fr->retrytime = pvt->pingtime * 2;
03930       if (fr->retrytime < MIN_RETRY_TIME)
03931          fr->retrytime = MIN_RETRY_TIME;
03932       if (fr->retrytime > MAX_RETRY_TIME)
03933          fr->retrytime = MAX_RETRY_TIME;
03934       /* Acks' don't get retried */
03935       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
03936          fr->retries = -1;
03937       else if (f->frametype == AST_FRAME_VOICE)
03938          pvt->svoiceformat = f->subclass;
03939       else if (f->frametype == AST_FRAME_VIDEO)
03940          pvt->svideoformat = f->subclass & ~0x1;
03941       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
03942          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
03943             if (iaxdebug) {
03944                if (fr->transfer)
03945                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
03946                else
03947                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
03948             }
03949             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
03950          } else
03951             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
03952       }
03953    
03954       if (now) {
03955          res = send_packet(fr);
03956       } else
03957          res = iax2_transmit(fr);
03958    } else {
03959       if (ast_test_flag(pvt, IAX_TRUNK)) {
03960          iax2_trunk_queue(pvt, fr);
03961          res = 0;
03962       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
03963          /* Video frame have no sequence number */
03964          fr->oseqno = -1;
03965          fr->iseqno = -1;
03966          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
03967          vh->zeros = 0;
03968          vh->callno = htons(0x8000 | fr->callno);
03969          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
03970          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
03971          fr->data = vh;
03972          fr->retries = -1;
03973          res = send_packet(fr);        
03974       } else {
03975          /* Mini-frames have no sequence number */
03976          fr->oseqno = -1;
03977          fr->iseqno = -1;
03978          /* Mini frame will do */
03979          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
03980          mh->callno = htons(fr->callno);
03981          mh->ts = htons(fr->ts & 0xFFFF);
03982          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
03983          fr->data = mh;
03984          fr->retries = -1;
03985          if (pvt->transferring == TRANSFER_MEDIAPASS)
03986             fr->transfer = 1;
03987          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
03988             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
03989                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
03990             } else
03991                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
03992          }
03993          res = send_packet(fr);
03994       }
03995    }
03996    return res;
03997 }

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

Definition at line 2440 of file chan_iax2.c.

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

02441 {
02442    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02443 }

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

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

02436 {
02437    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02438 }

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

Definition at line 2428 of file chan_iax2.c.

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

02429 {
02430    
02431    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02432       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02433 }

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

Definition at line 3000 of file chan_iax2.c.

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

03001 {
03002    struct ast_option_header *h;
03003    int res;
03004 
03005    switch (option) {
03006    case AST_OPTION_TXGAIN:
03007    case AST_OPTION_RXGAIN:
03008       /* these two cannot be sent, because they require a result */
03009       errno = ENOSYS;
03010       return -1;
03011    default:
03012       if (!(h = ast_malloc(datalen + sizeof(*h))))
03013          return -1;
03014 
03015       h->flag = AST_OPTION_FLAG_REQUEST;
03016       h->option = htons(option);
03017       memcpy(h->data, data, datalen);
03018       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03019                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03020                  datalen + sizeof(*h), -1);
03021       free(h);
03022       return res;
03023    }
03024 }

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

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

02127 {
02128    struct iax2_dpcache *dp;
02129    char tmp[1024], *pc;
02130    int s;
02131    int x,y;
02132    struct timeval tv;
02133    gettimeofday(&tv, NULL);
02134    ast_mutex_lock(&dpcache_lock);
02135    dp = dpcache;
02136    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02137    while(dp) {
02138       s = dp->expiry.tv_sec - tv.tv_sec;
02139       tmp[0] = '\0';
02140       if (dp->flags & CACHE_FLAG_EXISTS)
02141          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02142       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02143          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02144       if (dp->flags & CACHE_FLAG_CANEXIST)
02145          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02146       if (dp->flags & CACHE_FLAG_PENDING)
02147          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02148       if (dp->flags & CACHE_FLAG_TIMEOUT)
02149          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02150       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02151          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02152       if (dp->flags & CACHE_FLAG_MATCHMORE)
02153          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02154       if (dp->flags & CACHE_FLAG_UNKNOWN)
02155          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02156       /* Trim trailing pipe */
02157       if (!ast_strlen_zero(tmp))
02158          tmp[strlen(tmp) - 1] = '\0';
02159       else
02160          ast_copy_string(tmp, "(none)", sizeof(tmp));
02161       y=0;
02162       pc = strchr(dp->peercontext, '@');
02163       if (!pc)
02164          pc = dp->peercontext;
02165       else
02166          pc++;
02167       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02168          if (dp->waiters[x] > -1)
02169             y++;
02170       if (s > 0)
02171          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02172       else
02173          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02174       dp = dp->next;
02175    }
02176    ast_mutex_unlock(&dpcache_lock);
02177    return RESULT_SUCCESS;
02178 }

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

Definition at line 4340 of file chan_iax2.c.

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

04341 {
04342 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04343 #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"
04344 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04345    int x;
04346    int numchans = 0;
04347 
04348    if (argc != 3)
04349       return RESULT_SHOWUSAGE;
04350    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04351    for (x=0;x<IAX_MAX_CALLS;x++) {
04352       ast_mutex_lock(&iaxsl[x]);
04353       if (iaxs[x]) {
04354          int lag, jitter, localdelay;
04355          jb_info jbinfo;
04356          
04357          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04358             jb_getinfo(iaxs[x]->jb, &jbinfo);
04359             jitter = jbinfo.jitter;
04360             localdelay = jbinfo.current - jbinfo.min;
04361          } else {
04362             jitter = -1;
04363             localdelay = 0;
04364          }
04365          lag = iaxs[x]->remote_rr.delay;
04366          ast_cli(fd, FORMAT,
04367             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04368             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04369             S_OR(iaxs[x]->username, "(None)"),
04370             iaxs[x]->callno, iaxs[x]->peercallno,
04371             iaxs[x]->oseqno, iaxs[x]->iseqno,
04372             lag,
04373             jitter,
04374             localdelay,
04375             ast_getformatname(iaxs[x]->voiceformat) );
04376          numchans++;
04377       }
04378       ast_mutex_unlock(&iaxsl[x]);
04379    }
04380    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04381    return RESULT_SUCCESS;
04382 #undef FORMAT
04383 #undef FORMAT2
04384 #undef FORMATB
04385 }

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

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

04252 {
04253 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04254 #if !defined(__FreeBSD__)
04255 #define FORMAT "%-15.15s  %-15d %-15d\n"
04256 #else /* __FreeBSD__ */
04257 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04258 #endif /* __FreeBSD__ */
04259    struct iax_firmware *cur;
04260    if ((argc != 3) && (argc != 4))
04261       return RESULT_SHOWUSAGE;
04262    ast_mutex_lock(&waresl.lock);
04263    
04264    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04265    for (cur = waresl.wares;cur;cur = cur->next) {
04266       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04267          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04268             (int)ntohl(cur->fwh->datalen));
04269    }
04270    ast_mutex_unlock(&waresl.lock);
04271    return RESULT_SUCCESS;
04272 #undef FORMAT
04273 #undef FORMAT2
04274 }

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

Definition at line 4463 of file chan_iax2.c.

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

04464 {
04465    int numchans = 0;
04466    if (argc != 3)
04467       return RESULT_SHOWUSAGE;
04468    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04469    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04470    numchans = ast_cli_netstats(NULL, fd, 1);
04471    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04472    return RESULT_SUCCESS;
04473 }

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

Show one peer in detail.

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

02019 {
02020    char status[30];
02021    char cbuf[256];
02022    struct iax2_peer *peer;
02023    char codec_buf[512];
02024    int x = 0, codec = 0, load_realtime = 0;
02025 
02026    if (argc < 4)
02027       return RESULT_SHOWUSAGE;
02028 
02029    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02030 
02031    peer = find_peer(argv[3], load_realtime);
02032    if (peer) {
02033       ast_cli(fd,"\n\n");
02034       ast_cli(fd, "  * Name       : %s\n", peer->name);
02035       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02036       ast_cli(fd, "  Context      : %s\n", peer->context);
02037       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02038       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02039       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02040       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02041       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02042       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));
02043       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02044       ast_cli(fd, "  Username     : %s\n", peer->username);
02045       ast_cli(fd, "  Codecs       : ");
02046       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02047       ast_cli(fd, "%s\n", codec_buf);
02048 
02049       ast_cli(fd, "  Codec Order  : (");
02050       for(x = 0; x < 32 ; x++) {
02051          codec = ast_codec_pref_index(&peer->prefs,x);
02052          if(!codec)
02053             break;
02054          ast_cli(fd, "%s", ast_getformatname(codec));
02055          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02056             ast_cli(fd, "|");
02057       }
02058 
02059       if (!x)
02060          ast_cli(fd, "none");
02061       ast_cli(fd, ")\n");
02062 
02063       ast_cli(fd, "  Status       : ");
02064       peer_status(peer, status, sizeof(status));   
02065       ast_cli(fd, "%s\n",status);
02066       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02067       ast_cli(fd,"\n");
02068       if (ast_test_flag(peer, IAX_TEMPONLY))
02069          destroy_peer(peer);
02070    } else {
02071       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02072       ast_cli(fd,"\n");
02073    }
02074 
02075    return RESULT_SUCCESS;
02076 }

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

Definition at line 4240 of file chan_iax2.c.

References __iax2_show_peers().

04241 {
04242    return __iax2_show_peers(0, fd, NULL, argc, argv);
04243 }

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

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

04313 {
04314 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04315 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04316    struct iax2_registry *reg = NULL;
04317 
04318    char host[80];
04319    char perceived[80];
04320    if (argc != 3)
04321       return RESULT_SHOWUSAGE;
04322    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04323    AST_LIST_LOCK(&registrations);
04324    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04325       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04326       if (reg->us.sin_addr.s_addr) 
04327          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04328       else
04329          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04330       ast_cli(fd, FORMAT, host, 
04331                (reg->dnsmgr) ? "Y" : "N", 
04332                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04333    }
04334    AST_LIST_UNLOCK(&registrations);
04335    return RESULT_SUCCESS;
04336 #undef FORMAT
04337 #undef FORMAT2
04338 }

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

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

02101 {
02102    struct iax_frame *cur;
02103    int cnt = 0, dead=0, final=0;
02104 
02105    if (argc != 3)
02106       return RESULT_SHOWUSAGE;
02107 
02108    AST_LIST_LOCK(&iaxq.queue);
02109    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02110       if (cur->retries < 0)
02111          dead++;
02112       if (cur->final)
02113          final++;
02114       cnt++;
02115    }
02116    AST_LIST_UNLOCK(&iaxq.queue);
02117 
02118    ast_cli(fd, "    IAX Statistics\n");
02119    ast_cli(fd, "---------------------\n");
02120    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02121    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02122    
02123    return RESULT_SUCCESS;
02124 }

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

Definition at line 4181 of file chan_iax2.c.

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

04182 {
04183    struct iax2_thread *thread = NULL;
04184    time_t t;
04185    int threadcount = 0, dynamiccount = 0;
04186    char type;
04187 
04188    if (argc != 3)
04189       return RESULT_SHOWUSAGE;
04190       
04191    ast_cli(fd, "IAX2 Thread Information\n");
04192    time(&t);
04193    ast_cli(fd, "Idle Threads:\n");
04194    AST_LIST_LOCK(&idle_list);
04195    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04196 #ifdef DEBUG_SCHED_MULTITHREAD
04197       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04198          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04199 #else
04200       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04201          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04202 #endif
04203       threadcount++;
04204    }
04205    AST_LIST_UNLOCK(&idle_list);
04206    ast_cli(fd, "Active Threads:\n");
04207    AST_LIST_LOCK(&active_list);
04208    AST_LIST_TRAVERSE(&active_list, thread, list) {
04209       if (thread->type == IAX_TYPE_DYNAMIC)
04210          type = 'D';
04211       else
04212          type = 'P';
04213 #ifdef DEBUG_SCHED_MULTITHREAD
04214       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04215          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04216 #else
04217       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04218          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04219 #endif
04220       threadcount++;
04221    }
04222    AST_LIST_UNLOCK(&active_list);
04223    ast_cli(fd, "Dynamic Threads:\n");
04224         AST_LIST_LOCK(&dynamic_list);
04225         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04226 #ifdef DEBUG_SCHED_MULTITHREAD
04227                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04228                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04229 #else
04230                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04231                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04232 #endif
04233       dynamiccount++;
04234         }
04235         AST_LIST_UNLOCK(&dynamic_list);
04236    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04237    return RESULT_SUCCESS;
04238 }

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

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

04000 {
04001    regex_t regexbuf;
04002    int havepattern = 0;
04003 
04004 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04005 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04006 
04007    struct iax2_user *user = NULL;
04008    char auth[90];
04009    char *pstr = "";
04010 
04011    switch (argc) {
04012    case 5:
04013       if (!strcasecmp(argv[3], "like")) {
04014          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04015             return RESULT_SHOWUSAGE;
04016          havepattern = 1;
04017       } else
04018          return RESULT_SHOWUSAGE;
04019    case 3:
04020       break;
04021    default:
04022       return RESULT_SHOWUSAGE;
04023    }
04024 
04025    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04026    AST_LIST_LOCK(&users);
04027    AST_LIST_TRAVERSE(&users, user, entry) {
04028       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04029          continue;
04030       
04031       if (!ast_strlen_zero(user->secret)) {
04032          ast_copy_string(auth,user->secret,sizeof(auth));
04033       } else if (!ast_strlen_zero(user->inkeys)) {
04034          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04035       } else
04036          ast_copy_string(auth, "-no secret-", sizeof(auth));
04037       
04038       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04039          pstr = "REQ Only";
04040       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04041          pstr = "Disabled";
04042       else
04043          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04044       
04045       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04046          user->contexts ? user->contexts->context : context,
04047          user->ha ? "Yes" : "No", pstr);
04048       
04049    }
04050    AST_LIST_UNLOCK(&users);
04051 
04052    if (havepattern)
04053       regfree(&regexbuf);
04054 
04055    return RESULT_SUCCESS;
04056 #undef FORMAT
04057 #undef FORMAT2
04058 }

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

Definition at line 3032 of file chan_iax2.c.

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

03033 {
03034    int res;
03035    struct iax_ie_data ied0;
03036    struct iax_ie_data ied1;
03037    unsigned int transferid = (unsigned int)ast_random();
03038    memset(&ied0, 0, sizeof(ied0));
03039    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03040    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03041    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03042 
03043    memset(&ied1, 0, sizeof(ied1));
03044    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03045    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03046    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03047    
03048    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03049    if (res)
03050       return -1;
03051    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03052    if (res)
03053       return -1;
03054    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03055    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03056    return 0;
03057 }

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

Definition at line 1949 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01950 {
01951        if (argc != 4)
01952                return RESULT_SHOWUSAGE;
01953 
01954        test_losspct = atoi(argv[3]);
01955 
01956        return RESULT_SUCCESS;
01957 }

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

Definition at line 3260 of file chan_iax2.c.

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

03261 {
03262    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03263    struct iax_ie_data ied;
03264    char tmp[256], *context;
03265    ast_copy_string(tmp, dest, sizeof(tmp));
03266    context = strchr(tmp, '@');
03267    if (context) {
03268       *context = '\0';
03269       context++;
03270    }
03271    memset(&ied, 0, sizeof(ied));
03272    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03273    if (context)
03274       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03275    if (option_debug)
03276       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03277    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03278 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

02400 {
02401    /* Lock the queue and place this packet at the end */
02402    /* By setting this to 0, the network thread will send it for us, and
02403       queue retransmission if necessary */
02404    fr->sentyet = 0;
02405    AST_LIST_LOCK(&iaxq.queue);
02406    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02407    iaxq.count++;
02408    AST_LIST_UNLOCK(&iaxq.queue);
02409    /* Wake up the network and scheduler thread */
02410    if (netthreadid != AST_PTHREADT_NULL)
02411       pthread_kill(netthreadid, SIGURG);
02412    signal_condition(&sched_lock, &sched_cond);
02413    return 0;
02414 }

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

Definition at line 5968 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

05969 {
05970    /* Drop when trunk is about 5 seconds idle */
05971    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
05972       return 1;
05973    return 0;
05974 }

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

Definition at line 3602 of file chan_iax2.c.

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

Referenced by iax2_send().

03603 {
03604    struct ast_frame *f;
03605    struct iax2_trunk_peer *tpeer;
03606    void *tmp, *ptr;
03607    struct ast_iax2_meta_trunk_entry *met;
03608    struct ast_iax2_meta_trunk_mini *mtm;
03609 
03610    f = &fr->af;
03611    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
03612    if (tpeer) {
03613       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
03614          /* Need to reallocate space */
03615          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
03616             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
03617                ast_mutex_unlock(&tpeer->lock);
03618                return -1;
03619             }
03620             
03621             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
03622             tpeer->trunkdata = tmp;
03623             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);
03624          } else {
03625             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));
03626             ast_mutex_unlock(&tpeer->lock);
03627             return -1;
03628          }
03629       }
03630 
03631       /* Append to meta frame */
03632       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
03633       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
03634          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
03635          mtm->len = htons(f->datalen);
03636          mtm->mini.callno = htons(pvt->callno);
03637          mtm->mini.ts = htons(0xffff & fr->ts);
03638          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
03639          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
03640       } else {
03641          met = (struct ast_iax2_meta_trunk_entry *)ptr;
03642          /* Store call number and length in meta header */
03643          met->callno = htons(pvt->callno);
03644          met->len = htons(f->datalen);
03645          /* Advance pointers/decrease length past trunk entry header */
03646          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
03647          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
03648       }
03649       /* Copy actual trunk data */
03650       memcpy(ptr, f->data, f->datalen);
03651       tpeer->trunkdatalen += f->datalen;
03652 
03653       tpeer->calls++;
03654       ast_mutex_unlock(&tpeer->lock);
03655    }
03656    return 0;
03657 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 5888 of file chan_iax2.c.

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

Referenced by socket_process().

05889 {
05890    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
05891 }

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

Definition at line 4530 of file chan_iax2.c.

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

04531 {
04532    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04533    int res = -1;
04534    ast_mutex_lock(&iaxsl[callno]);
04535    if (iaxs[callno]) {
04536    /* If there's an outstanding error, return failure now */
04537       if (!iaxs[callno]->error) {
04538          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
04539             res = 0;
04540             /* Don't waste bandwidth sending null frames */
04541          else if (f->frametype == AST_FRAME_NULL)
04542             res = 0;
04543          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
04544             res = 0;
04545          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
04546             res = 0;
04547          else
04548          /* Simple, just queue for transmission */
04549             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
04550       } else {
04551          ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
04552       }
04553    }
04554    /* If it's already gone, just return */
04555    ast_mutex_unlock(&iaxsl[callno]);
04556    return res;
04557 }

static int iax_check_version ( char *  dev  )  [static]

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

01485 {
01486    int res = 0;
01487    struct iax_firmware *cur;
01488    if (!ast_strlen_zero(dev)) {
01489       ast_mutex_lock(&waresl.lock);
01490       cur = waresl.wares;
01491       while(cur) {
01492          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01493             res = ntohs(cur->fwh->version);
01494             break;
01495          }
01496          cur = cur->next;
01497       }
01498       ast_mutex_unlock(&waresl.lock);
01499    }
01500    return res;
01501 }

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

Definition at line 719 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

00720 {
00721    if (iaxdebug)
00722       ast_verbose("%s", data);
00723 }

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

Definition at line 725 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00726 {
00727    ast_log(LOG_WARNING, "%s", data);
00728 }

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

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

01504 {
01505    int res = -1;
01506    unsigned int bs = desc & 0xff;
01507    unsigned int start = (desc >> 8) & 0xffffff;
01508    unsigned int bytes;
01509    struct iax_firmware *cur;
01510    if (!ast_strlen_zero((char *)dev) && bs) {
01511       start *= bs;
01512       ast_mutex_lock(&waresl.lock);
01513       cur = waresl.wares;
01514       while(cur) {
01515          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01516             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01517             if (start < ntohl(cur->fwh->datalen)) {
01518                bytes = ntohl(cur->fwh->datalen) - start;
01519                if (bytes > bs)
01520                   bytes = bs;
01521                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01522             } else {
01523                bytes = 0;
01524                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01525             }
01526             if (bytes == bs)
01527                res = 0;
01528             else
01529                res = 1;
01530             break;
01531          }
01532          cur = cur->next;
01533       }
01534       ast_mutex_unlock(&waresl.lock);
01535    }
01536    return res;
01537 }

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

Definition at line 6150 of file chan_iax2.c.

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

Referenced by socket_process().

06151 {
06152    struct iax_dual *d;
06153    struct ast_channel *chan1m, *chan2m;
06154    pthread_t th;
06155    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06156    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06157    if (chan2m && chan1m) {
06158       /* Make formats okay */
06159       chan1m->readformat = chan1->readformat;
06160       chan1m->writeformat = chan1->writeformat;
06161       ast_channel_masquerade(chan1m, chan1);
06162       /* Setup the extensions and such */
06163       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06164       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06165       chan1m->priority = chan1->priority;
06166       
06167       /* We make a clone of the peer channel too, so we can play
06168          back the announcement */
06169       /* Make formats okay */
06170       chan2m->readformat = chan2->readformat;
06171       chan2m->writeformat = chan2->writeformat;
06172       ast_channel_masquerade(chan2m, chan2);
06173       /* Setup the extensions and such */
06174       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06175       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06176       chan2m->priority = chan2->priority;
06177       if (ast_do_masquerade(chan2m)) {
06178          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06179          ast_hangup(chan2m);
06180          return -1;
06181       }
06182    } else {
06183       if (chan1m)
06184          ast_hangup(chan1m);
06185       if (chan2m)
06186          ast_hangup(chan2m);
06187       return -1;
06188    }
06189    if ((d = ast_calloc(1, sizeof(*d)))) {
06190       pthread_attr_t attr;
06191 
06192       pthread_attr_init(&attr);
06193       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06194 
06195       d->chan1 = chan1m;
06196       d->chan2 = chan2m;
06197       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06198          pthread_attr_destroy(&attr);
06199          return 0;
06200       }
06201       pthread_attr_destroy(&attr);
06202       free(d);
06203    }
06204    return -1;
06205 }

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

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

06131 {
06132    struct ast_channel *chan1, *chan2;
06133    struct iax_dual *d;
06134    struct ast_frame *f;
06135    int ext;
06136    int res;
06137    d = stuff;
06138    chan1 = d->chan1;
06139    chan2 = d->chan2;
06140    free(d);
06141    f = ast_read(chan1);
06142    if (f)
06143       ast_frfree(f);
06144    res = ast_park_call(chan1, chan2, 0, &ext);
06145    ast_hangup(chan2);
06146    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06147    return NULL;
06148 }

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

Definition at line 1090 of file chan_iax2.c.

References iax_frame::af, iax_frame::cacheable, ast_frame::datalen, DIRECTION_INGRESS, iax_frame_new(), iax_frame_wrap(), and iax_frame::mallocd_datalen.

Referenced by socket_process().

01091 {
01092    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01093    if (new) {
01094       size_t mallocd_datalen = new->mallocd_datalen;
01095       memcpy(new, fr, sizeof(*new));
01096       iax_frame_wrap(new, &fr->af);
01097       new->mallocd_datalen = mallocd_datalen;
01098       new->data = NULL;
01099       new->datalen = 0;
01100       new->direction = DIRECTION_INGRESS;
01101       new->retrans = -1;
01102    }
01103    return new;
01104 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 829 of file chan_iax2.c.

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

Referenced by iax2_process_thread(), and socket_read().

00830 {
00831    if (thread->type == IAX_TYPE_DYNAMIC) {
00832       AST_LIST_LOCK(&dynamic_list);
00833       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00834       AST_LIST_UNLOCK(&dynamic_list);
00835    } else {
00836       AST_LIST_LOCK(&idle_list);
00837       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00838       AST_LIST_UNLOCK(&idle_list);
00839    }
00840 
00841    return;
00842 }

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

Definition at line 754 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

00755 {
00756    va_list args;
00757    char buf[1024];
00758 
00759    va_start(args, fmt);
00760    vsnprintf(buf, 1024, fmt, args);
00761    va_end(args);
00762 
00763    ast_verbose(buf);
00764 }

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

Definition at line 730 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

00731 {
00732    va_list args;
00733    char buf[1024];
00734 
00735    va_start(args, fmt);
00736    vsnprintf(buf, 1024, fmt, args);
00737    va_end(args);
00738 
00739    ast_log(LOG_ERROR, buf);
00740 }

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

Definition at line 742 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

00743 {
00744    va_list args;
00745    char buf[1024];
00746 
00747    va_start(args, fmt);
00748    vsnprintf(buf, 1024, fmt, args);
00749    va_end(args);
00750 
00751    ast_log(LOG_WARNING, buf);
00752 }

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 10146 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_provision_reload(), iax_set_error(), iax_set_output(), iaxpeer_function, iaxq, iaxs, iaxsl, iaxvar_function, io, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), netsock, option_verbose, outsock, reload_firmware(), sched, sched_context_create(), set_config(), iax2_peer::sockfd, start_network_thread(), VERBOSE_PREFIX_2, and waresl.

10147 {
10148    char *config = "iax.conf";
10149    int res = 0;
10150    int x;
10151    struct iax2_registry *reg = NULL;
10152    struct iax2_peer *peer = NULL;
10153    
10154    ast_custom_function_register(&iaxpeer_function);
10155    ast_custom_function_register(&iaxvar_function);
10156 
10157    iax_set_output(iax_debug_output);
10158    iax_set_error(iax_error_output);
10159    jb_setoutput(jb_error_output, jb_warning_output, NULL);
10160    
10161 #ifdef HAVE_ZAPTEL
10162 #ifdef ZT_TIMERACK
10163    timingfd = open("/dev/zap/timer", O_RDWR);
10164    if (timingfd < 0)
10165 #endif
10166       timingfd = open("/dev/zap/pseudo", O_RDWR);
10167    if (timingfd < 0) 
10168       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
10169 #endif      
10170 
10171    memset(iaxs, 0, sizeof(iaxs));
10172 
10173    for (x=0;x<IAX_MAX_CALLS;x++)
10174       ast_mutex_init(&iaxsl[x]);
10175    
10176    ast_cond_init(&sched_cond, NULL);
10177 
10178    io = io_context_create();
10179    sched = sched_context_create();
10180    
10181    if (!io || !sched) {
10182       ast_log(LOG_ERROR, "Out of memory\n");
10183       return -1;
10184    }
10185 
10186    netsock = ast_netsock_list_alloc();
10187    if (!netsock) {
10188       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
10189       return -1;
10190    }
10191    ast_netsock_init(netsock);
10192 
10193    outsock = ast_netsock_list_alloc();
10194    if (!outsock) {
10195       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10196       return -1;
10197    }
10198    ast_netsock_init(outsock);
10199 
10200    ast_mutex_init(&waresl.lock);
10201 
10202    AST_LIST_HEAD_INIT(&iaxq.queue);
10203    
10204    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10205 
10206    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
10207    
10208    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
10209    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
10210 
10211    if(set_config(config, 0) == -1)
10212       return AST_MODULE_LOAD_DECLINE;
10213 
10214    if (ast_channel_register(&iax2_tech)) {
10215       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
10216       __unload_module();
10217       return -1;
10218    }
10219 
10220    if (ast_register_switch(&iax2_switch)) 
10221       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
10222 
10223    res = start_network_thread();
10224    if (!res) {
10225       if (option_verbose > 1) 
10226          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
10227    } else {
10228       ast_log(LOG_ERROR, "Unable to start network thread\n");
10229       ast_netsock_release(netsock);
10230       ast_netsock_release(outsock);
10231    }
10232 
10233    AST_LIST_LOCK(&registrations);
10234    AST_LIST_TRAVERSE(&registrations, reg, entry)
10235       iax2_do_register(reg);
10236    AST_LIST_UNLOCK(&registrations); 
10237 
10238    AST_LIST_LOCK(&peers);
10239    AST_LIST_TRAVERSE(&peers, peer, entry) {
10240       if (peer->sockfd < 0)
10241          peer->sockfd = defaultsockfd;
10242       iax2_poke_peer(peer, 0);
10243    }
10244    AST_LIST_UNLOCK(&peers);
10245    reload_firmware();
10246    iax_provision_reload();
10247    return res;
10248 }

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

Definition at line 3059 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03060 {
03061    ast_mutex_lock(&iaxsl[callno0]);
03062    while (ast_mutex_trylock(&iaxsl[callno1])) {
03063       ast_mutex_unlock(&iaxsl[callno0]);
03064       usleep(10);
03065       ast_mutex_lock(&iaxsl[callno0]);
03066    }
03067 }

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

Definition at line 1158 of file chan_iax2.c.

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

Referenced by iax2_request(), and socket_process().

01159 {
01160    int x;
01161    int res= 0;
01162    struct timeval now;
01163    if (iaxs[callno]->oseqno) {
01164       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01165       return -1;
01166    }
01167    if (callno & TRUNK_CALL_START) {
01168       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01169       return -1;
01170    }
01171    gettimeofday(&now, NULL);
01172    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01173       ast_mutex_lock(&iaxsl[x]);
01174       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01175          iaxs[x] = iaxs[callno];
01176          iaxs[x]->callno = x;
01177          iaxs[callno] = NULL;
01178          /* Update the two timers that should have been started */
01179          if (iaxs[x]->pingid > -1)
01180             ast_sched_del(sched, iaxs[x]->pingid);
01181          if (iaxs[x]->lagid > -1)
01182             ast_sched_del(sched, iaxs[x]->lagid);
01183          iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01184          iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01185          if (locked)
01186             ast_mutex_unlock(&iaxsl[callno]);
01187          res = x;
01188          if (!locked)
01189             ast_mutex_unlock(&iaxsl[x]);
01190          break;
01191       }
01192       ast_mutex_unlock(&iaxsl[x]);
01193    }
01194    if (x >= IAX_MAX_CALLS - 1) {
01195       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01196       return -1;
01197    }
01198    ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
01199    /* We move this call from a non-trunked to a trunked call */
01200    update_max_trunk();
01201    update_max_nontrunk();
01202    return res;
01203 }

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

Definition at line 4244 of file chan_iax2.c.

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

Referenced by load_module().

04245 {
04246    ast_cli_netstats(s, -1, 0);
04247    astman_append(s, "\r\n");
04248    return RESULT_SUCCESS;
04249 }

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

Definition at line 4277 of file chan_iax2.c.

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

Referenced by load_module().

04278 {
04279    char *a[] = { "iax2", "show", "users" };
04280    int ret;
04281    const char *id = astman_get_header(m,"ActionID");
04282 
04283    if (!ast_strlen_zero(id))
04284       astman_append(s, "ActionID: %s\r\n",id);
04285    ret = __iax2_show_peers(1, -1, s, 3, a );
04286    astman_append(s, "\r\n\r\n" );
04287    return ret;
04288 } /* /JDG */

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

Definition at line 1110 of file chan_iax2.c.

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

01111 {
01112    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01113       (cur->addr.sin_port == sin->sin_port)) {
01114       /* This is the main host */
01115       if ((cur->peercallno == callno) ||
01116          ((dcallno == cur->callno) && !cur->peercallno)) {
01117          /* That's us.  Be sure we keep track of the peer call number */
01118          return 1;
01119       }
01120    }
01121    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01122        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01123       /* We're transferring */
01124       if (dcallno == cur->callno)
01125          return 1;
01126    }
01127    return 0;
01128 }

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

Definition at line 3665 of file chan_iax2.c.

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

Referenced by decode_frame().

03666 {
03667 #if 0
03668    /* Debug with "fake encryption" */
03669    int x;
03670    if (len % 16)
03671       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03672    for (x=0;x<len;x++)
03673       dst[x] = src[x] ^ 0xff;
03674 #else 
03675    unsigned char lastblock[16] = { 0 };
03676    int x;
03677    while(len > 0) {
03678       aes_decrypt(src, dst, dcx);
03679       for (x=0;x<16;x++)
03680          dst[x] ^= lastblock[x];
03681       memcpy(lastblock, src, sizeof(lastblock));
03682       dst += 16;
03683       src += 16;
03684       len -= 16;
03685    }
03686 #endif
03687 }

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

Definition at line 3689 of file chan_iax2.c.

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

Referenced by encrypt_frame().

03690 {
03691 #if 0
03692    /* Debug with "fake encryption" */
03693    int x;
03694    if (len % 16)
03695       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03696    for (x=0;x<len;x++)
03697       dst[x] = src[x] ^ 0xff;
03698 #else
03699    unsigned char curblock[16] = { 0 };
03700    int x;
03701    while(len > 0) {
03702       for (x=0;x<16;x++)
03703          curblock[x] ^= src[x];
03704       aes_encrypt(curblock, dst, ecx);
03705       memcpy(curblock, dst, sizeof(curblock)); 
03706       dst += 16;
03707       src += 16;
03708       len -= 16;
03709    }
03710 #endif
03711 }

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

Definition at line 4835 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

04836 {
04837    /* Select exactly one common encryption if there are any */
04838    p->encmethods &= enc;
04839    if (p->encmethods) {
04840       if (p->encmethods & IAX_ENCRYPT_AES128)
04841          p->encmethods = IAX_ENCRYPT_AES128;
04842       else
04843          p->encmethods = 0;
04844    }
04845 }

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

Definition at line 8156 of file chan_iax2.c.

References ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_sched_add(), attempt_transmit(), f, iax_frame_free(), iaxq, iaxs, iaxsl, io, sched, send_packet(), signal_condition(), and timing_read().

Referenced by start_network_thread().

08157 {
08158    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
08159       from the network, and queue them for delivery to the channels */
08160    int res, count, wakeup;
08161    struct iax_frame *f;
08162 
08163    if (timingfd > -1)
08164       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
08165    
08166    for(;;) {
08167       pthread_testcancel();
08168 
08169       /* Go through the queue, sending messages which have not yet been
08170          sent, and scheduling retransmissions if appropriate */
08171       AST_LIST_LOCK(&iaxq.queue);
08172       count = 0;
08173       wakeup = -1;
08174       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
08175          if (f->sentyet)
08176             continue;
08177          
08178          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
08179          if (ast_mutex_trylock(&iaxsl[f->callno])) {
08180             wakeup = 1;
08181             continue;
08182          }
08183 
08184          f->sentyet++;
08185 
08186          if (iaxs[f->callno]) {
08187             send_packet(f);
08188             count++;
08189          } 
08190 
08191          ast_mutex_unlock(&iaxsl[f->callno]);
08192 
08193          if (f->retries < 0) {
08194             /* This is not supposed to be retransmitted */
08195             AST_LIST_REMOVE(&iaxq.queue, f, list);
08196             iaxq.count--;
08197             /* Free the iax frame */
08198             iax_frame_free(f);
08199          } else {
08200             /* We need reliable delivery.  Schedule a retransmission */
08201             f->retries++;
08202             f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f);
08203             signal_condition(&sched_lock, &sched_cond);
08204          }
08205       }
08206       AST_LIST_TRAVERSE_SAFE_END
08207       AST_LIST_UNLOCK(&iaxq.queue);
08208 
08209       pthread_testcancel();
08210 
08211       if (count >= 20)
08212          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
08213 
08214       /* Now do the IO, and run scheduled tasks */
08215       res = ast_io_wait(io, wakeup);
08216       if (res >= 0) {
08217          if (res >= 20)
08218             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
08219       }
08220    }
08221    return NULL;
08222 }

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

Definition at line 1052 of file chan_iax2.c.

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

Referenced by find_callno().

01053 {
01054    struct chan_iax2_pvt *tmp;
01055    jb_conf jbconf;
01056 
01057    if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01058       return NULL;
01059 
01060    if (ast_string_field_init(tmp, 32)) {
01061       free(tmp);
01062       tmp = NULL;
01063       return NULL;
01064    }
01065       
01066    tmp->prefs = prefs;
01067    tmp->callno = 0;
01068    tmp->peercallno = 0;
01069    tmp->transfercallno = 0;
01070    tmp->bridgecallno = 0;
01071    tmp->pingid = -1;
01072    tmp->lagid = -1;
01073    tmp->autoid = -1;
01074    tmp->authid = -1;
01075    tmp->initid = -1;
01076 
01077    ast_string_field_set(tmp,exten, "s");
01078    ast_string_field_set(tmp,host, host);
01079 
01080    tmp->jb = jb_new();
01081    tmp->jbid = -1;
01082    jbconf.max_jitterbuf = maxjitterbuffer;
01083    jbconf.resync_threshold = resyncthreshold;
01084    jbconf.max_contig_interp = maxjitterinterps;
01085    jb_setconf(tmp->jb,&jbconf);
01086 
01087    return tmp;
01088 }

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

02782 {
02783    if (ast_strlen_zero(data))
02784       return;
02785 
02786    pds->peer = strsep(&data, "/");
02787    pds->exten = strsep(&data, "/");
02788    pds->options = data;
02789 
02790    if (pds->exten) {
02791       data = pds->exten;
02792       pds->exten = strsep(&data, "@");
02793       pds->context = data;
02794    }
02795 
02796    if (strchr(pds->peer, '@')) {
02797       data = pds->peer;
02798       pds->username = strsep(&data, "@");
02799       pds->peer = data;
02800    }
02801 
02802    if (pds->username) {
02803       data = pds->username;
02804       pds->username = strsep(&data, ":");
02805       pds->password = data;
02806    }
02807 
02808    data = pds->peer;
02809    pds->peer = strsep(&data, ":");
02810    pds->port = data;
02811 
02812    /* check for a key name wrapped in [] in the secret position, if found,
02813       move it to the key field instead
02814    */
02815    if (pds->password && (pds->password[0] == '[')) {
02816       pds->key = ast_strip_quoted(pds->password, "[", "]");
02817       pds->password = NULL;
02818    }
02819 }

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

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

Referenced by build_peer().

08307 {
08308    struct sockaddr_in sin;
08309    int nonlocal = 1;
08310    int port = IAX_DEFAULT_PORTNO;
08311    int sockfd = defaultsockfd;
08312    char *tmp;
08313    char *addr;
08314    char *portstr;
08315 
08316    if (!(tmp = ast_strdupa(srcaddr)))
08317       return -1;
08318 
08319    addr = strsep(&tmp, ":");
08320    portstr = tmp;
08321 
08322    if (portstr) {
08323       port = atoi(portstr);
08324       if (port < 1)
08325          port = IAX_DEFAULT_PORTNO;
08326    }
08327    
08328    if (!ast_get_ip(&sin, addr)) {
08329       struct ast_netsock *sock;
08330       int res;
08331 
08332       sin.sin_port = 0;
08333       sin.sin_family = AF_INET;
08334       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
08335       if (res == 0) {
08336          /* ip address valid. */
08337          sin.sin_port = htons(port);
08338          if (!(sock = ast_netsock_find(netsock, &sin)))
08339             sock = ast_netsock_find(outsock, &sin);
08340          if (sock) {
08341             sockfd = ast_netsock_sockfd(sock);
08342             nonlocal = 0;
08343          } else {
08344             unsigned int orig_saddr = sin.sin_addr.s_addr;
08345             /* INADDR_ANY matches anyway! */
08346             sin.sin_addr.s_addr = INADDR_ANY;
08347             if (ast_netsock_find(netsock, &sin)) {
08348                sin.sin_addr.s_addr = orig_saddr;
08349                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
08350                if (sock) {
08351                   sockfd = ast_netsock_sockfd(sock);
08352                   ast_netsock_unref(sock);
08353                   nonlocal = 0;
08354                } else {
08355                   nonlocal = 2;
08356                }
08357             }
08358          }
08359       }
08360    }
08361       
08362    peer->sockfd = sockfd;
08363 
08364    if (nonlocal == 1) {
08365       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
08366          srcaddr, peer->name);
08367       return -1;
08368         } else if (nonlocal == 2) {
08369       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
08370          srcaddr, peer->name);
08371          return -1;
08372    } else {
08373       ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
08374       return 0;
08375    }
08376 }

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

peer_status: Report Peer status in character string

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

01996 {
01997    int res = 0;
01998    if (peer->maxms) {
01999       if (peer->lastms < 0) {
02000          ast_copy_string(status, "UNREACHABLE", statuslen);
02001       } else if (peer->lastms > peer->maxms) {
02002          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02003          res = 1;
02004       } else if (peer->lastms) {
02005          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02006          res = 1;
02007       } else {
02008          ast_copy_string(status, "UNKNOWN", statuslen);
02009       }
02010    } else { 
02011       ast_copy_string(status, "Unmonitored", statuslen);
02012       res = -1;
02013    }
02014    return res;
02015 }

static void prune_peers ( void   )  [static]

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

08929                              {
08930    /* Prune peers who still are supposed to be deleted */
08931    struct iax2_peer *peer = NULL;
08932 
08933    AST_LIST_LOCK(&peers);
08934    AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, entry) {
08935       if (ast_test_flag(peer, IAX_DELME)) {
08936          destroy_peer(peer);
08937          AST_LIST_REMOVE_CURRENT(&peers, entry);
08938       }
08939    }
08940    AST_LIST_TRAVERSE_SAFE_END
08941    AST_LIST_UNLOCK(&peers);
08942 }

static void prune_users ( void   )  [static]

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

08889 {
08890    struct iax2_user *user = NULL;
08891 
08892    AST_LIST_LOCK(&users);
08893    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, entry) {
08894       if (ast_test_flag(user, IAX_DELME)) {
08895          destroy_user(user);
08896          AST_LIST_REMOVE_CURRENT(&users, entry);
08897       }
08898    }
08899    AST_LIST_TRAVERSE_SAFE_END
08900    AST_LIST_UNLOCK(&users);
08901 
08902 }

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

Definition at line 4815 of file chan_iax2.c.

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

Referenced by socket_process().

04816 {
04817    struct ast_iax2_full_hdr fh;
04818    fh.scallno = htons(src | IAX_FLAG_FULL);
04819    fh.dcallno = htons(dst);
04820    fh.ts = 0;
04821    fh.oseqno = 0;
04822    fh.iseqno = 0;
04823    fh.type = AST_FRAME_IAX;
04824    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
04825    if (iaxdebug)
04826        iax_showframe(NULL, &fh, 0, sin, 0);
04827 #if 0
04828    if (option_debug)
04829 #endif   
04830       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
04831          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
04832    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
04833 }

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

Definition at line 2457 of file chan_iax2.c.

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

02458 {
02459    struct ast_variable *var;
02460    struct ast_variable *tmp;
02461    struct iax2_peer *peer=NULL;
02462    time_t regseconds = 0, nowtime;
02463    int dynamic=0;
02464 
02465    if (peername)
02466       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
02467    else {
02468       char porta[25];
02469       sprintf(porta, "%d", ntohs(sin->sin_port));
02470       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02471       if (var) {
02472          /* We'll need the peer name in order to build the structure! */
02473          for (tmp = var; tmp; tmp = tmp->next) {
02474             if (!strcasecmp(tmp->name, "name"))
02475                peername = tmp->value;
02476          }
02477       }
02478    }
02479    if (!var)
02480       return NULL;
02481 
02482    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
02483    
02484    if (!peer) {
02485       ast_variables_destroy(var);
02486       return NULL;
02487    }
02488 
02489    for (tmp = var; tmp; tmp = tmp->next) {
02490       /* Make sure it's not a user only... */
02491       if (!strcasecmp(tmp->name, "type")) {
02492          if (strcasecmp(tmp->value, "friend") &&
02493              strcasecmp(tmp->value, "peer")) {
02494             /* Whoops, we weren't supposed to exist! */
02495             destroy_peer(peer);
02496             peer = NULL;
02497             break;
02498          } 
02499       } else if (!strcasecmp(tmp->name, "regseconds")) {
02500          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
02501       } else if (!strcasecmp(tmp->name, "ipaddr")) {
02502          inet_aton(tmp->value, &(peer->addr.sin_addr));
02503       } else if (!strcasecmp(tmp->name, "port")) {
02504          peer->addr.sin_port = htons(atoi(tmp->value));
02505       } else if (!strcasecmp(tmp->name, "host")) {
02506          if (!strcasecmp(tmp->value, "dynamic"))
02507             dynamic = 1;
02508       }
02509    }
02510 
02511    ast_variables_destroy(var);
02512 
02513    if (!peer)
02514       return NULL;
02515 
02516    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02517       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
02518       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
02519          if (peer->expire > -1)
02520             ast_sched_del(sched, peer->expire);
02521          peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, (void*)peer->name);
02522       }
02523       AST_LIST_LOCK(&peers);
02524       AST_LIST_INSERT_HEAD(&peers, peer, entry);
02525       AST_LIST_UNLOCK(&peers);
02526       if (ast_test_flag(peer, IAX_DYNAMIC))
02527          reg_source_db(peer);
02528    } else {
02529       ast_set_flag(peer, IAX_TEMPONLY);   
02530    }
02531 
02532    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
02533       time(&nowtime);
02534       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
02535          memset(&peer->addr, 0, sizeof(peer->addr));
02536          realtime_update_peer(peer->name, &peer->addr, 0);
02537          if (option_debug)
02538             ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
02539                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02540       }
02541       else {
02542          if (option_debug)
02543             ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
02544                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02545       }
02546    }
02547 
02548    return peer;
02549 }

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

Definition at line 2592 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02593 {
02594    char port[10];
02595    char regseconds[20];
02596    
02597    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
02598    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
02599    ast_update_realtime("iaxpeers", "name", peername, 
02600       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
02601       "regseconds", regseconds, NULL);
02602 }

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

Definition at line 2551 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(), globalflags, IAX_RTCACHEFRIENDS, IAX_TEMPONLY, ast_variable::name, ast_variable::next, ast_variable::value, and var.

02552 {
02553    struct ast_variable *var;
02554    struct ast_variable *tmp;
02555    struct iax2_user *user=NULL;
02556 
02557    var = ast_load_realtime("iaxusers", "name", username, NULL);
02558    if (!var)
02559       return NULL;
02560 
02561    tmp = var;
02562    while(tmp) {
02563       /* Make sure it's not a peer only... */
02564       if (!strcasecmp(tmp->name, "type")) {
02565          if (strcasecmp(tmp->value, "friend") &&
02566              strcasecmp(tmp->value, "user")) {
02567             return NULL;
02568          } 
02569       }
02570       tmp = tmp->next;
02571    }
02572 
02573    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
02574 
02575    ast_variables_destroy(var);
02576 
02577    if (!user)
02578       return NULL;
02579 
02580    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02581       ast_set_flag(user, IAX_RTCACHEFRIENDS);
02582       AST_LIST_LOCK(&users);
02583       AST_LIST_INSERT_HEAD(&users, user, entry);
02584       AST_LIST_UNLOCK(&users);
02585    } else {
02586       ast_set_flag(user, IAX_TEMPONLY);   
02587    }
02588 
02589    return user;
02590 }

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 5570 of file chan_iax2.c.

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

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

05571 {
05572    char data[80];
05573    struct in_addr in;
05574    char *c, *d;
05575    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
05576       c = strchr(data, ':');
05577       if (c) {
05578          *c = '\0';
05579          c++;
05580          if (inet_aton(data, &in)) {
05581             d = strchr(c, ':');
05582             if (d) {
05583                *d = '\0';
05584                d++;
05585                if (option_verbose > 2)
05586                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
05587                   ast_inet_ntoa(in), atoi(c), atoi(d));
05588                iax2_poke_peer(p, 0);
05589                p->expiry = atoi(d);
05590                memset(&p->addr, 0, sizeof(p->addr));
05591                p->addr.sin_family = AF_INET;
05592                p->addr.sin_addr = in;
05593                p->addr.sin_port = htons(atoi(c));
05594                if (p->expire > -1)
05595                   ast_sched_del(sched, p->expire);
05596                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05597                p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
05598                if (iax2_regfunk)
05599                   iax2_regfunk(p->name, 1);
05600                register_peer_exten(p, 1);
05601             }              
05602                
05603          }
05604       }
05605    }
05606 }

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

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

05500 {
05501    char multi[256];
05502    char *stringp, *ext;
05503    if (!ast_strlen_zero(regcontext)) {
05504       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
05505       stringp = multi;
05506       while((ext = strsep(&stringp, "&"))) {
05507          if (onoff) {
05508             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
05509                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
05510                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
05511          } else
05512             ast_context_remove_extension(regcontext, ext, 1, NULL);
05513       }
05514    }
05515 }

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

Verify inbound registration.

Definition at line 4976 of file chan_iax2.c.

References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, destroy_peer(), 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, ies, inaddrcmp(), key(), LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), and strsep().

Referenced by handle_request_register(), and socket_process().

04977 {
04978    char requeststr[256] = "";
04979    char peer[256] = "";
04980    char md5secret[256] = "";
04981    char rsasecret[256] = "";
04982    char secret[256] = "";
04983    struct iax2_peer *p;
04984    struct ast_key *key;
04985    char *keyn;
04986    int x;
04987    int expire = 0;
04988 
04989    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
04990    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
04991    if (ies->username)
04992       ast_copy_string(peer, ies->username, sizeof(peer));
04993    if (ies->password)
04994       ast_copy_string(secret, ies->password, sizeof(secret));
04995    if (ies->md5_result)
04996       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
04997    if (ies->rsa_result)
04998       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
04999    if (ies->refresh)
05000       expire = ies->refresh;
05001 
05002    if (ast_strlen_zero(peer)) {
05003       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05004       return -1;
05005    }
05006 
05007    /* SLD: first call to lookup peer during registration */
05008    p = find_peer(peer, 1);
05009 
05010    if (!p) {
05011       if (authdebug)
05012          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05013       return -1;
05014    }
05015 
05016    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05017       if (authdebug)
05018          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05019       if (ast_test_flag(p, IAX_TEMPONLY))
05020          destroy_peer(p);
05021       return -1;
05022    }
05023 
05024    if (!ast_apply_ha(p->ha, sin)) {
05025       if (authdebug)
05026          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05027       if (ast_test_flag(p, IAX_TEMPONLY))
05028          destroy_peer(p);
05029       return -1;
05030    }
05031    if (!inaddrcmp(&p->addr, sin))
05032       ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
05033    ast_string_field_set(iaxs[callno], secret, p->secret);
05034    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05035    /* Check secret against what we have on file */
05036    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05037       if (!ast_strlen_zero(p->inkeys)) {
05038          char tmpkeys[256];
05039          char *stringp=NULL;
05040          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05041          stringp=tmpkeys;
05042          keyn = strsep(&stringp, ":");
05043          while(keyn) {
05044             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05045             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05046                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05047                break;
05048             } else if (!key) 
05049                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05050             keyn = strsep(&stringp, ":");
05051          }
05052          if (!keyn) {
05053             if (authdebug)
05054                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05055             if (ast_test_flag(p, IAX_TEMPONLY))
05056                destroy_peer(p);
05057             return -1;
05058          }
05059       } else {
05060          if (authdebug)
05061             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05062          if (ast_test_flag(p, IAX_TEMPONLY))
05063             destroy_peer(p);
05064          return -1;
05065       }
05066    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05067       struct MD5Context md5;
05068       unsigned char digest[16];
05069       char *tmppw, *stringp;
05070       
05071       tmppw = ast_strdupa(p->secret);
05072       stringp = tmppw;
05073       while((tmppw = strsep(&stringp, ";"))) {
05074          MD5Init(&md5);
05075          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05076          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05077          MD5Final(digest, &md5);
05078          for (x=0;x<16;x++)
05079             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05080          if (!strcasecmp(requeststr, md5secret)) 
05081             break;
05082       }
05083       if (tmppw) {
05084          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05085       } else {
05086          if (authdebug)
05087             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05088          if (ast_test_flag(p, IAX_TEMPONLY))
05089             destroy_peer(p);
05090          return -1;
05091       }
05092    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05093       /* They've provided a plain text password and we support that */
05094       if (strcmp(secret, p->secret)) {
05095          if (authdebug)
05096             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05097          if (ast_test_flag(p, IAX_TEMPONLY))
05098             destroy_peer(p);
05099          return -1;
05100       } else
05101          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05102    } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) {
05103       if (authdebug)
05104          ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
05105       if (ast_test_flag(p, IAX_TEMPONLY))
05106          destroy_peer(p);
05107       return -1;
05108    }
05109    ast_string_field_set(iaxs[callno], peer, peer);
05110    /* Choose lowest expiry number */
05111    if (expire && (expire < iaxs[callno]->expiry)) 
05112       iaxs[callno]->expiry = expire;
05113 
05114    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05115 
05116    if (ast_test_flag(p, IAX_TEMPONLY))
05117       destroy_peer(p);
05118    return 0;
05119    
05120 }

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

Definition at line 5715 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_random(), ast_string_field_set, ast_test_flag, iax2_peer::authmethods, 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, and send_command().

Referenced by socket_process().

05716 {
05717    struct iax_ie_data ied;
05718    struct iax2_peer *p;
05719    char challenge[10];
05720    /* SLD: third call to find_peer in registration */
05721    p = find_peer(name, 1);
05722    if (p) {
05723       memset(&ied, 0, sizeof(ied));
05724       iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05725       if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
05726          /* Build the challenge */
05727          snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05728          ast_string_field_set(iaxs[callno], challenge, challenge);
05729          /* snprintf(iaxs[callno]->challenge, sizeof(iaxs[callno]->challenge), "%d", (int)ast_random()); */
05730          iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
05731       }
05732       iax_ie_append_str(&ied, IAX_IE_USERNAME, name);
05733       if (ast_test_flag(p, IAX_TEMPONLY))
05734          destroy_peer(p);
05735       return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
05736    } 
05737    ast_log(LOG_WARNING, "No such peer '%s'\n", name);
05738    return 0;
05739 }

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

Definition at line 5741 of file chan_iax2.c.

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

Referenced by socket_process().

05742 {
05743    struct iax2_registry *reg;
05744    /* Start pessimistic */
05745    struct iax_ie_data ied;
05746    char peer[256] = "";
05747    char challenge[256] = "";
05748    int res;
05749    int authmethods = 0;
05750    if (ies->authmethods)
05751       authmethods = ies->authmethods;
05752    if (ies->username)
05753       ast_copy_string(peer, ies->username, sizeof(peer));
05754    if (ies->challenge)
05755       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
05756    memset(&ied, 0, sizeof(ied));
05757    reg = iaxs[callno]->reg;
05758    if (reg) {
05759          if (inaddrcmp(&reg->addr, sin)) {
05760             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05761             return -1;
05762          }
05763          if (ast_strlen_zero(reg->secret)) {
05764             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
05765             reg->regstate = REG_STATE_NOAUTH;
05766             return -1;
05767          }
05768          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
05769          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
05770          if (reg->secret[0] == '[') {
05771             char tmpkey[256];
05772             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
05773             tmpkey[strlen(tmpkey) - 1] = '\0';
05774             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
05775          } else
05776             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
05777          if (!res) {
05778             reg->regstate = REG_STATE_AUTHSENT;
05779             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
05780          } else
05781             return -1;
05782          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
05783    } else   
05784       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
05785    return -1;
05786 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4290 of file chan_iax2.c.

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

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

04291 {
04292    switch(regstate) {
04293    case REG_STATE_UNREGISTERED:
04294       return "Unregistered";
04295    case REG_STATE_REGSENT:
04296       return "Request Sent";
04297    case REG_STATE_AUTHSENT:
04298       return "Auth. Sent";
04299    case REG_STATE_REGISTERED:
04300       return "Registered";
04301    case REG_STATE_REJECTED:
04302       return "Rejected";
04303    case REG_STATE_TIMEOUT:
04304       return "Timeout";
04305    case REG_STATE_NOAUTH:
04306       return "No Authentication";
04307    default:
04308       return "Unknown";
04309    }
04310 }

static int reload ( void   )  [static]

Definition at line 9358 of file chan_iax2.c.

References reload_config().

09359 {
09360    return reload_config();
09361 }

static int reload_config ( void   )  [static]

Definition at line 9318 of file chan_iax2.c.

References ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, delete_users(), globalflags, 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().

09319 {
09320    char *config = "iax.conf";
09321    struct iax2_registry *reg;
09322    struct iax2_peer *peer;
09323 
09324    strcpy(accountcode, "");
09325    strcpy(language, "");
09326    strcpy(mohinterpret, "default");
09327    strcpy(mohsuggest, "");
09328    amaflags = 0;
09329    delayreject = 0;
09330    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09331    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09332    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09333    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09334    delete_users();
09335    set_config(config, 1);
09336    prune_peers();
09337    prune_users();
09338    AST_LIST_LOCK(&registrations);
09339    AST_LIST_TRAVERSE(&registrations, reg, entry)
09340       iax2_do_register(reg);
09341    AST_LIST_UNLOCK(&registrations);
09342    /* Qualify hosts, too */
09343    AST_LIST_LOCK(&peers);
09344    AST_LIST_TRAVERSE(&peers, peer, entry)
09345       iax2_poke_peer(peer, 0);
09346    AST_LIST_UNLOCK(&peers);
09347    reload_firmware();
09348    iax_provision_reload();
09349 
09350    return 0;
09351 }

static void reload_firmware ( void   )  [static]

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

01541 {
01542    struct iax_firmware *cur, *curl, *curp;
01543    DIR *fwd;
01544    struct dirent *de;
01545    char dir[256];
01546    char fn[256];
01547    /* Mark all as dead */
01548    ast_mutex_lock(&waresl.lock);
01549    cur = waresl.wares;
01550    while(cur) {
01551       cur->dead = 1;
01552       cur = cur->next;
01553    }
01554    /* Now that we've freed them, load the new ones */
01555    snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
01556    fwd = opendir(dir);
01557    if (fwd) {
01558       while((de = readdir(fwd))) {
01559          if (de->d_name[0] != '.') {
01560             snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
01561             if (!try_firmware(fn)) {
01562                if (option_verbose > 1)
01563                   ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
01564             }
01565          }
01566       }
01567       closedir(fwd);
01568    } else 
01569       ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
01570 
01571    /* Clean up leftovers */
01572    cur = waresl.wares;
01573    curp = NULL;
01574    while(cur) {
01575       curl = cur;
01576       cur = cur->next;
01577       if (curl->dead) {
01578          if (curp) {
01579             curp->next = cur;
01580          } else {
01581             waresl.wares = cur;
01582          }
01583          destroy_firmware(curl);
01584       } else {
01585          curp = cur;
01586       }
01587    }
01588    ast_mutex_unlock(&waresl.lock);
01589 }

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

Definition at line 6240 of file chan_iax2.c.

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

Referenced by socket_process().

06241 {
06242    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06243    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06244    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06245    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06246    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06247    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06248    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06249 }

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

Definition at line 8128 of file chan_iax2.c.

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

Referenced by start_network_thread().

08129 {
08130    int count;
08131    int res;
08132    struct timeval tv;
08133    struct timespec ts;
08134 
08135    for (;;) {
08136       res = ast_sched_wait(sched);
08137       if ((res > 1000) || (res < 0))
08138          res = 1000;
08139       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
08140       ts.tv_sec = tv.tv_sec;
08141       ts.tv_nsec = tv.tv_usec * 1000;
08142 
08143       pthread_testcancel();
08144       ast_mutex_lock(&sched_lock);
08145       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
08146       ast_mutex_unlock(&sched_lock);
08147       pthread_testcancel();
08148 
08149       count = ast_sched_runq(sched);
08150       if (count >= 20)
08151          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
08152    }
08153    return NULL;
08154 }

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

Definition at line 2318 of file chan_iax2.c.

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

Referenced by socket_process().

02319 {
02320    int type, len;
02321    int ret;
02322    int needfree = 0;
02323 
02324    /* Attempt to recover wrapped timestamps */
02325    unwrap_timestamp(fr);
02326    
02327 
02328    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02329    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02330       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02331    else {
02332 #if 0
02333       ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02334 #endif
02335       fr->af.delivery = ast_tv(0,0);
02336    }
02337 
02338    type = JB_TYPE_CONTROL;
02339    len = 0;
02340 
02341    if(fr->af.frametype == AST_FRAME_VOICE) {
02342       type = JB_TYPE_VOICE;
02343       len = ast_codec_get_samples(&fr->af) / 8;
02344    } else if(fr->af.frametype == AST_FRAME_CNG) {
02345       type = JB_TYPE_SILENCE;
02346    }
02347 
02348    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02349       if (tsout)
02350          *tsout = fr->ts;
02351       __do_deliver(fr);
02352       return -1;
02353    }
02354 
02355    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02356     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02357    if( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) &&
02358        iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) &&
02359        (ast_bridged_channel(iaxs[fr->callno]->owner)->tech->properties & AST_CHAN_TP_WANTSJITTER)) {
02360                 jb_frame frame;
02361 
02362                 /* deliver any frames in the jb */
02363                 while(jb_getall(iaxs[fr->callno]->jb,&frame) == JB_OK)
02364                         __do_deliver(frame.data);
02365 
02366       jb_reset(iaxs[fr->callno]->jb);
02367 
02368       if (iaxs[fr->callno]->jbid > -1)
02369                         ast_sched_del(sched, iaxs[fr->callno]->jbid);
02370 
02371       iaxs[fr->callno]->jbid = -1;
02372 
02373       /* deliver this frame now */
02374       if (tsout)
02375          *tsout = fr->ts;
02376       __do_deliver(fr);
02377       return -1;
02378    }
02379 
02380    /* insert into jitterbuffer */
02381    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02382    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02383          calc_rxstamp(iaxs[fr->callno],fr->ts));
02384    if (ret == JB_DROP) {
02385       needfree++;
02386    } else if (ret == JB_SCHED) {
02387       update_jbsched(iaxs[fr->callno]);
02388    }
02389    if (tsout)
02390       *tsout = fr->ts;
02391    if (needfree) {
02392       /* Free our iax frame */
02393       iax2_frame_free(fr);
02394       return -1;
02395    }
02396    return 0;
02397 }

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

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

04574 {
04575    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
04576 }

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

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

04588 {
04589    /* It is assumed that the callno has already been locked */
04590    iax2_predestroy(i->callno);
04591    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
04592 }

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

Definition at line 4594 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

04595 {
04596    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
04597 }

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

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

04579 {
04580    int res;
04581    ast_mutex_lock(&iaxsl[callno]);
04582    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
04583    ast_mutex_unlock(&iaxsl[callno]);
04584    return res;
04585 }

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

Definition at line 4599 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

04600 {
04601    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
04602 }

static int send_lagrq ( void *  data  )  [static]

Definition at line 960 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

00961 {
00962 #ifdef SCHED_MULTITHREADED
00963    if (schedule_action(__send_lagrq, data))
00964 #endif      
00965       __send_lagrq(data);
00966    return 0;
00967 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 1654 of file chan_iax2.c.

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

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

01655 {
01656    int res;
01657    int callno;
01658 
01659    if( f == NULL ) {
01660        ast_log(LOG_ERROR, "send_packet( NULL )\n");
01661        ast_backtrace();
01662        return -1;
01663    }
01664    
01665    callno = f->callno;
01666 
01667    /* Don't send if there was an error, but return error instead */
01668    if (!callno || !iaxs[callno] || iaxs[callno]->error)
01669        return -1;
01670    
01671    /* Called with iaxsl held */
01672    if (option_debug > 2 && iaxdebug)
01673       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));
01674    if (f->transfer) {
01675       if (iaxdebug)
01676          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
01677       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
01678                sizeof(iaxs[callno]->transfer));
01679    } else {
01680       if (iaxdebug)
01681          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
01682       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
01683                sizeof(iaxs[callno]->addr));
01684    }
01685    if (res < 0) {
01686       if (option_debug && iaxdebug)
01687          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01688       handle_error();
01689    } else
01690       res = 0;
01691    return res;
01692 }

static int send_ping ( void *  data  )  [static]

Definition at line 925 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

00926 {
00927 #ifdef SCHED_MULTITHREADED
00928    if (schedule_action(__send_ping, data))
00929 #endif      
00930       __send_ping(data);
00931    return 0;
00932 }

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

Definition at line 5925 of file chan_iax2.c.

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

Referenced by timing_read().

05926 {
05927    int res = 0;
05928    struct iax_frame *fr;
05929    struct ast_iax2_meta_hdr *meta;
05930    struct ast_iax2_meta_trunk_hdr *mth;
05931    int calls = 0;
05932    
05933    /* Point to frame */
05934    fr = (struct iax_frame *)tpeer->trunkdata;
05935    /* Point to meta data */
05936    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
05937    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
05938    if (tpeer->trunkdatalen) {
05939       /* We're actually sending a frame, so fill the meta trunk header and meta header */
05940       meta->zeros = 0;
05941       meta->metacmd = IAX_META_TRUNK;
05942       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
05943          meta->cmddata = IAX_META_TRUNK_MINI;
05944       else
05945          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
05946       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
05947       /* And the rest of the ast_iax2 header */
05948       fr->direction = DIRECTION_OUTGRESS;
05949       fr->retrans = -1;
05950       fr->transfer = 0;
05951       /* Any appropriate call will do */
05952       fr->data = fr->afdata;
05953       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
05954       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
05955       calls = tpeer->calls;
05956 #if 0
05957       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));
05958 #endif      
05959       /* Reset transmit trunk side data */
05960       tpeer->trunkdatalen = 0;
05961       tpeer->calls = 0;
05962    }
05963    if (res < 0)
05964       return res;
05965    return calls;
05966 }

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

Load configuration.

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

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

08962 {
08963    struct ast_config *cfg, *ucfg;
08964    int capability=iax2_capability;
08965    struct ast_variable *v;
08966    char *cat;
08967    const char *utype;
08968    const char *tosval;
08969    int format;
08970    int portno = IAX_DEFAULT_PORTNO;
08971    int  x;
08972    struct iax2_user *user;
08973    struct iax2_peer *peer;
08974    struct ast_netsock *ns;
08975 #if 0
08976    static unsigned short int last_port=0;
08977 #endif
08978 
08979    cfg = ast_config_load(config_file);
08980    
08981    if (!cfg) {
08982       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
08983       return -1;
08984    }
08985 
08986    /* Reset global codec prefs */   
08987    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
08988    
08989    /* Reset Global Flags */
08990    memset(&globalflags, 0, sizeof(globalflags));
08991    ast_set_flag(&globalflags, IAX_RTUPDATE);
08992 
08993 #ifdef SO_NO_CHECK
08994    nochecksums = 0;
08995 #endif
08996 
08997    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
08998    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
08999 
09000    maxauthreq = 3;
09001 
09002    v = ast_variable_browse(cfg, "general");
09003 
09004    /* Seed initial tos value */
09005    tosval = ast_variable_retrieve(cfg, "general", "tos");
09006    if (tosval) {
09007       if (ast_str2tos(tosval, &tos))
09008          ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n");
09009    }
09010    while(v) {
09011       if (!strcasecmp(v->name, "bindport")){ 
09012          if (reload)
09013             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
09014          else
09015             portno = atoi(v->value);
09016       } else if (!strcasecmp(v->name, "pingtime")) 
09017          ping_time = atoi(v->value);
09018       else if (!strcasecmp(v->name, "iaxthreadcount")) {
09019          if (reload) {
09020             if (atoi(v->value) != iaxthreadcount)
09021                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
09022          } else {
09023             iaxthreadcount = atoi(v->value);
09024             if (iaxthreadcount < 1) {
09025                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
09026                iaxthreadcount = 1;
09027             } else if (iaxthreadcount > 256) {
09028                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
09029                iaxthreadcount = 256;
09030             }
09031          }
09032       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
09033          if (reload) {
09034             AST_LIST_LOCK(&dynamic_list);
09035             iaxmaxthreadcount = atoi(v->value);
09036             AST_LIST_UNLOCK(&dynamic_list);
09037          } else {
09038             iaxmaxthreadcount = atoi(v->value);
09039             if (iaxmaxthreadcount < 0) {
09040                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
09041                iaxmaxthreadcount = 0;
09042             } else if (iaxmaxthreadcount > 256) {
09043                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
09044                iaxmaxthreadcount = 256;
09045             }
09046          }
09047       } else if (!strcasecmp(v->name, "nochecksums")) {
09048 #ifdef SO_NO_CHECK
09049          if (ast_true(v->value))
09050             nochecksums = 1;
09051          else
09052             nochecksums = 0;
09053 #else
09054          if (ast_true(v->value))
09055             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
09056 #endif
09057       }
09058       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
09059          maxjitterbuffer = atoi(v->value);
09060       else if (!strcasecmp(v->name, "resyncthreshold")) 
09061          resyncthreshold = atoi(v->value);
09062       else if (!strcasecmp(v->name, "maxjitterinterps")) 
09063          maxjitterinterps = atoi(v->value);
09064       else if (!strcasecmp(v->name, "lagrqtime")) 
09065          lagrq_time = atoi(v->value);
09066       else if (!strcasecmp(v->name, "maxregexpire")) 
09067          max_reg_expire = atoi(v->value);
09068       else if (!strcasecmp(v->name, "minregexpire")) 
09069          min_reg_expire = atoi(v->value);
09070       else if (!strcasecmp(v->name, "bindaddr")) {
09071          if (reload) {
09072             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
09073          } else {
09074             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) {
09075                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
09076             } else {
09077                if (option_verbose > 1) {
09078                   if (strchr(v->value, ':'))
09079                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value);
09080                   else
09081                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno);
09082                }
09083                if (defaultsockfd < 0) 
09084                   defaultsockfd = ast_netsock_sockfd(ns);
09085                ast_netsock_unref(ns);
09086             }
09087          }
09088       } else if (!strcasecmp(v->name, "authdebug"))
09089          authdebug = ast_true(v->value);
09090       else if (!strcasecmp(v->name, "encryption"))
09091          iax2_encryption = get_encrypt_methods(v->value);
09092       else if (!strcasecmp(v->name, "notransfer")) {
09093          ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09094          ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09095          ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER);   
09096       } else if (!strcasecmp(v->name, "transfer")) {
09097          if (!strcasecmp(v->value, "mediaonly")) {
09098             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
09099          } else if (ast_true(v->value)) {
09100             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09101          } else 
09102             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09103       } else if (!strcasecmp(v->name, "codecpriority")) {
09104          if(!strcasecmp(v->value, "caller"))
09105             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
09106          else if(!strcasecmp(v->value, "disabled"))
09107             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09108          else if(!strcasecmp(v->value, "reqonly")) {
09109             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
09110             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09111          }
09112       } else if (!strcasecmp(v->name, "jitterbuffer"))
09113          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
09114       else if (!strcasecmp(v->name, "forcejitterbuffer"))
09115          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
09116       else if (!strcasecmp(v->name, "delayreject"))
09117          delayreject = ast_true(v->value);
09118       else if (!strcasecmp(v->name, "rtcachefriends"))
09119          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
09120       else if (!strcasecmp(v->name, "rtignoreregexpire"))
09121          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
09122       else if (!strcasecmp(v->name, "rtupdate"))
09123          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
09124       else if (!strcasecmp(v->name, "trunktimestamps"))
09125          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
09126       else if (!strcasecmp(v->name, "rtautoclear")) {
09127          int i = atoi(v->value);
09128          if(i > 0)
09129             global_rtautoclear = i;
09130          else
09131             i = 0;
09132          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
09133       } else if (!strcasecmp(v->name, "trunkfreq")) {
09134          trunkfreq = atoi(v->value);
09135          if (trunkfreq < 10)
09136             trunkfreq = 10;
09137       } else if (!strcasecmp(v->name, "autokill")) {
09138          if (sscanf(v->value, "%d", &x) == 1) {
09139             if (x >= 0)
09140                autokill = x;
09141             else
09142                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
09143          } else if (ast_true(v->value)) {
09144             autokill = DEFAULT_MAXMS;
09145          } else {
09146             autokill = 0;
09147          }
09148       } else if (!strcasecmp(v->name, "bandwidth")) {
09149          if (!strcasecmp(v->value, "low")) {
09150             capability = IAX_CAPABILITY_LOWBANDWIDTH;
09151          } else if (!strcasecmp(v->value, "medium")) {
09152             capability = IAX_CAPABILITY_MEDBANDWIDTH;
09153          } else if (!strcasecmp(v->value, "high")) {
09154             capability = IAX_CAPABILITY_FULLBANDWIDTH;
09155          } else
09156             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
09157       } else if (!strcasecmp(v->name, "allow")) {
09158          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
09159       } else if (!strcasecmp(v->name, "disallow")) {
09160          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
09161       } else if (!strcasecmp(v->name, "register")) {
09162          iax2_register(v->value, v->lineno);
09163       } else if (!strcasecmp(v->name, "iaxcompat")) {
09164          iaxcompat = ast_true(v->value);
09165       } else if (!strcasecmp(v->name, "regcontext")) {
09166          ast_copy_string(regcontext, v->value, sizeof(regcontext));
09167          /* Create context if it doesn't exist already */
09168          if (!ast_context_find(regcontext))
09169             ast_context_create(NULL, regcontext, "IAX2");
09170       } else if (!strcasecmp(v->name, "tos")) {
09171          if (ast_str2tos(v->value, &tos))
09172             ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno);
09173       } else if (!strcasecmp(v->name, "accountcode")) {
09174          ast_copy_string(accountcode, v->value, sizeof(accountcode));
09175       } else if (!strcasecmp(v->name, "mohinterpret")) {
09176          ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret));
09177       } else if (!strcasecmp(v->name, "mohsuggest")) {
09178          ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest));
09179       } else if (!strcasecmp(v->name, "amaflags")) {
09180          format = ast_cdr_amaflags2int(v->value);
09181          if (format < 0) {
09182             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09183          } else {
09184             amaflags = format;
09185          }
09186       } else if (!strcasecmp(v->name, "language")) {
09187          ast_copy_string(language, v->value, sizeof(language));
09188       } else if (!strcasecmp(v->name, "maxauthreq")) {
09189          maxauthreq = atoi(v->value);
09190          if (maxauthreq < 0)
09191             maxauthreq = 0;
09192       } else if (!strcasecmp(v->name, "adsi")) {
09193          adsi = ast_true(v->value);
09194       } /*else if (strcasecmp(v->name,"type")) */
09195       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09196       v = v->next;
09197    }
09198    
09199    if (defaultsockfd < 0) {
09200       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) {
09201          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
09202       } else {
09203          if (option_verbose > 1)
09204             ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
09205          defaultsockfd = ast_netsock_sockfd(ns);
09206          ast_netsock_unref(ns);
09207       }
09208    }
09209    if (reload) {
09210       ast_netsock_release(outsock);
09211       outsock = ast_netsock_list_alloc();
09212       if (!outsock) {
09213          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
09214          return -1;
09215       }
09216       ast_netsock_init(outsock);
09217    }
09218 
09219    if (min_reg_expire > max_reg_expire) {
09220       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
09221          min_reg_expire, max_reg_expire, max_reg_expire);
09222       min_reg_expire = max_reg_expire;
09223    }
09224    iax2_capability = capability;
09225    
09226    ucfg = ast_config_load("users.conf");
09227    if (ucfg) {
09228       struct ast_variable *gen;
09229       int genhasiax;
09230       int genregisteriax;
09231       const char *hasiax, *registeriax;
09232       
09233       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
09234       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
09235       gen = ast_variable_browse(ucfg, "general");
09236       cat = ast_category_browse(ucfg, NULL);
09237       while (cat) {
09238          if (strcasecmp(cat, "general")) {
09239             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
09240             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
09241             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
09242                /* Start with general parameters, then specific parameters, user and peer */
09243                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
09244                if (user) {
09245                   AST_LIST_LOCK(&users);
09246                   AST_LIST_INSERT_HEAD(&users, user, entry);
09247                   AST_LIST_UNLOCK(&users);
09248                }
09249                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
09250                if (peer) {
09251                   AST_LIST_LOCK(&peers);
09252                   AST_LIST_INSERT_HEAD(&peers, peer, entry);
09253                   AST_LIST_UNLOCK(&peers);
09254                   if (ast_test_flag(peer, IAX_DYNAMIC))
09255                      reg_source_db(peer);
09256                }
09257             }
09258             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
09259                char tmp[256];
09260                const char *host = ast_variable_retrieve(ucfg, cat, "host");
09261                const char *username = ast_variable_retrieve(ucfg, cat, "username");
09262                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
09263                if (!host)
09264                   host = ast_variable_retrieve(ucfg, "general", "host");
09265                if (!username)
09266                   username = ast_variable_retrieve(ucfg, "general", "username");
09267                if (!secret)
09268                   secret = ast_variable_retrieve(ucfg, "general", "secret");
09269                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
09270                   if (!ast_strlen_zero(secret))
09271                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
09272                   else
09273                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
09274                   iax2_register(tmp, 0);
09275                }
09276             }
09277          }
09278          cat = ast_category_browse(ucfg, cat);
09279       }
09280       ast_config_destroy(ucfg);
09281    }
09282    
09283    cat = ast_category_browse(cfg, NULL);
09284    while(cat) {
09285       if (strcasecmp(cat, "general")) {
09286          utype = ast_variable_retrieve(cfg, cat, "type");
09287          if (utype) {
09288             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
09289                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
09290                if (user) {
09291                   AST_LIST_LOCK(&users);
09292                   AST_LIST_INSERT_HEAD(&users, user, entry);
09293                   AST_LIST_UNLOCK(&users);
09294                }
09295             }
09296             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
09297                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
09298                if (peer) {
09299                   AST_LIST_LOCK(&peers);
09300                   AST_LIST_INSERT_HEAD(&peers, peer, entry);
09301                   AST_LIST_UNLOCK(&peers);
09302                   if (ast_test_flag(peer, IAX_DYNAMIC))
09303                      reg_source_db(peer);
09304                }
09305             } else if (strcasecmp(utype, "user")) {
09306                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
09307             }
09308          } else
09309             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
09310       }
09311       cat = ast_category_browse(cfg, cat);
09312    }
09313    ast_config_destroy(cfg);
09314    set_timing();
09315    return capability;
09316 }

static void set_timing ( void   )  [static]

Definition at line 8944 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

08945 {
08946 #ifdef HAVE_ZAPTEL
08947    int bs = trunkfreq * 8;
08948    if (timingfd > -1) {
08949       if (
08950 #ifdef ZT_TIMERACK
08951          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
08952 #endif         
08953          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
08954          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
08955    }
08956 #endif
08957 }

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

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

00713 {
00714    ast_mutex_lock(lock);
00715    ast_cond_signal(cond);
00716    ast_mutex_unlock(lock);
00717 }

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6317 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_device_state_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_parking_ext(), ast_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_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variables_destroy(), ast_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax2_peer::callno, iax2_dpcache::callno, chan_iax2_pvt::callno, iax_frame::callno, ast_iax2_mini_hdr::callno, check_access(), check_provisioning(), complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, decrypt_frame(), dp_lookup(), EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, format, chan_iax2_pvt::frames_received, free, 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_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iaxfrdup2(), iaxq, iaxs, iaxsl, ies, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, NEW_ALLOW, NEW_PREVENT, option_debug, option_verbose, iax_frame::oseqno, chan_iax2_pvt::oseqno, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, chan_iax2_pvt::peercallno, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, raw_hangup(), REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), iax_frame::retries, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, save_rr(), sched, schedule_delivery(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax2_peer::smoothing, spawn_dp_lookup(), chan_iax2_pvt::state, stop_stuff(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), iax_frame::ts, ast_iax2_mini_hdr::ts, uncompress_subclass(), update_registry(), var, VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.

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

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

Definition at line 6251 of file chan_iax2.c.

References ast_log(), ast_random(), find_idle_thread(), handle_error(), IAX_IOSTATE_READY, insert_idle_thread(), len, LOG_NOTICE, LOG_WARNING, signal_condition(), t, and thread.

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

06252 {
06253    struct iax2_thread *thread;
06254    socklen_t len;
06255    time_t t;
06256    static time_t last_errtime=0;
06257 
06258    thread = find_idle_thread();
06259    if (thread) {
06260       len = sizeof(thread->iosin);
06261       thread->iofd = fd;
06262       thread->iores = recvfrom(fd, thread->buf, sizeof(thread->buf), 0,(struct sockaddr *) &thread->iosin, &len);
06263       if (thread->iores < 0) {
06264          if (errno != ECONNREFUSED && errno != EAGAIN)
06265             ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06266          handle_error();
06267          insert_idle_thread(thread);
06268          return 1;
06269       }
06270       if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06271          insert_idle_thread(thread);
06272          return 1;
06273       }
06274       /* Mark as ready and send on its way */
06275       thread->iostate = IAX_IOSTATE_READY;
06276 #ifdef DEBUG_SCHED_MULTITHREAD
06277       ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06278 #endif
06279       signal_condition(&thread->lock, &thread->cond);
06280    } else {
06281       time(&t);
06282       if (t != last_errtime)
06283          ast_log(LOG_NOTICE, "Out of idle IAX2 threads for I/O, pausing!\n");
06284       last_errtime = t;
06285       usleep(1);
06286    }
06287    return 1;
06288 }

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

Definition at line 6101 of file chan_iax2.c.

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

Referenced by socket_process().

06102 {
06103    pthread_t newthread;
06104    struct dpreq_data *dpr;
06105    pthread_attr_t attr;
06106    
06107    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06108       return;
06109 
06110    pthread_attr_init(&attr);
06111    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06112 
06113    dpr->callno = callno;
06114    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06115    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06116    if (callerid)
06117       dpr->callerid = ast_strdup(callerid);
06118    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06119       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06120    }
06121 
06122    pthread_attr_destroy(&attr);
06123 }

static int start_network_thread ( void   )  [static]

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

08225 {
08226    pthread_attr_t attr;
08227    int threadcount = 0;
08228    int x;
08229    for (x = 0; x < iaxthreadcount; x++) {
08230       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
08231       if (thread) {
08232          thread->type = IAX_TYPE_POOL;
08233          thread->threadnum = ++threadcount;
08234          ast_mutex_init(&thread->lock);
08235          ast_cond_init(&thread->cond, NULL);
08236          pthread_attr_init(&attr);
08237          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
08238          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
08239             ast_log(LOG_WARNING, "Failed to create new thread!\n");
08240             free(thread);
08241             thread = NULL;
08242          }
08243          AST_LIST_LOCK(&idle_list);
08244          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
08245          AST_LIST_UNLOCK(&idle_list);
08246       }
08247    }
08248    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
08249    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
08250    if (option_verbose > 1)
08251       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
08252    return 0;
08253 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 5788 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

05789 {
05790    iax2_destroy_helper(iaxs[callno]);
05791 }

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

Definition at line 5976 of file chan_iax2.c.

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

Referenced by network_thread().

05977 {
05978    char buf[1024];
05979    int res;
05980    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
05981    int processed = 0;
05982    int totalcalls = 0;
05983 #ifdef ZT_TIMERACK
05984    int x = 1;
05985 #endif
05986    struct timeval now;
05987    if (iaxtrunkdebug)
05988       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
05989    gettimeofday(&now, NULL);
05990    if (events & AST_IO_PRI) {
05991 #ifdef ZT_TIMERACK
05992       /* Great, this is a timing interface, just call the ioctl */
05993       if (ioctl(fd, ZT_TIMERACK, &x)) 
05994          ast_log(LOG_WARNING, "Unable to acknowledge zap timer\n");
05995       res = 0;
05996 #endif      
05997    } else {
05998       /* Read and ignore from the pseudo channel for timing */
05999       res = read(fd, buf, sizeof(buf));
06000       if (res < 1) {
06001          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06002          return 1;
06003       }
06004    }
06005    /* For each peer that supports trunking... */
06006    ast_mutex_lock(&tpeerlock);
06007    tpeer = tpeers;
06008    while(tpeer) {
06009       processed++;
06010       res = 0;
06011       ast_mutex_lock(&tpeer->lock);
06012       /* We can drop a single tpeer per pass.  That makes all this logic
06013          substantially easier */
06014       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06015          /* Take it out of the list, but don't free it yet, because it
06016             could be in use */
06017          if (prev)
06018             prev->next = tpeer->next;
06019          else
06020             tpeers = tpeer->next;
06021          drop = tpeer;
06022       } else {
06023          res = send_trunk(tpeer, &now);
06024          if (iaxtrunkdebug)
06025             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);
06026       }     
06027       totalcalls += res;   
06028       res = 0;
06029       ast_mutex_unlock(&tpeer->lock);
06030       prev = tpeer;
06031       tpeer = tpeer->next;
06032    }
06033    ast_mutex_unlock(&tpeerlock);
06034    if (drop) {
06035       ast_mutex_lock(&drop->lock);
06036       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06037          because by the time they could get tpeerlock, we've already grabbed it */
06038       ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06039       free(drop->trunkdata);
06040       ast_mutex_unlock(&drop->lock);
06041       ast_mutex_destroy(&drop->lock);
06042       free(drop);
06043       
06044    }
06045    if (iaxtrunkdebug)
06046       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06047    iaxtrunkdebug =0;
06048    return 1;
06049 }

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

Definition at line 1640 of file chan_iax2.c.

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

Referenced by send_trunk().

01641 {
01642    int res;
01643    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
01644                sizeof(*sin));
01645    if (res < 0) {
01646       if (option_debug)
01647          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01648       handle_error();
01649    } else
01650       res = 0;
01651    return res;
01652 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1339 of file chan_iax2.c.

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

Referenced by reload_firmware().

01340 {
01341    struct stat stbuf;
01342    struct iax_firmware *cur;
01343    int ifd;
01344    int fd;
01345    int res;
01346    
01347    struct ast_iax2_firmware_header *fwh, fwh2;
01348    struct MD5Context md5;
01349    unsigned char sum[16];
01350    unsigned char buf[1024];
01351    int len, chunk;
01352    char *s2;
01353    char *last;
01354    s2 = alloca(strlen(s) + 100);
01355    if (!s2) {
01356       ast_log(LOG_WARNING, "Alloca failed!\n");
01357       return -1;
01358    }
01359    last = strrchr(s, '/');
01360    if (last)
01361       last++;
01362    else
01363       last = s;
01364    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01365    res = stat(s, &stbuf);
01366    if (res < 0) {
01367       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01368       return -1;
01369    }
01370    /* Make sure it's not a directory */
01371    if (S_ISDIR(stbuf.st_mode))
01372       return -1;
01373    ifd = open(s, O_RDONLY);
01374    if (ifd < 0) {
01375       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01376       return -1;
01377    }
01378    fd = open(s2, O_RDWR | O_CREAT | O_EXCL);
01379    if (fd < 0) {
01380       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
01381       close(ifd);
01382       return -1;
01383    }
01384    /* Unlink our newly created file */
01385    unlink(s2);
01386    
01387    /* Now copy the firmware into it */
01388    len = stbuf.st_size;
01389    while(len) {
01390       chunk = len;
01391       if (chunk > sizeof(buf))
01392          chunk = sizeof(buf);
01393       res = read(ifd, buf, chunk);
01394       if (res != chunk) {
01395          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01396          close(ifd);
01397          close(fd);
01398          return -1;
01399       }
01400       res = write(fd, buf, chunk);
01401       if (res != chunk) {
01402          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01403          close(ifd);
01404          close(fd);
01405          return -1;
01406       }
01407       len -= chunk;
01408    }
01409    close(ifd);
01410    /* Return to the beginning */
01411    lseek(fd, 0, SEEK_SET);
01412    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
01413       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
01414       close(fd);
01415       return -1;
01416    }
01417    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
01418       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
01419       close(fd);
01420       return -1;
01421    }
01422    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
01423       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
01424       close(fd);
01425       return -1;
01426    }
01427    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
01428       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
01429       close(fd);
01430       return -1;
01431    }
01432    fwh = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
01433    if (fwh == (void *) -1) {
01434       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
01435       close(fd);
01436       return -1;
01437    }
01438    MD5Init(&md5);
01439    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
01440    MD5Final(sum, &md5);
01441    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
01442       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
01443       munmap(fwh, stbuf.st_size);
01444       close(fd);
01445       return -1;
01446    }
01447    cur = waresl.wares;
01448    while(cur) {
01449       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
01450          /* Found a candidate */
01451          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
01452             /* The version we have on loaded is older, load this one instead */
01453             break;
01454          /* This version is no newer than what we have.  Don't worry about it.
01455             We'll consider it a proper load anyhow though */
01456          munmap(fwh, stbuf.st_size);
01457          close(fd);
01458          return 0;
01459       }
01460       cur = cur->next;
01461    }
01462    if (!cur) {
01463       /* Allocate a new one and link it */
01464       if ((cur = ast_calloc(1, sizeof(*cur)))) {
01465          cur->fd = -1;
01466          cur->next = waresl.wares;
01467          waresl.wares = cur;
01468       }
01469    }
01470    if (cur) {
01471       if (cur->fwh) {
01472          munmap(cur->fwh, cur->mmaplen);
01473       }
01474       if (cur->fd > -1)
01475          close(cur->fd);
01476       cur->fwh = fwh;
01477       cur->fd = fd;
01478       cur->mmaplen = stbuf.st_size;
01479       cur->dead = 0;
01480    }
01481    return 0;
01482 }

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

Definition at line 5251 of file chan_iax2.c.

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

Referenced by socket_process().

05252 {
05253    int newcall = 0;
05254    char newip[256];
05255    struct iax_ie_data ied;
05256    struct sockaddr_in new;
05257    
05258    
05259    memset(&ied, 0, sizeof(ied));
05260    if (ies->apparent_addr)
05261       bcopy(ies->apparent_addr, &new, sizeof(new));
05262    if (ies->callno)
05263       newcall = ies->callno;
05264    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05265       ast_log(LOG_WARNING, "Invalid transfer request\n");
05266       return -1;
05267    }
05268    pvt->transfercallno = newcall;
05269    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05270    inet_aton(newip, &pvt->transfer.sin_addr);
05271    pvt->transfer.sin_family = AF_INET;
05272    pvt->transferring = TRANSFER_BEGIN;
05273    pvt->transferid = ies->transferid;
05274    if (ies->transferid)
05275       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05276    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05277    return 0; 
05278 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 989 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

00990 {
00991    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
00992    if (csub & IAX_FLAG_SC_LOG) {
00993       /* special case for 'compressed' -1 */
00994       if (csub == 0xff)
00995          return -1;
00996       else
00997          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
00998    }
00999    else
01000       return csub;
01001 }

static int unload_module ( void   )  [static]

Definition at line 10137 of file chan_iax2.c.

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

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

Definition at line 3069 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03070 {
03071    ast_mutex_unlock(&iaxsl[callno1]);
03072    ast_mutex_unlock(&iaxsl[callno0]);
03073 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

02183 {
02184    int x;
02185 
02186    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02187       x = fr->ts - iaxs[fr->callno]->last;
02188       if (x < -50000) {
02189          /* Sudden big jump backwards in timestamp:
02190             What likely happened here is that miniframe timestamp has circled but we haven't
02191             gotten the update from the main packet.  We'll just pretend that we did, and
02192             update the timestamp appropriately. */
02193          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02194          if (option_debug && iaxdebug)
02195             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02196       }
02197       if (x > 50000) {
02198          /* Sudden apparent big jump forwards in timestamp:
02199             What's likely happened is this is an old miniframe belonging to the previous
02200             top-16-bit timestamp that has turned up out of order.
02201             Adjust the timestamp appropriately. */
02202          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02203          if (option_debug && iaxdebug)
02204             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02205       }
02206    }
02207 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2211 of file chan_iax2.c.

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

Referenced by __get_from_jb(), and schedule_delivery().

02212 {
02213    int when;
02214    
02215    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02216    
02217    when = jb_next(pvt->jb) - when;
02218    
02219    if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
02220    
02221    if(when <= 0) {
02222       /* XXX should really just empty until when > 0.. */
02223       when = 1;
02224    }
02225    
02226    pvt->jbid = ast_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02227    
02228    /* Signal scheduler thread */
02229    signal_condition(&sched_lock, &sched_cond);
02230 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1144 of file chan_iax2.c.

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

Referenced by find_callno().

01145 {
01146    int max = 1;
01147    int x;
01148    /* XXX Prolly don't need locks here XXX */
01149    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01150       if (iaxs[x])
01151          max = x + 1;
01152    }
01153    maxnontrunkcall = max;
01154    if (option_debug && iaxdebug)
01155       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01156 }

static void update_max_trunk ( void   )  [static]

Definition at line 1130 of file chan_iax2.c.

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

Referenced by iax2_destroy().

01131 {
01132    int max = TRUNK_CALL_START;
01133    int x;
01134    /* XXX Prolly don't need locks here XXX */
01135    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01136       if (iaxs[x])
01137          max = x + 1;
01138    }
01139    maxtrunkcall = max;
01140    if (option_debug && iaxdebug)
01141       ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
01142 }

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 1822 of file chan_iax2.c.

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

Referenced by __attempt_transmit().

01823 {
01824    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
01825    struct ast_iax2_full_hdr *fh = f->data;
01826    /* Mark this as a retransmission */
01827    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
01828    /* Update iseqno */
01829    f->iseqno = iaxs[f->callno]->iseqno;
01830    fh->iseqno = f->iseqno;
01831    return 0;
01832 }

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

Definition at line 5608 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(), destroy_peer(), EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), globalflags, iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, iaxs, inaddrcmp(), LOG_NOTICE, LOG_WARNING, manager_event(), option_verbose, realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.

Referenced by socket_process().

05609 {
05610    /* Called from IAX thread only, with proper iaxsl lock */
05611    struct iax_ie_data ied;
05612    struct iax2_peer *p;
05613    int msgcount;
05614    char data[80];
05615    int version;
05616 
05617    memset(&ied, 0, sizeof(ied));
05618 
05619    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
05620    if (!(p = find_peer(name, 1))) {
05621       ast_log(LOG_WARNING, "No such peer '%s'\n", name);
05622       return -1;
05623    }
05624 
05625    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
05626       if (sin->sin_addr.s_addr) {
05627          time_t nowtime;
05628          time(&nowtime);
05629          realtime_update_peer(name, sin, nowtime);
05630       } else {
05631          realtime_update_peer(name, sin, 0);
05632       }
05633    }
05634    if (inaddrcmp(&p->addr, sin)) {
05635       if (iax2_regfunk)
05636          iax2_regfunk(p->name, 1);
05637       /* Stash the IP address from which they registered */
05638       memcpy(&p->addr, sin, sizeof(p->addr));
05639       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
05640       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
05641          ast_db_put("IAX/Registry", p->name, data);
05642          if  (option_verbose > 2)
05643             ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 
05644                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
05645          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
05646          register_peer_exten(p, 1);
05647          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05648       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
05649          if  (option_verbose > 2)
05650             ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 
05651                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
05652          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
05653          register_peer_exten(p, 0);
05654          ast_db_del("IAX/Registry", p->name);
05655          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05656       }
05657       /* Update the host */
05658       /* Verify that the host is really there */
05659       iax2_poke_peer(p, callno);
05660    }     
05661 
05662    /* Make sure our call still exists, an INVAL at the right point may make it go away */
05663    if (!iaxs[callno])
05664       return 0;
05665 
05666    /* Store socket fd */
05667    p->sockfd = fd;
05668    /* Setup the expiry */
05669    if (p->expire > -1)
05670       ast_sched_del(sched, p->expire);
05671    /* treat an unspecified refresh interval as the minimum */
05672    if (!refresh)
05673       refresh = min_reg_expire;
05674    if (refresh > max_reg_expire) {
05675       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
05676          p->name, max_reg_expire, refresh);
05677       p->expiry = max_reg_expire;
05678    } else if (refresh < min_reg_expire) {
05679       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
05680          p->name, min_reg_expire, refresh);
05681       p->expiry = min_reg_expire;
05682    } else {
05683       p->expiry = refresh;
05684    }
05685    if (p->expiry && sin->sin_addr.s_addr)
05686       p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
05687    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
05688    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
05689    if (sin->sin_addr.s_addr) {
05690       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
05691       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
05692       if (!ast_strlen_zero(p->mailbox)) {
05693          int new, old;
05694          ast_app_inboxcount(p->mailbox, &new, &old);
05695          if (new > 255)
05696             new = 255;
05697          if (old > 255)
05698             old = 255;
05699          msgcount = (old << 8) | new;
05700          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
05701       }
05702       if (ast_test_flag(p, IAX_HASCALLERID)) {
05703          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
05704          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
05705       }
05706    }
05707    version = iax_check_version(devtype);
05708    if (version) 
05709       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
05710    if (ast_test_flag(p, IAX_TEMPONLY))
05711       destroy_peer(p);
05712    return send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
05713 }

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

Definition at line 5893 of file chan_iax2.c.

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

Referenced by socket_process().

05894 {
05895    struct iax_frame *f;
05896 
05897    AST_LIST_LOCK(&iaxq.queue);
05898    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
05899       /* Send a copy immediately */
05900       if ((f->callno == callno) && iaxs[f->callno] &&
05901          (f->oseqno >= last)) {
05902          send_packet(f);
05903       }
05904    }
05905    AST_LIST_UNLOCK(&iaxq.queue);
05906 }


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(), begin_dial(), build_device(), build_gateway(), check_user_full(), disa_exec(), features_call(), gtalk_new(), local_call(), mgcp_new(), rpt_call(), sip_new(), skinny_new(), tds_log(), wait_for_answer(), and zt_new().

int adsi = 0 [static]

Definition at line 222 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

Definition at line 221 of file chan_iax2.c.

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

int authdebug = 1 [static]

Definition at line 158 of file chan_iax2.c.

Referenced by set_config().

int autokill = 0 [static]

Definition at line 159 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 9961 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 9941 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 9946 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 9956 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 9951 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 9936 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 9910 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 9902 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 9894 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 273 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

Definition at line 226 of file chan_iax2.c.

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

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

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

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 9826 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

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

int iaxactivethreadcount = 0 [static]

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

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 449 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 9764 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 767 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 768 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 448 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 ast_custom_function iaxvar_function [static]

Definition at line 6309 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

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

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

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

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 228 of file chan_iax2.c.

Referenced by start_network_thread().

char no_debug_jb_usage[] [static]

Initial value:

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

Definition at line 9914 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 9906 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 9898 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.

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

char* papp = "IAX2Provision" [static]

Definition at line 7898 of file chan_iax2.c.

char* pdescrip [static]

Initial value:

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

Definition at line 7900 of file chan_iax2.c.

int ping_time = 20 [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(), ast_rtp_codec_setpref(), build_peer(), build_user(), check_access(), create_addr(), gtalk_create_member(), gtalk_load_config(), set_config(), set_local_capabilities(), and set_peer_capabilities().

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 9848 of file chan_iax2.c.

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

Definition at line 7899 of file chan_iax2.c.

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 9840 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 9868 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 9886 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 9872 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 9844 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 9880 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 9856 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 9890 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 9836 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 9876 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 9863 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 Mon May 14 04:46:10 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1