Mon Apr 30 07:39:42 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 5792 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().

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

static void __auto_congest ( void *  nothing  )  [static]

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

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

static void __auto_hangup ( void *  nothing  )  [static]

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

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

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

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

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

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

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

static void __iax2_poke_noanswer ( void *  data  )  [static]

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

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

static void __iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 5907 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by iax2_poke_peer_s().

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

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

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

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

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

References f, and iax2_send().

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

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

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

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

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

Definition at line 6289 of file chan_iax2.c.

References pbx_builtin_getvar_helper().

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

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

Definition at line 6299 of file chan_iax2.c.

References pbx_builtin_setvar_helper().

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

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

Definition at line 4603 of file chan_iax2.c.

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

Referenced by check_access().

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

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

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

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

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

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

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

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

static int auth_reject ( void *  data  )  [static]

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

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

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

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

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

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

static int authenticate_request ( struct chan_iax2_pvt p  )  [static]

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

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

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

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

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

static int auto_congest ( void *  data  )  [static]

Definition at line 2724 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

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

static int auto_hangup ( void *  data  )  [static]

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

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

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

Definition at line 8247 of file chan_iax2.c.

References ast_calloc.

Referenced by build_user().

08248 {
08249    struct iax2_context *con;
08250 
08251    if ((con = ast_calloc(1, sizeof(*con))))
08252       ast_copy_string(con->context, context, sizeof(con->context));
08253    
08254    return con;
08255 }

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

Definition at line 3658 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

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

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

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

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

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

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

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

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

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

Definition at line 3528 of file chan_iax2.c.

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 6209 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

References ast_log(), and LOG_ERROR.

Referenced by peer_set_srcaddr().

08274 {
08275    int sd;
08276    int res;
08277    
08278    sd = socket(AF_INET, SOCK_DGRAM, 0);
08279    if (sd < 0) {
08280       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
08281       return -1;
08282    }
08283 
08284    res = bind(sd, sa, salen);
08285    if (res < 0) {
08286       ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
08287       close(sd);
08288       return 1;
08289    }
08290 
08291    close(sd);
08292    return 0;
08293 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void delete_users ( void   )  [static]

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

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

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

08897 {
08898    ast_free_ha(peer->ha);
08899 
08900    /* Delete it, it needs to disappear */
08901    if (peer->expire > -1)
08902       ast_sched_del(sched, peer->expire);
08903    if (peer->pokeexpire > -1)
08904       ast_sched_del(sched, peer->pokeexpire);
08905    if (peer->callno > 0) {
08906       ast_mutex_lock(&iaxsl[peer->callno]);
08907       iax2_destroy(peer->callno);
08908       ast_mutex_unlock(&iaxsl[peer->callno]);
08909    }
08910 
08911    register_peer_exten(peer, 0);
08912 
08913    if (peer->dnsmgr)
08914       ast_dnsmgr_release(peer->dnsmgr);
08915 
08916    ast_string_field_free_pools(peer);
08917 
08918    free(peer);
08919 }

static void destroy_user ( struct iax2_user user  )  [static]

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

08869 {
08870    ast_free_ha(user->ha);
08871    free_context(user->contexts);
08872    if(user->vars) {
08873       ast_variables_destroy(user->vars);
08874       user->vars = NULL;
08875    }
08876    ast_string_field_free_pools(user);
08877    free(user);
08878 }

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

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

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

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

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

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

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

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

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

static int expire_registry ( void *  data  )  [static]

Definition at line 5558 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

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

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

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

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

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

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

Definition at line 3395 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

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

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8031 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and destroy_user().

08032 {
08033    struct iax2_context *conl;
08034    while(con) {
08035       conl = con;
08036       con = con->next;
08037       free(conl);
08038    }
08039 }

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

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

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

static int get_auth_methods ( char *  value  )  [static]

Definition at line 8257 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

08258 {
08259    int methods = 0;
08260    if (strstr(value, "rsa"))
08261       methods |= IAX_AUTH_RSA;
08262    if (strstr(value, "md5"))
08263       methods |= IAX_AUTH_MD5;
08264    if (strstr(value, "plaintext"))
08265       methods |= IAX_AUTH_PLAINTEXT;
08266    return methods;
08267 }

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

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

static int iax2_answer ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

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

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

Definition at line 2733 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

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

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

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

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

Definition at line 2417 of file chan_iax2.c.

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

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

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

Definition at line 2422 of file chan_iax2.c.

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

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

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

Definition at line 4474 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 4492 of file chan_iax2.c.

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

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

static int iax2_do_register ( struct iax2_registry reg  )  [static]

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

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

static int iax2_do_register_s ( void *  data  )  [static]

Definition at line 5241 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

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

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

Definition at line 4483 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

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

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

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

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

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

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

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

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

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

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

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

static int iax2_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

Definition at line 4501 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 4519 of file chan_iax2.c.

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

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

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

Definition at line 4510 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

static int iax2_poke_noanswer ( void *  data  )  [static]

Definition at line 7972 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

07973 {
07974    struct iax2_peer *peer = data;
07975    peer->pokeexpire = -1;
07976 #ifdef SCHED_MULTITHREADED
07977    if (schedule_action(__iax2_poke_noanswer, data))
07978 #endif      
07979       __iax2_poke_noanswer(data);
07980    return 0;
07981 }

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

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

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

static int iax2_poke_peer_s ( void *  data  )  [static]

Definition at line 5913 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

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

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

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

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 7689 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

07690 {
07691    struct iax2_thread *thread = data;
07692    ast_mutex_destroy(&thread->lock);
07693    ast_cond_destroy(&thread->cond);
07694    free(thread);
07695    ast_atomic_dec_and_test(&iaxactivethreadcount);
07696 }

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

Definition at line 7931 of file chan_iax2.c.

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

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

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

Definition at line 7833 of file chan_iax2.c.

References iax_prov_complete_template().

07834 {
07835    if (pos != 3)
07836       return NULL;
07837    return iax_prov_complete_template(line, word, pos, state);
07838 }

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

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

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

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

References ast_log(), ast_null_frame, and LOG_NOTICE.

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

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

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

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

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

Definition at line 9345 of file chan_iax2.c.

References reload_config().

09346 {
09347    return reload_config();
09348 }

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

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

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

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

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

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

Definition at line 2439 of file chan_iax2.c.

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

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

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

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

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

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

Definition at line 2427 of file chan_iax2.c.

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4462 of file chan_iax2.c.

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

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

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

References __iax2_show_peers().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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, 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    pthread_kill(netthreadid, SIGURG);
02411    signal_condition(&sched_lock, &sched_cond);
02412    return 0;
02413 }

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

Definition at line 5967 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

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

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

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

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

static int iax2_vnak ( int  callno  )  [static]

Definition at line 5887 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3058 of file chan_iax2.c.

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

Referenced by iax2_bridge().

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

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

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

Referenced by load_module().

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

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

Definition at line 4276 of file chan_iax2.c.

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

Referenced by load_module().

04277 {
04278    char *a[] = { "iax2", "show", "users" };
04279    int ret;
04280    const char *id = astman_get_header(m,"ActionID");
04281 
04282    if (!ast_strlen_zero(id))
04283       astman_append(s, "ActionID: %s\r\n",id);
04284    ret = __iax2_show_peers(1, -1, s, 3, a );
04285    astman_append(s, "\r\n\r\n" );
04286    return ret;
04287 } /* /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 3664 of file chan_iax2.c.

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

Referenced by decode_frame().

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

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

Definition at line 3688 of file chan_iax2.c.

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

Referenced by encrypt_frame().

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

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

Definition at line 4834 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

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

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

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

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

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

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

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

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

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

08921                              {
08922    /* Prune peers who still are supposed to be deleted */
08923    struct iax2_peer *peer = NULL;
08924 
08925    AST_LIST_LOCK(&peers);
08926    AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, entry) {
08927       if (ast_test_flag(peer, IAX_DELME)) {
08928          destroy_peer(peer);
08929          AST_LIST_REMOVE_CURRENT(&peers, entry);
08930       }
08931    }
08932    AST_LIST_TRAVERSE_SAFE_END
08933    AST_LIST_UNLOCK(&peers);
08934 }

static void prune_users ( void   )  [static]

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

08881 {
08882    struct iax2_user *user = NULL;
08883 
08884    AST_LIST_LOCK(&users);
08885    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, entry) {
08886       if (ast_test_flag(user, IAX_DELME)) {
08887          destroy_user(user);
08888          AST_LIST_REMOVE_CURRENT(&users, entry);
08889       }
08890    }
08891    AST_LIST_TRAVERSE_SAFE_END
08892    AST_LIST_UNLOCK(&users);
08893 
08894 }

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

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

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

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

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

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

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

Definition at line 2591 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

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

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

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

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

static void reg_source_db ( struct iax2_peer p  )  [static]

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

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

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

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

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

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

Verify inbound registration.

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

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

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

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

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

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

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

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

static char* regstate2str ( int  regstate  )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 9350 of file chan_iax2.c.

References reload_config().

09351 {
09352    return reload_config();
09353 }

static int reload_config ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4593 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

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

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

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

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

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

Definition at line 4598 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

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

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

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

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

Load configuration.

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

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

static void set_timing ( void   )  [static]

Definition at line 8936 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

08937 {
08938 #ifdef HAVE_ZAPTEL
08939    int bs = trunkfreq * 8;
08940    if (timingfd > -1) {
08941       if (
08942 #ifdef ZT_TIMERACK
08943          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
08944 #endif         
08945          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
08946          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
08947    }
08948 #endif
08949 }

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 6316 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_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.

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

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

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

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

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

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

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

static int start_network_thread ( void   )  [static]

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

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

static void stop_stuff ( int  callno  )  [static]

Definition at line 5787 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

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

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

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

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

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

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

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

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

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

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

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

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

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

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


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 9953 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 9933 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 9938 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 9948 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 9943 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 9928 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 9902 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 9894 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 9886 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 9844 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 9818 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 9910 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 9756 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 6308 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 9906 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 9898 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 9890 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 7890 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 7892 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 9840 of file chan_iax2.c.

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

Definition at line 7891 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 9832 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 9860 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 9878 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 9864 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 9836 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 9872 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 9848 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 9882 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 9828 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 9868 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 9855 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 Apr 30 07:39:46 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1