Mon Nov 24 15:34:28 2008

Asterisk developer's documentation


chan_iax2.c File Reference

Implementation of Inter-Asterisk eXchange Version 2. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/md5.h"
#include "asterisk/cdr.h"
#include "asterisk/crypto.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/app.h"
#include "asterisk/astdb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/localtime.h"
#include "asterisk/aes.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/netsock.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/astobj2.h"
#include "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
#include "jitterbuf.h"

Go to the source code of this file.

Data Structures

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

Defines

#define CACHE_FLAG_CANEXIST   (1 << 2)
#define CACHE_FLAG_EXISTS   (1 << 0)
#define CACHE_FLAG_MATCHMORE   (1 << 7)
#define CACHE_FLAG_NONEXISTENT   (1 << 1)
#define CACHE_FLAG_PENDING   (1 << 3)
#define CACHE_FLAG_TIMEOUT   (1 << 4)
#define CACHE_FLAG_TRANSMITTED   (1 << 5)
#define CACHE_FLAG_UNKNOWN   (1 << 6)
#define CALLNO_TO_PTR(a)   ((void *)(unsigned long)(a))
#define DEBUG_SCHED_MULTITHREAD
#define DEBUG_SUPPORT
#define DEFAULT_DROP   3
#define DEFAULT_FREQ_NOTOK   10 * 1000
#define DEFAULT_FREQ_OK   60 * 1000
#define DEFAULT_MAX_THREAD_COUNT   100
#define DEFAULT_MAXMS   2000
#define DEFAULT_RETRY_TIME   1000
#define DEFAULT_THREAD_COUNT   10
#define DEFAULT_TRUNKDATA   640 * 10
#define FORMAT   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n"
#define FORMAT   "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n"
#define FORMAT   "%-15.15s %-15d %-15d\n"
#define FORMAT   "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s"
#define FORMAT   "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n"
#define FORMAT2   "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n"
#define FORMAT2   "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n"
#define FORMAT2   "%-15.15s %-15.15s %-15.15s\n"
#define FORMAT2   "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s"
#define FORMAT2   "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n"
#define FORMATB   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n"
#define GAMMA   (0.01)
#define IAX2_TRUNK_PREFACE   (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))
#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF
#define IAX_CAPABILITY_LOWBANDWIDTH
#define IAX_CAPABILITY_LOWFREE
#define IAX_CAPABILITY_MEDBANDWIDTH
#define IAX_IOSTATE_IDLE   0
#define IAX_IOSTATE_PROCESSING   2
#define IAX_IOSTATE_READY   1
#define IAX_IOSTATE_SCHEDREADY   3
#define IAX_TYPE_DYNAMIC   2
#define IAX_TYPE_POOL   1
#define IPTOS_MINCOST   0x02
#define MAX_JITTER_BUFFER   50
#define MAX_PEER_BUCKETS   1
#define MAX_RETRY_TIME   10000
#define MAX_TIMESTAMP_SKEW   160
#define MAX_TRUNKDATA   640 * 200
#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS
#define MEMORY_SIZE   100
#define MIN_JITTER_BUFFER   10
#define MIN_RETRY_TIME   100
#define MIN_REUSE_TIME   60
#define NEW_ALLOW   1
#define NEW_FORCE   2
#define NEW_PREVENT   0
#define PTR_TO_CALLNO(a)   ((unsigned short)(unsigned long)(a))
#define SCHED_MULTITHREADED
#define schedule_action(func, data)   __schedule_action(func, data, __PRETTY_FUNCTION__)
#define TRUNK_CALL_START   ARRAY_LEN(iaxs) / 2
#define TS_GAP_FOR_JB_RESYNC   5000

Enumerations

enum  { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2), IAX_STATE_UNCHANGED = (1 << 3) }
enum  {
  IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3),
  IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7),
  IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12),
  IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16),
  IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20),
  IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24),
  IAX_DELAYPBXSTART = (1 << 25), IAX_ALLOWFWDOWNLOAD = (1 << 26)
}
enum  iax_reg_state {
  REG_STATE_UNREGISTERED = 0, REG_STATE_REGSENT, REG_STATE_AUTHSENT, REG_STATE_REGISTERED,
  REG_STATE_REJECTED, REG_STATE_TIMEOUT, REG_STATE_NOAUTH
}
enum  iax_transfer_state {
  TRANSFER_NONE = 0, TRANSFER_BEGIN, TRANSFER_READY, TRANSFER_RELEASED,
  TRANSFER_PASSTHROUGH, TRANSFER_MBEGIN, TRANSFER_MREADY, TRANSFER_MRELEASED,
  TRANSFER_MPASSTHROUGH, TRANSFER_MEDIA, TRANSFER_MEDIAPASS
}

Functions

static void __attempt_transmit (const void *data)
static void __auth_reject (const void *nothing)
static void __auto_congest (const void *nothing)
static void __auto_hangup (const void *nothing)
static int __do_deliver (void *data)
static void __expire_registry (const void *data)
static int __find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int return_locked, int check_dcallno)
static void __get_from_jb (const void *p)
static void __iax2_do_register_s (const void *data)
static void __iax2_poke_noanswer (const void *data)
static void __iax2_poke_peer_s (const void *data)
static int __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[])
static int __schedule_action (void(*func)(const void *data), const void *data, const char *funcname)
static int __send_command (struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const unsigned char *data, int datalen, int seqno, int now, int transfer, int final)
static void __send_lagrq (const void *data)
static void __send_ping (const void *data)
static int __unload_module (void)
static int apply_context (struct iax2_context *con, const char *context)
static int ast_cli_netstats (struct mansession *s, int fd, int limit_fmt)
static struct ast_channelast_iax2_new (int callno, int state, int capability)
 Create new call, interface with the PBX core.
static AST_LIST_HEAD_STATIC (dynamic_list, iax2_thread)
static AST_LIST_HEAD_STATIC (active_list, iax2_thread)
static AST_LIST_HEAD_STATIC (idle_list, iax2_thread)
static AST_LIST_HEAD_STATIC (registrations, iax2_registry)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Inter Asterisk eXchange (Ver 2)",.load=load_module,.unload=unload_module,.reload=reload,)
 AST_MUTEX_DEFINE_STATIC (dpcache_lock)
 AST_MUTEX_DEFINE_STATIC (tpeerlock)
 AST_MUTEX_DEFINE_STATIC (sched_lock)
static int attempt_transmit (const void *data)
static int auth_fail (int callno, int failcode)
static int auth_reject (const void *data)
static int authenticate (const char *challenge, const char *secret, const char *keyn, int authmethods, struct iax_ie_data *ied, struct sockaddr_in *sin, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx)
static int authenticate_reply (struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey)
static int authenticate_request (int call_num)
static int authenticate_verify (struct chan_iax2_pvt *p, struct iax_ies *ies)
static int auto_congest (const void *data)
static int auto_hangup (const 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 ast_channel *c, struct sockaddr_in *sin, struct create_addr_info *cai)
static int decode_frame (aes_decrypt_ctx *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen)
static int decrypt_frame (int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen)
static void defer_full_frame (struct iax2_thread *from_here, struct iax2_thread *to_here)
 Queue the last read full frame for processing by a certain thread.
static void delete_users (void)
static void destroy_firmware (struct iax_firmware *cur)
static void dp_lookup (int callno, const char *context, const char *callednum, const char *callerid, int skiplock)
static void * dp_lookup_thread (void *data)
static int encrypt_frame (aes_encrypt_ctx *ecx, struct ast_iax2_full_hdr *fh, unsigned char *poo, int *datalen)
static int expire_registry (const void *data)
static struct iax2_dpcachefind_cache (struct ast_channel *chan, const char *data, const char *context, const char *exten, int priority)
static int find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame)
static int find_callno_locked (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame)
static struct iax2_threadfind_idle_thread (void)
static struct iax2_peerfind_peer (const char *name, int realtime)
static struct iax2_trunk_peerfind_tpeer (struct sockaddr_in *sin, int fd)
static unsigned int fix_peerts (struct timeval *tv, int callno, unsigned int ts)
static void free_context (struct iax2_context *con)
static int function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int get_auth_methods (char *value)
static int get_encrypt_methods (const char *s)
static int get_from_jb (const void *p)
static void handle_deferred_full_frames (struct iax2_thread *thread)
 Handle any deferred full frames for this thread.
static int handle_error (void)
static int iax2_ack_registry (struct iax_ies *ies, struct sockaddr_in *sin, int callno)
 Acknowledgment received for OUR registration.
static int iax2_answer (struct ast_channel *c)
static enum ast_bridge_result iax2_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int iax2_call (struct ast_channel *c, char *dest, int timeout)
static int iax2_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 part of the IAX2 dial plan switch interface
static unsigned int iax2_datetime (const char *tz)
static void iax2_destroy (int callno)
static void iax2_destroy_helper (struct chan_iax2_pvt *pvt)
static int iax2_devicestate (void *data)
 Part of the device state notification system ---.
static int iax2_digit_begin (struct ast_channel *c, char digit)
static int iax2_digit_end (struct ast_channel *c, char digit, unsigned int duration)
static int iax2_do_debug (int fd, int argc, char *argv[])
static int iax2_do_jb_debug (int fd, int argc, char *argv[])
static int iax2_do_register (struct iax2_registry *reg)
static int iax2_do_register_s (const void *data)
static int iax2_do_trunk_debug (int fd, int argc, char *argv[])
static void iax2_dprequest (struct iax2_dpcache *dp, int callno)
static int iax2_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 Execute IAX2 dialplan switch.
static int iax2_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 Part of the IAX2 switch interface.
static int iax2_fixup (struct ast_channel *oldchannel, struct ast_channel *newchan)
static void iax2_frame_free (struct iax_frame *fr)
static int iax2_getpeername (struct sockaddr_in sin, char *host, int len)
static int iax2_getpeertrunk (struct sockaddr_in sin)
static int iax2_hangup (struct ast_channel *c)
static int iax2_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen)
static int iax2_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 Part of the IAX2 Switch interface.
static int iax2_no_debug (int fd, int argc, char *argv[])
static int iax2_no_jb_debug (int fd, int argc, char *argv[])
static int iax2_no_trunk_debug (int fd, int argc, char *argv[])
static int iax2_poke_noanswer (const void *data)
static int iax2_poke_peer (struct iax2_peer *peer, int heldcall)
static int iax2_poke_peer_cb (void *obj, void *arg, int flags)
static int iax2_poke_peer_s (const void *data)
static int iax2_predestroy (int callno)
static void * iax2_process_thread (void *data)
static void iax2_process_thread_cleanup (void *data)
static int iax2_prov_app (struct ast_channel *chan, void *data)
static int iax2_prov_cmd (int fd, int argc, char *argv[])
static char * iax2_prov_complete_template_3rd (const char *line, const char *word, int pos, int state)
static int iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force)
static int iax2_prune_realtime (int fd, int argc, char *argv[])
static int iax2_queue_control_data (int callno, enum ast_control_frame_type control, const void *data, size_t datalen)
 Queue a control frame on the ast_channel owner.
static int iax2_queue_frame (int callno, struct ast_frame *f)
 Queue a frame to a call's owning asterisk channel.
static int iax2_queue_hangup (int callno)
 Queue a hangup frame on the ast_channel owner.
static struct ast_frameiax2_read (struct ast_channel *c)
static int iax2_register (char *value, int lineno)
static int iax2_reload (int fd, int argc, char *argv[])
static struct ast_channeliax2_request (const char *type, int format, void *data, int *cause)
static int iax2_sched_add (struct sched_context *con, int when, ast_sched_cb callback, const void *data)
static int iax2_send (struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final)
static int iax2_sendhtml (struct ast_channel *c, int subclass, const char *data, int datalen)
static int iax2_sendimage (struct ast_channel *c, struct ast_frame *img)
static int iax2_sendtext (struct ast_channel *c, const char *text)
static int iax2_setoption (struct ast_channel *c, int option, void *data, int datalen)
static int iax2_show_cache (int fd, int argc, char *argv[])
static int iax2_show_channels (int fd, int argc, char *argv[])
static int iax2_show_firmware (int fd, int argc, char *argv[])
static int iax2_show_netstats (int fd, int argc, char *argv[])
static int iax2_show_peer (int fd, int argc, char *argv[])
 Show one peer in detail.
static int iax2_show_peers (int fd, int argc, char *argv[])
static int iax2_show_registry (int fd, int argc, char *argv[])
static int iax2_show_stats (int fd, int argc, char *argv[])
static int iax2_show_threads (int fd, int argc, char *argv[])
static int iax2_show_users (int fd, int argc, char *argv[])
static int iax2_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly)
static int iax2_test_losspct (int fd, int argc, char *argv[])
static int iax2_transfer (struct ast_channel *c, const char *dest)
static int iax2_transmit (struct iax_frame *fr)
static int iax2_trunk_expired (struct iax2_trunk_peer *tpeer, struct timeval *now)
static int iax2_trunk_queue (struct chan_iax2_pvt *pvt, struct iax_frame *fr)
static int iax2_vnak (int callno)
static int iax2_write (struct ast_channel *c, struct ast_frame *f)
static int iax_check_version (char *dev)
static void iax_debug_output (const char *data)
static void iax_error_output (const char *data)
static int iax_firmware_append (struct iax_ie_data *ied, const unsigned char *dev, unsigned int desc)
static int iax_park (struct ast_channel *chan1, struct ast_channel *chan2)
static void * iax_park_thread (void *stuff)
static struct iax_frameiaxfrdup2 (struct iax_frame *fr)
static void insert_idle_thread (struct iax2_thread *thread)
static void jb_debug_output (const char *fmt,...)
static void jb_error_output (const char *fmt,...)
static void jb_warning_output (const char *fmt,...)
static int load_module (void)
 Load IAX2 module, load configuraiton ---.
static void lock_both (unsigned short callno0, unsigned short callno1)
static int make_trunk (unsigned short callno, int locked)
static int manager_iax2_show_netstats (struct mansession *s, const struct message *m)
static int manager_iax2_show_peers (struct mansession *s, const struct message *m)
static int match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, struct chan_iax2_pvt *cur, int check_dcallno)
static void memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, aes_decrypt_ctx *dcx)
static void memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, aes_encrypt_ctx *ecx)
static void merge_encryption (struct chan_iax2_pvt *p, unsigned int enc)
static void * network_thread (void *ignore)
static struct chan_iax2_pvtnew_iax (struct sockaddr_in *sin, const char *host)
static void parse_dial_string (char *data, struct parsed_dial_string *pds)
 Parses an IAX dial string into its component parts.
static int peer_cmp_cb (void *obj, void *arg, int flags)
static int peer_delme_cb (void *obj, void *arg, int flags)
static void peer_destructor (void *obj)
static int peer_hash_cb (const void *obj, const int flags)
static struct iax2_peerpeer_ref (struct iax2_peer *peer)
static int peer_set_sock_cb (void *obj, void *arg, int flags)
static int peer_set_srcaddr (struct iax2_peer *peer, const char *srcaddr)
 Parse the "sourceaddress" value, lookup in netsock list and set peer's sockfd. Defaults to defaultsockfd if not found.
static int peer_status (struct iax2_peer *peer, char *status, int statuslen)
 peer_status: Report Peer status in character string
static struct iax2_peerpeer_unref (struct iax2_peer *peer)
static void poke_all_peers (void)
static void prune_peers (void)
static void prune_users (void)
static int pvt_cmp_cb (void *obj, void *arg, int flags)
static void pvt_destructor (void *obj)
static int pvt_hash_cb (const void *obj, const int flags)
static int raw_hangup (struct sockaddr_in *sin, unsigned short src, unsigned short dst, int sockfd)
static struct iax2_peerrealtime_peer (const char *peername, struct sockaddr_in *sin)
static void realtime_update_peer (const char *peername, struct sockaddr_in *sin, time_t regtime)
static struct iax2_userrealtime_user (const char *username, struct sockaddr_in *sin)
static void reg_source_db (struct iax2_peer *p)
static void register_peer_exten (struct iax2_peer *peer, int onoff)
static int register_verify (int callno, struct sockaddr_in *sin, struct iax_ies *ies)
 Verify inbound registration.
static int registry_authrequest (int callno)
static int registry_rerequest (struct iax_ies *ies, int callno, struct sockaddr_in *sin)
static char * regstate2str (int regstate)
static int reload (void)
static int reload_config (void)
static void reload_firmware (int unload)
static void remove_by_peercallno (struct chan_iax2_pvt *pvt)
static void save_rr (struct iax_frame *fr, struct iax_ies *ies)
static void * sched_thread (void *ignore)
static int schedule_delivery (struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout)
static int send_apathetic_reply (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int command, int ts, unsigned char seqno)
static int send_command (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_final (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_immediate (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_locked (unsigned short callno, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_transfer (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int)
static int send_lagrq (const void *data)
static int send_packet (struct iax_frame *f)
static int send_ping (const void *data)
static int send_trunk (struct iax2_trunk_peer *tpeer, struct timeval *now)
static int set_config (char *config_file, int reload)
 Load configuration.
static void set_config_destroy (void)
static void set_timing (void)
static void signal_condition (ast_mutex_t *lock, ast_cond_t *cond)
static int socket_process (struct iax2_thread *thread)
static int socket_read (int *id, int fd, short events, void *cbdata)
static void spawn_dp_lookup (int callno, const char *context, const char *callednum, const char *callerid)
static int start_network_thread (void)
static void stop_stuff (int callno)
static void store_by_peercallno (struct chan_iax2_pvt *pvt)
static int timing_read (int *id, int fd, short events, void *cbdata)
static int transmit_trunk (struct iax_frame *f, struct sockaddr_in *sin, int sockfd)
static int try_firmware (char *s)
static int try_transfer (struct chan_iax2_pvt *pvt, struct iax_ies *ies)
static int uncompress_subclass (unsigned char csub)
static void unlink_peer (struct iax2_peer *peer)
static int unload_module (void)
static void unlock_both (unsigned short callno0, unsigned short callno1)
static void unwrap_timestamp (struct iax_frame *fr)
static void update_jbsched (struct chan_iax2_pvt *pvt)
static void update_max_nontrunk (void)
static void update_max_trunk (void)
static int update_packet (struct iax_frame *f)
static int update_registry (struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh)
static int user_cmp_cb (void *obj, void *arg, int flags)
static int user_delme_cb (void *obj, void *arg, int flags)
static void user_destructor (void *obj)
static int user_hash_cb (const void *obj, const int flags)
static struct iax2_useruser_ref (struct iax2_user *user)
static struct iax2_useruser_unref (struct iax2_user *user)
static void vnak_retransmit (int callno, int last)

Variables

static char accountcode [AST_MAX_ACCOUNT_CODE]
static int adsi = 0
static int amaflags = 0
static int authdebug = 1
static int autokill = 0
static struct ast_cli_entry cli_iax2 []
static struct ast_cli_entry cli_iax2_jb_debug_deprecated
static struct ast_cli_entry cli_iax2_no_debug_deprecated
static struct ast_cli_entry cli_iax2_no_jb_debug_deprecated
static struct ast_cli_entry cli_iax2_no_trunk_debug_deprecated
static struct ast_cli_entry cli_iax2_trunk_debug_deprecated
static char context [80] = "default"
static char debug_jb_usage []
static char debug_trunk_usage []
static char debug_usage []
static int defaultsockfd = -1
static int delayreject = 0
static struct iax2_dpcachedpcache
static int global_rtautoclear = 120
static struct ast_flags globalflags = { 0 }
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH
static int iax2_encryption = 0
enum { ... }  iax2_flags
int(*) iax2_regfunk (const char *username, int onoff) = NULL
static char iax2_reload_usage []
enum { ... }  iax2_state
static struct ast_switch iax2_switch
static struct ast_channel_tech iax2_tech
static char iax2_test_losspct_usage []
static struct ao2_containeriax_peercallno_pvts
 Another container of iax2_pvt structures.
static int iaxactivethreadcount = 0
static int iaxcompat = 0
static int iaxdebug = 0
static int iaxdefaultdpcache = 10 * 60
static int iaxdefaulttimeout = 5
static int iaxdynamicthreadcount = 0
static int iaxdynamicthreadnum = 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 [ARRAY_LEN(iaxs)]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct io_contextio
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static struct timeval lastused [ARRAY_LEN(iaxs)]
static int max_reg_expire
static int max_retries = 4
static int maxauthreq = 3
static int maxjitterbuffer = 1000
static int maxjitterinterps = 10
static int maxnontrunkcall = 1
static int maxtrunkcall = TRUNK_CALL_START
static int min_reg_expire
static char mohinterpret [MAX_MUSICCLASS]
static char mohsuggest [MAX_MUSICCLASS]
static struct ast_netsock_listnetsock
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_jb_usage []
static char no_debug_trunk_usage []
static char no_debug_usage []
static struct ast_netsock_listoutsock
static char * papp = "IAX2Provision"
static char * pdescrip
static struct ao2_containerpeers
static int ping_time = 21
static struct ast_codec_pref prefs
static char prune_realtime_usage []
static char * psyn = "Provision a calling IAXy with a given template"
static char regcontext [AST_MAX_CONTEXT] = ""
static int resyncthreshold = 1000
static struct sched_contextsched
static ast_cond_t sched_cond
static pthread_t schedthreadid = AST_PTHREADT_NULL
static char show_cache_usage []
static char show_channels_usage []
static char show_firmware_usage []
static char show_netstats_usage []
static char show_peer_usage []
static char show_peers_usage []
static char show_prov_usage []
static char show_reg_usage []
static char show_stats_usage []
static char show_threads_usage []
static char show_users_usage []
static const char tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)"
static int test_losspct = 0
static int timingfd = -1
static unsigned int tos = 0
static struct iax2_trunk_peertpeers
static int trunkfreq = 20
static struct ao2_containerusers
static struct ast_firmware_list waresl


Detailed Description

Implementation of Inter-Asterisk eXchange Version 2.

Author:
Mark Spencer <markster@digium.com>
See also

Definition in file chan_iax2.c.


Define Documentation

#define CACHE_FLAG_CANEXIST   (1 << 2)

Extension can exist

Definition at line 663 of file chan_iax2.c.

Referenced by complete_dpreply(), iax2_canmatch(), and iax2_show_cache().

#define CACHE_FLAG_EXISTS   (1 << 0)

Extension exists

Definition at line 659 of file chan_iax2.c.

Referenced by complete_dpreply(), iax2_exec(), iax2_exists(), and iax2_show_cache().

#define CACHE_FLAG_MATCHMORE   (1 << 7)

Matchmore

Definition at line 673 of file chan_iax2.c.

Referenced by complete_dpreply(), iax2_matchmore(), and iax2_show_cache().

#define CACHE_FLAG_NONEXISTENT   (1 << 1)

Extension is nonexistent

Definition at line 661 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

#define CACHE_FLAG_PENDING   (1 << 3)

Waiting to hear back response

Definition at line 665 of file chan_iax2.c.

Referenced by complete_dpreply(), find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TIMEOUT   (1 << 4)

Timed out

Definition at line 667 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

Definition at line 669 of file chan_iax2.c.

Referenced by iax2_dprequest(), iax2_show_cache(), and socket_process().

#define CACHE_FLAG_UNKNOWN   (1 << 6)

Timeout

Definition at line 671 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 123 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 111 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 131 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

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

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 126 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 194 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 127 of file chan_iax2.c.

Referenced by __find_callno(), and complete_transfer().

#define DEFAULT_THREAD_COUNT   10

Definition at line 125 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

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

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 177 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 185 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 190 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 179 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 694 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 696 of file chan_iax2.c.

#define IAX_IOSTATE_READY   1

Definition at line 695 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 697 of file chan_iax2.c.

Referenced by __schedule_action().

#define IAX_TYPE_DYNAMIC   2

Definition at line 700 of file chan_iax2.c.

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

#define IAX_TYPE_POOL   1

Definition at line 699 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 114 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 436 of file chan_iax2.c.

#define MAX_PEER_BUCKETS   1

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

Definition at line 645 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 440 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 650 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 128 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 437 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 433 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 133 of file chan_iax2.c.

Referenced by __find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1439 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

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

Referenced by socket_process().

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

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

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

Definition at line 981 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   ARRAY_LEN(iaxs) / 2

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

00230      {
00231    IAX_STATE_STARTED =     (1 << 0),
00232    IAX_STATE_AUTHENTICATED =  (1 << 1),
00233    IAX_STATE_TBD =      (1 << 2),
00234    IAX_STATE_UNCHANGED =      (1 << 3),
00235 } iax2_state;

anonymous enum

Enumerator:
IAX_HASCALLERID  CallerID has been specified
IAX_DELME  Needs to be deleted
IAX_TEMPONLY  Temporary (realtime)
IAX_TRUNK  Treat as a trunk
IAX_NOTRANSFER  Don't native bridge
IAX_USEJITTERBUF  Use jitter buffer
IAX_DYNAMIC  dynamic peer
IAX_SENDANI  Send ANI along with CallerID
IAX_ALREADYGONE  Already disconnected
IAX_PROVISION  This is a provisioning request
IAX_QUELCH  Whether or not we quelch audio
IAX_ENCRYPTED  Whether we should assume encrypted tx/rx
IAX_KEYPOPULATED  Whether we have a key populated
IAX_CODEC_USER_FIRST  are we willing to let the other guy choose the codec?
IAX_CODEC_NOPREFS  Force old behaviour by turning off prefs
IAX_CODEC_NOCAP  only consider requested format and ignore capabilities
IAX_RTCACHEFRIENDS  let realtime stay till your reload
IAX_RTUPDATE  Send a realtime update
IAX_RTAUTOCLEAR  erase me on expire
IAX_FORCEJITTERBUF  Force jitterbuffer, even when bridged to a channel that can take jitter
IAX_RTIGNOREREGEXPIRE  When using realtime, ignore registration expiration
IAX_TRUNKTIMESTAMPS  Send trunk timestamps
IAX_TRANSFERMEDIA  When doing IAX2 transfers, transfer media only
IAX_MAXAUTHREQ  Maximum outstanding AUTHREQ restriction is in place
IAX_DELAYPBXSTART  Don't start a PBX on the channel until the peer sends us a response, so that we've achieved a three-way handshake with them before sending voice or anything else
IAX_ALLOWFWDOWNLOAD  Allow the FWDOWNL command?

Definition at line 242 of file chan_iax2.c.

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


Function Documentation

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

Definition at line 2189 of file chan_iax2.c.

References AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, chan_iax2_pvt::error, f, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, ast_format::name, 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().

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

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

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

06397 {
06398    /* Called from IAX thread only, without iaxs lock */
06399    int callno = (int)(long)(nothing);
06400    struct iax_ie_data ied;
06401    ast_mutex_lock(&iaxsl[callno]);
06402    if (iaxs[callno]) {
06403       memset(&ied, 0, sizeof(ied));
06404       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06405          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06406          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06407       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06408          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06409          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06410       }
06411       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06412    }
06413    ast_mutex_unlock(&iaxsl[callno]);
06414 }

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

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

03151 {
03152    int callno = PTR_TO_CALLNO(nothing);
03153    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03154    ast_mutex_lock(&iaxsl[callno]);
03155    if (iaxs[callno]) {
03156       iaxs[callno]->initid = -1;
03157       iax2_queue_frame(callno, &f);
03158       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03159    }
03160    ast_mutex_unlock(&iaxsl[callno]);
03161 }

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

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

06446 {
06447    /* Called from IAX thread only, without iaxs lock */
06448    int callno = (int)(long)(nothing);
06449    struct iax_ie_data ied;
06450    ast_mutex_lock(&iaxsl[callno]);
06451    if (iaxs[callno]) {
06452       memset(&ied, 0, sizeof(ied));
06453       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06454       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06455       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06456    }
06457    ast_mutex_unlock(&iaxsl[callno]);
06458 }

static int __do_deliver ( void *  data  )  [static]

Note:
This function assumes that iaxsl[callno] is locked when called.

IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it. This function calls iax2_queue_frame(), which may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 2056 of file chan_iax2.c.

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

Referenced by __get_from_jb(), and schedule_delivery().

02057 {
02058    /* Just deliver the packet by using queueing.  This is called by
02059      the IAX thread with the iaxsl lock held. */
02060    struct iax_frame *fr = data;
02061    fr->retrans = -1;
02062    ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
02063    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
02064       iax2_queue_frame(fr->callno, &fr->af);
02065    /* Free our iax frame */
02066    iax2_frame_free(fr);
02067    /* And don't run again */
02068    return 0;
02069 }

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

Definition at line 6084 of file chan_iax2.c.

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

Referenced by expire_registry().

06085 {
06086    struct iax2_peer *peer = (struct iax2_peer *) data;
06087 
06088    if (!peer)
06089       return;
06090 
06091    peer->expire = -1;
06092 
06093    if (option_debug)
06094       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
06095    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
06096       realtime_update_peer(peer->name, &peer->addr, 0);
06097    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
06098    /* Reset the address */
06099    memset(&peer->addr, 0, sizeof(peer->addr));
06100    /* Reset expiry value */
06101    peer->expiry = min_reg_expire;
06102    if (!ast_test_flag(peer, IAX_TEMPONLY))
06103       ast_db_del("IAX/Registry", peer->name);
06104    register_peer_exten(peer, 0);
06105    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
06106    if (iax2_regfunk)
06107       iax2_regfunk(peer->name, 0);
06108 
06109    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
06110       unlink_peer(peer);
06111 
06112    peer_unref(peer);
06113 }

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

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

Definition at line 1529 of file chan_iax2.c.

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

Referenced by find_callno(), and find_callno_locked().

01530 {
01531    int res = 0;
01532    int x;
01533    struct timeval now;
01534    char host[80];
01535 
01536    if (new <= NEW_ALLOW) {
01537       if (callno) {
01538          struct chan_iax2_pvt *pvt;
01539          struct chan_iax2_pvt tmp_pvt = {
01540             .callno = dcallno,
01541             .peercallno = callno,
01542             /* hack!! */
01543             .frames_received = check_dcallno,
01544          };
01545  
01546          memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
01547  
01548          if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
01549             if (return_locked) {
01550                ast_mutex_lock(&iaxsl[pvt->callno]);
01551             }
01552             res = pvt->callno;
01553             ao2_ref(pvt, -1);
01554             pvt = NULL;
01555             return res;
01556          }
01557       }
01558 
01559       /* This will occur on the first response to a message that we initiated,
01560        * such as a PING. */
01561       if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) {
01562          iaxs[dcallno]->peercallno = callno;
01563          res = dcallno;
01564          store_by_peercallno(iaxs[dcallno]);
01565          return res;
01566       }
01567 
01568 #ifdef IAX_OLD_FIND
01569       /* If we get here, we SHOULD NOT find a call structure for this
01570          callno; if we do, it means that there is a call structure that
01571          has a peer callno but did NOT get entered into the hash table,
01572          which is bad.
01573 
01574          If we find a call structure using this old, slow method, output a log
01575          message so we'll know about it. After a few months of leaving this in
01576          place, if we don't hear about people seeing these messages, we can
01577          remove this code for good.
01578       */
01579 
01580       for (x = 1; !res && x < maxnontrunkcall; x++) {
01581          ast_mutex_lock(&iaxsl[x]);
01582          if (iaxs[x]) {
01583             /* Look for an exact match */
01584             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01585                res = x;
01586             }
01587          }
01588          if (!res || !return_locked)
01589             ast_mutex_unlock(&iaxsl[x]);
01590       }
01591 
01592       for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) {
01593          ast_mutex_lock(&iaxsl[x]);
01594          if (iaxs[x]) {
01595             /* Look for an exact match */
01596             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01597                res = x;
01598             }
01599          }
01600          if (!res || !return_locked)
01601             ast_mutex_unlock(&iaxsl[x]);
01602       }
01603 
01604       if (res) {
01605          ast_log(LOG_WARNING, "Old call search code found call number %d that was not in hash table!\n", res);
01606       }
01607 #endif
01608    }
01609    if (!res && (new >= NEW_ALLOW)) {
01610       int start, found = 0;
01611 
01612       /* It may seem odd that we look through the peer list for a name for
01613        * this *incoming* call.  Well, it is weird.  However, users don't
01614        * have an IP address/port number that we can match against.  So,
01615        * this is just checking for a peer that has that IP/port and
01616        * assuming that we have a user of the same name.  This isn't always
01617        * correct, but it will be changed if needed after authentication. */
01618       if (!iax2_getpeername(*sin, host, sizeof(host)))
01619          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01620 
01621       now = ast_tvnow();
01622       start = 2 + (ast_random() % (TRUNK_CALL_START - 1));
01623       for (x = start; 1; x++) {
01624          if (x == TRUNK_CALL_START) {
01625             x = 1;
01626             continue;
01627          }
01628 
01629          /* Find first unused call number that hasn't been used in a while */
01630          ast_mutex_lock(&iaxsl[x]);
01631          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01632             found = 1;
01633             break;
01634          }
01635          ast_mutex_unlock(&iaxsl[x]);
01636          
01637          if (x == start - 1) {
01638             break;
01639          }
01640       }
01641       /* We've still got lock held if we found a spot */
01642       if (x == start - 1 && !found) {
01643          ast_log(LOG_WARNING, "No more space\n");
01644          return 0;
01645       }
01646       iaxs[x] = new_iax(sin, host);
01647       update_max_nontrunk();
01648       if (iaxs[x]) {
01649          if (option_debug && iaxdebug)
01650             ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
01651          iaxs[x]->sockfd = sockfd;
01652          iaxs[x]->addr.sin_port = sin->sin_port;
01653          iaxs[x]->addr.sin_family = sin->sin_family;
01654          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01655          iaxs[x]->peercallno = callno;
01656          iaxs[x]->callno = x;
01657          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01658          iaxs[x]->expiry = min_reg_expire;
01659          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01660          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01661          iaxs[x]->amaflags = amaflags;
01662          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01663          
01664          ast_string_field_set(iaxs[x], accountcode, accountcode);
01665          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01666          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01667 
01668          if (iaxs[x]->peercallno) {
01669             store_by_peercallno(iaxs[x]);
01670          }
01671       } else {
01672          ast_log(LOG_WARNING, "Out of resources\n");
01673          ast_mutex_unlock(&iaxsl[x]);
01674          return 0;
01675       }
01676       if (!return_locked)
01677          ast_mutex_unlock(&iaxsl[x]);
01678       res = x;
01679    }
01680    return res;
01681 }

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

Definition at line 2592 of file chan_iax2.c.

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

Referenced by get_from_jb().

02593 {
02594    int callno = PTR_TO_CALLNO(p);
02595    struct chan_iax2_pvt *pvt = NULL;
02596    struct iax_frame *fr;
02597    jb_frame frame;
02598    int ret;
02599    long now;
02600    long next;
02601    struct timeval tv;
02602    
02603    /* Make sure we have a valid private structure before going on */
02604    ast_mutex_lock(&iaxsl[callno]);
02605    pvt = iaxs[callno];
02606    if (!pvt) {
02607       /* No go! */
02608       ast_mutex_unlock(&iaxsl[callno]);
02609       return;
02610    }
02611 
02612    pvt->jbid = -1;
02613    
02614    gettimeofday(&tv,NULL);
02615    /* round up a millisecond since ast_sched_runq does; */
02616    /* prevents us from spinning while waiting for our now */
02617    /* to catch up with runq's now */
02618    tv.tv_usec += 1000;
02619    
02620    now = ast_tvdiff_ms(tv, pvt->rxcore);
02621    
02622    if(now >= (next = jb_next(pvt->jb))) {
02623       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02624       switch(ret) {
02625       case JB_OK:
02626          fr = frame.data;
02627          __do_deliver(fr);
02628          /* __do_deliver() can cause the call to disappear */
02629          pvt = iaxs[callno];
02630          break;
02631       case JB_INTERP:
02632       {
02633          struct ast_frame af = { 0, };
02634          
02635          /* create an interpolation frame */
02636          af.frametype = AST_FRAME_VOICE;
02637          af.subclass = pvt->voiceformat;
02638          af.samples  = frame.ms * 8;
02639          af.src  = "IAX2 JB interpolation";
02640          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02641          af.offset = AST_FRIENDLY_OFFSET;
02642          
02643          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02644           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02645          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
02646             iax2_queue_frame(callno, &af);
02647             /* iax2_queue_frame() could cause the call to disappear */
02648             pvt = iaxs[callno];
02649          }
02650       }
02651          break;
02652       case JB_DROP:
02653          iax2_frame_free(frame.data);
02654          break;
02655       case JB_NOFRAME:
02656       case JB_EMPTY:
02657          /* do nothing */
02658          break;
02659       default:
02660          /* shouldn't happen */
02661          break;
02662       }
02663    }
02664    if (pvt)
02665       update_jbsched(pvt);
02666    ast_mutex_unlock(&iaxsl[callno]);
02667 }

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

Definition at line 5777 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05778 {
05779    struct iax2_registry *reg = (struct iax2_registry *)data;
05780    reg->expire = -1;
05781    iax2_do_register(reg);
05782 }

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

Definition at line 8882 of file chan_iax2.c.

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

Referenced by iax2_poke_noanswer().

08883 {
08884    struct iax2_peer *peer = (struct iax2_peer *)data;
08885    int callno;
08886 
08887    if (peer->lastms > -1) {
08888       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08889       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08890       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08891    }
08892    if ((callno = peer->callno) > 0) {
08893       ast_mutex_lock(&iaxsl[callno]);
08894       iax2_destroy(callno);
08895       ast_mutex_unlock(&iaxsl[callno]);
08896    }
08897    peer->callno = 0;
08898    peer->lastms = -1;
08899    /* Try again quickly */
08900    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08901    if (peer->pokeexpire == -1)
08902       peer_unref(peer);
08903 }

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

Definition at line 6508 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06509 {
06510    struct iax2_peer *peer = (struct iax2_peer *)data;
06511    iax2_poke_peer(peer, 0);
06512    peer_unref(peer);
06513 }

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

Definition at line 4570 of file chan_iax2.c.

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

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

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

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

Definition at line 956 of file chan_iax2.c.

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

00957 {
00958    struct iax2_thread *thread = NULL;
00959    static time_t lasterror;
00960    static time_t t;
00961 
00962    thread = find_idle_thread();
00963 
00964    if (thread != NULL) {
00965       thread->schedfunc = func;
00966       thread->scheddata = data;
00967       thread->iostate = IAX_IOSTATE_SCHEDREADY;
00968 #ifdef DEBUG_SCHED_MULTITHREAD
00969       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
00970 #endif
00971       signal_condition(&thread->lock, &thread->cond);
00972       return 0;
00973    }
00974    time(&t);
00975    if (t != lasterror && option_debug) 
00976       ast_log(LOG_DEBUG, "Out of idle IAX2 threads for scheduling!\n");
00977    lasterror = t;
00978 
00979    return -1;
00980 }

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

References f, and iax2_send().

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

05073 {
05074    struct ast_frame f = { 0, };
05075 
05076    f.frametype = type;
05077    f.subclass = command;
05078    f.datalen = datalen;
05079    f.src = __FUNCTION__;
05080    f.data = (void *) data;
05081 
05082    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05083 }

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

Definition at line 1041 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, iaxsl, LOG_WARNING, sched, send_command(), and send_lagrq().

Referenced by send_lagrq().

01042 {
01043    int callno = (long) data;
01044 
01045    ast_mutex_lock(&iaxsl[callno]);
01046 
01047    if (iaxs[callno]) {
01048       if (iaxs[callno]->peercallno) {
01049          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01050          iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01051       } else {
01052          /* I am the schedule, so I'm allowed to do this */
01053          iaxs[callno]->lagid = -1;
01054       }
01055    } else {
01056       ast_log(LOG_WARNING, "I was supposed to send a LAGRQ with callno %d, but no such call exists (and I cannot remove lagid, either).\n", callno);
01057    }
01058 
01059    ast_mutex_unlock(&iaxsl[callno]);
01060 }

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

Definition at line 996 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_PING, iaxsl, LOG_DEBUG, option_debug, sched, send_command(), and send_ping().

Referenced by send_ping().

00997 {
00998    int callno = (long) data;
00999 
01000    ast_mutex_lock(&iaxsl[callno]);
01001 
01002    if (iaxs[callno]) {
01003       if (iaxs[callno]->peercallno) {
01004          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
01005          iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
01006       } else {
01007          /* I am the schedule, so I'm allowed to do this */
01008          iaxs[callno]->pingid = -1;
01009       }
01010    } else if (option_debug > 0) {
01011       ast_log(LOG_DEBUG, "I was supposed to send a PING with callno %d, but no such call exists (and I cannot remove pingid, either).\n", callno);
01012    }
01013 
01014    ast_mutex_unlock(&iaxsl[callno]);
01015 }

static int __unload_module ( void   )  [static]

Definition at line 11001 of file chan_iax2.c.

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

11002 {
11003    struct iax2_thread *thread = NULL;
11004    int x;
11005 
11006    /* Make sure threads do not hold shared resources when they are canceled */
11007    
11008    /* Grab the sched lock resource to keep it away from threads about to die */
11009    /* Cancel the network thread, close the net socket */
11010    if (netthreadid != AST_PTHREADT_NULL) {
11011       AST_LIST_LOCK(&iaxq.queue);
11012       ast_mutex_lock(&sched_lock);
11013       pthread_cancel(netthreadid);
11014       ast_cond_signal(&sched_cond);
11015       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
11016       AST_LIST_UNLOCK(&iaxq.queue);
11017       pthread_join(netthreadid, NULL);
11018    }
11019    if (schedthreadid != AST_PTHREADT_NULL) {
11020       ast_mutex_lock(&sched_lock);  
11021       pthread_cancel(schedthreadid);
11022       ast_cond_signal(&sched_cond);
11023       ast_mutex_unlock(&sched_lock);   
11024       pthread_join(schedthreadid, NULL);
11025    }
11026    
11027    /* Call for all threads to halt */
11028    AST_LIST_LOCK(&idle_list);
11029    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
11030       AST_LIST_REMOVE_CURRENT(&idle_list, list);
11031       pthread_cancel(thread->threadid);
11032    }
11033    AST_LIST_TRAVERSE_SAFE_END
11034    AST_LIST_UNLOCK(&idle_list);
11035 
11036    AST_LIST_LOCK(&active_list);
11037    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
11038       AST_LIST_REMOVE_CURRENT(&active_list, list);
11039       pthread_cancel(thread->threadid);
11040    }
11041    AST_LIST_TRAVERSE_SAFE_END
11042    AST_LIST_UNLOCK(&active_list);
11043 
11044    AST_LIST_LOCK(&dynamic_list);
11045         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
11046       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
11047       pthread_cancel(thread->threadid);
11048         }
11049    AST_LIST_TRAVERSE_SAFE_END
11050         AST_LIST_UNLOCK(&dynamic_list);
11051 
11052    AST_LIST_HEAD_DESTROY(&iaxq.queue);
11053 
11054    /* Wait for threads to exit */
11055    while(0 < iaxactivethreadcount)
11056       usleep(10000);
11057    
11058    ast_netsock_release(netsock);
11059    ast_netsock_release(outsock);
11060    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
11061       if (iaxs[x]) {
11062          iax2_destroy(x);
11063       }
11064    }
11065    ast_manager_unregister( "IAXpeers" );
11066    ast_manager_unregister( "IAXnetstats" );
11067    ast_unregister_application(papp);
11068    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11069    ast_unregister_switch(&iax2_switch);
11070    ast_channel_unregister(&iax2_tech);
11071    delete_users();
11072    iax_provision_unload();
11073    sched_context_destroy(sched);
11074    reload_firmware(1);
11075 
11076    ast_mutex_destroy(&waresl.lock);
11077 
11078    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11079       ast_mutex_destroy(&iaxsl[x]);
11080    }
11081 
11082    ao2_ref(peers, -1);
11083    ao2_ref(users, -1);
11084    ao2_ref(iax_peercallno_pvts, -1);
11085 
11086    return 0;
11087 }

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

Definition at line 5124 of file chan_iax2.c.

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

Referenced by check_access().

05125 {
05126    while(con) {
05127       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05128          return -1;
05129       con = con->next;
05130    }
05131    return 0;
05132 }

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

Definition at line 4898 of file chan_iax2.c.

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

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04899 {
04900    int x;
04901    int numchans = 0;
04902    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04903       ast_mutex_lock(&iaxsl[x]);
04904       if (iaxs[x]) {
04905          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04906          char *fmt;
04907          jb_info jbinfo;
04908          
04909          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04910             jb_getinfo(iaxs[x]->jb, &jbinfo);
04911             localjitter = jbinfo.jitter;
04912             localdelay = jbinfo.current - jbinfo.min;
04913             locallost = jbinfo.frames_lost;
04914             locallosspct = jbinfo.losspct/1000;
04915             localdropped = jbinfo.frames_dropped;
04916             localooo = jbinfo.frames_ooo;
04917          } else {
04918             localjitter = -1;
04919             localdelay = 0;
04920             locallost = -1;
04921             locallosspct = -1;
04922             localdropped = 0;
04923             localooo = -1;
04924          }
04925          if (limit_fmt)
04926             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04927          else
04928             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04929          if (s)
04930             
04931             astman_append(s, fmt,
04932                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04933                      iaxs[x]->pingtime,
04934                      localjitter, 
04935                      localdelay,
04936                      locallost,
04937                      locallosspct,
04938                      localdropped,
04939                      localooo,
04940                      iaxs[x]->frames_received/1000,
04941                      iaxs[x]->remote_rr.jitter,
04942                      iaxs[x]->remote_rr.delay,
04943                      iaxs[x]->remote_rr.losscnt,
04944                      iaxs[x]->remote_rr.losspct,
04945                      iaxs[x]->remote_rr.dropped,
04946                      iaxs[x]->remote_rr.ooo,
04947                      iaxs[x]->remote_rr.packets/1000);
04948          else
04949             ast_cli(fd, fmt,
04950                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04951                iaxs[x]->pingtime,
04952                localjitter, 
04953                localdelay,
04954                locallost,
04955                locallosspct,
04956                localdropped,
04957                localooo,
04958                iaxs[x]->frames_received/1000,
04959                iaxs[x]->remote_rr.jitter,
04960                iaxs[x]->remote_rr.delay,
04961                iaxs[x]->remote_rr.losscnt,
04962                iaxs[x]->remote_rr.losspct,
04963                iaxs[x]->remote_rr.dropped,
04964                iaxs[x]->remote_rr.ooo,
04965                iaxs[x]->remote_rr.packets/1000
04966                );
04967          numchans++;
04968       }
04969       ast_mutex_unlock(&iaxsl[x]);
04970    }
04971    return numchans;
04972 }

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

References chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_channel_free(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_string_field_set, ast_strlen_zero(), chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, chan_iax2_pvt::callno, CALLNO_TO_PTR, chan_iax2_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, iax2_tech, iaxs, iaxsl, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), chan_iax2_pvt::peeradsicpe, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, chan_iax2_pvt::vars, and ast_channel::writeformat.

Referenced by iax2_request(), and socket_process().

03775 {
03776    struct ast_channel *tmp;
03777    struct chan_iax2_pvt *i;
03778    struct ast_variable *v = NULL;
03779 
03780    if (!(i = iaxs[callno])) {
03781       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03782       return NULL;
03783    }
03784 
03785    /* Don't hold call lock */
03786    ast_mutex_unlock(&iaxsl[callno]);
03787    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);
03788    ast_mutex_lock(&iaxsl[callno]);
03789    if (i != iaxs[callno]) {
03790       if (tmp) {
03791          /* unlock and relock iaxsl[callno] to preserve locking order */
03792          ast_mutex_unlock(&iaxsl[callno]);
03793          ast_channel_free(tmp);
03794          ast_mutex_lock(&iaxsl[callno]);
03795       }
03796       return NULL;
03797    }
03798 
03799    if (!tmp)
03800       return NULL;
03801    tmp->tech = &iax2_tech;
03802    /* We can support any format by default, until we get restricted */
03803    tmp->nativeformats = capability;
03804    tmp->readformat = ast_best_codec(capability);
03805    tmp->writeformat = ast_best_codec(capability);
03806    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03807 
03808    /* Don't use ast_set_callerid() here because it will
03809     * generate a NewCallerID event before the NewChannel event */
03810    if (!ast_strlen_zero(i->ani))
03811       tmp->cid.cid_ani = ast_strdup(i->ani);
03812    else
03813       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03814    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03815    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03816    tmp->cid.cid_pres = i->calling_pres;
03817    tmp->cid.cid_ton = i->calling_ton;
03818    tmp->cid.cid_tns = i->calling_tns;
03819    if (!ast_strlen_zero(i->language))
03820       ast_string_field_set(tmp, language, i->language);
03821    if (!ast_strlen_zero(i->accountcode))
03822       ast_string_field_set(tmp, accountcode, i->accountcode);
03823    if (i->amaflags)
03824       tmp->amaflags = i->amaflags;
03825    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03826    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03827    if (i->adsi)
03828       tmp->adsicpe = i->peeradsicpe;
03829    else
03830       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03831    i->owner = tmp;
03832    i->capability = capability;
03833 
03834    for (v = i->vars ; v ; v = v->next)
03835       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03836 
03837    if (state != AST_STATE_DOWN) {
03838       if (ast_pbx_start(tmp)) {
03839          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03840          ast_hangup(tmp);
03841          i->owner = NULL;
03842          return NULL;
03843       }
03844    }
03845 
03846    ast_module_ref(ast_module_info->self);
03847    
03848    return tmp;
03849 }

static AST_LIST_HEAD_STATIC ( dynamic_list  ,
iax2_thread   
) [static]

static AST_LIST_HEAD_STATIC ( active_list  ,
iax2_thread   
) [static]

static AST_LIST_HEAD_STATIC ( idle_list  ,
iax2_thread   
) [static]

static AST_LIST_HEAD_STATIC ( registrations  ,
iax2_registry   
) [static]

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
"Inter Asterisk eXchange (Ver 2)"  ,
load = load_module,
unload = unload_module,
reload = reload 
)

AST_MUTEX_DEFINE_STATIC ( dpcache_lock   ) 

AST_MUTEX_DEFINE_STATIC ( tpeerlock   ) 

AST_MUTEX_DEFINE_STATIC ( sched_lock   ) 

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

Definition at line 2270 of file chan_iax2.c.

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02271 {
02272 #ifdef SCHED_MULTITHREADED
02273    if (schedule_action(__attempt_transmit, data))
02274 #endif      
02275       __attempt_transmit(data);
02276    return 0;
02277 }

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

Definition at line 6430 of file chan_iax2.c.

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

Referenced by socket_process().

06431 {
06432    /* Schedule sending the authentication failure in one second, to prevent
06433       guessing */
06434    if (iaxs[callno]) {
06435       iaxs[callno]->authfail = failcode;
06436       if (delayreject) {
06437          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06438          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06439       } else
06440          auth_reject((void *)(long)callno);
06441    }
06442    return 0;
06443 }

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

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

06417 {
06418    int callno = (int)(long)(data);
06419    ast_mutex_lock(&iaxsl[callno]);
06420    if (iaxs[callno])
06421       iaxs[callno]->authid = -1;
06422    ast_mutex_unlock(&iaxsl[callno]);
06423 #ifdef SCHED_MULTITHREADED
06424    if (schedule_action(__auth_reject, data))
06425 #endif      
06426       __auth_reject(data);
06427    return 0;
06428 }

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

05647 {
05648    int res = -1;
05649    int x;
05650    if (!ast_strlen_zero(keyn)) {
05651       if (!(authmethods & IAX_AUTH_RSA)) {
05652          if (ast_strlen_zero(secret)) 
05653             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));
05654       } else if (ast_strlen_zero(challenge)) {
05655          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05656       } else {
05657          char sig[256];
05658          struct ast_key *key;
05659          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05660          if (!key) {
05661             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05662          } else {
05663             if (ast_sign(key, (char*)challenge, sig)) {
05664                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05665                res = -1;
05666             } else {
05667                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05668                res = 0;
05669             }
05670          }
05671       }
05672    } 
05673    /* Fall back */
05674    if (res && !ast_strlen_zero(secret)) {
05675       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05676          struct MD5Context md5;
05677          unsigned char digest[16];
05678          char digres[128];
05679          MD5Init(&md5);
05680          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05681          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05682          MD5Final(digest, &md5);
05683          /* If they support md5, authenticate with it.  */
05684          for (x=0;x<16;x++)
05685             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05686          if (ecx && dcx)
05687             build_enc_keys(digest, ecx, dcx);
05688          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05689          res = 0;
05690       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05691          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05692          res = 0;
05693       } else
05694          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05695    }
05696    return res;
05697 }

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

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

Definition at line 5703 of file chan_iax2.c.

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

Referenced by socket_process().

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

static int authenticate_request ( int  call_num  )  [static]

Precondition:
iaxsl[call_num] is locked
Note:
Since this function calls send_command_final(), the pvt struct for the given call number may disappear while executing this function.

Definition at line 5381 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 5434 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 3163 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03164 {
03165 #ifdef SCHED_MULTITHREADED
03166    if (schedule_action(__auto_congest, data))
03167 #endif      
03168       __auto_congest(data);
03169    return 0;
03170 }

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

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

06461 {
06462    int callno = (int)(long)(data);
06463    ast_mutex_lock(&iaxsl[callno]);
06464    if (iaxs[callno]) {
06465       iaxs[callno]->autoid = -1;
06466    }
06467    ast_mutex_unlock(&iaxsl[callno]);
06468 #ifdef SCHED_MULTITHREADED
06469    if (schedule_action(__auto_hangup, data))
06470 #endif      
06471       __auto_hangup(data);
06472    return 0;
06473 }

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

Definition at line 9202 of file chan_iax2.c.

References ast_calloc.

Referenced by build_user().

09203 {
09204    struct iax2_context *con;
09205 
09206    if ((con = ast_calloc(1, sizeof(*con))))
09207       ast_copy_string(con->context, context, sizeof(con->context));
09208    
09209    return con;
09210 }

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

Definition at line 4156 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

04157 {
04158    aes_encrypt_key128(digest, ecx);
04159    aes_decrypt_key128(digest, dcx);
04160 }

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

References ao2_alloc(), ao2_find(), ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), AST_SCHED_DEL, ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), cid_name, cid_num, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, get_auth_methods(), get_encrypt_methods(), globalflags, iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, prefs, S_OR, sched, secret, unlink_peer(), and ast_variable::value.

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

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

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

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

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

Definition at line 10298 of file chan_iax2.c.

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

Referenced by find_cache().

10299 {
10300    struct sockaddr_in sin;
10301    int x;
10302    int callno;
10303    struct iax_ie_data ied;
10304    struct create_addr_info cai;
10305    struct parsed_dial_string pds;
10306    char *tmpstr;
10307 
10308    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
10309       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10310          look up entries for a single context */
10311       if (!ast_mutex_trylock(&iaxsl[x])) {
10312          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10313             return x;
10314          ast_mutex_unlock(&iaxsl[x]);
10315       }
10316    }
10317 
10318    /* No match found, we need to create a new one */
10319 
10320    memset(&cai, 0, sizeof(cai));
10321    memset(&ied, 0, sizeof(ied));
10322    memset(&pds, 0, sizeof(pds));
10323 
10324    tmpstr = ast_strdupa(data);
10325    parse_dial_string(tmpstr, &pds);
10326 
10327    if (ast_strlen_zero(pds.peer)) {
10328       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
10329       return -1;
10330    }
10331 
10332    /* Populate our address from the given */
10333    if (create_addr(pds.peer, NULL, &sin, &cai))
10334       return -1;
10335 
10336    if (option_debug)
10337       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10338          pds.peer, pds.username, pds.password, pds.context);
10339 
10340    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10341    if (callno < 1) {
10342       ast_log(LOG_WARNING, "Unable to create call\n");
10343       return -1;
10344    }
10345 
10346    ast_string_field_set(iaxs[callno], dproot, data);
10347    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10348 
10349    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10350    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10351    /* the string format is slightly different from a standard dial string,
10352       because the context appears in the 'exten' position
10353    */
10354    if (pds.exten)
10355       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10356    if (pds.username)
10357       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10358    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10359    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10360    /* Keep password handy */
10361    if (pds.password)
10362       ast_string_field_set(iaxs[callno], secret, pds.password);
10363    if (pds.key)
10364       ast_string_field_set(iaxs[callno], outkey, pds.key);
10365    /* Start the call going */
10366    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10367 
10368    return callno;
10369 }

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

Definition at line 4024 of file chan_iax2.c.

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

04025 {
04026    /* Returns where in "receive time" we are.  That is, how many ms
04027       since we received (or would have received) the frame with timestamp 0 */
04028    int ms;
04029 #ifdef IAXTESTS
04030    int jit;
04031 #endif /* IAXTESTS */
04032    /* Setup rxcore if necessary */
04033    if (ast_tvzero(p->rxcore)) {
04034       p->rxcore = ast_tvnow();
04035       if (option_debug && iaxdebug)
04036          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
04037                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
04038       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
04039 #if 1
04040       if (option_debug && iaxdebug)
04041          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
04042                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
04043 #endif
04044    }
04045 
04046    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
04047 #ifdef IAXTESTS
04048    if (test_jit) {
04049       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
04050          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
04051          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
04052             jit = -jit;
04053          ms += jit;
04054       }
04055    }
04056    if (test_late) {
04057       ms += test_late;
04058       test_late = 0;
04059    }
04060 #endif /* IAXTESTS */
04061    return ms;
04062 }

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

Definition at line 3895 of file chan_iax2.c.

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

Referenced by iax2_send(), and socket_process().

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

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

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

03852 {
03853    unsigned long int mssincetx; /* unsigned to handle overflows */
03854    long int ms, pred;
03855 
03856    tpeer->trunkact = *tv;
03857    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03858    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03859       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03860       tpeer->txtrunktime = *tv;
03861       tpeer->lastsent = 999999;
03862    }
03863    /* Update last transmit time now */
03864    tpeer->lasttxtime = *tv;
03865    
03866    /* Calculate ms offset */
03867    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03868    /* Predict from last value */
03869    pred = tpeer->lastsent + sampms;
03870    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03871       ms = pred;
03872    
03873    /* We never send the same timestamp twice, so fudge a little if we must */
03874    if (ms == tpeer->lastsent)
03875       ms = tpeer->lastsent + 1;
03876    tpeer->lastsent = ms;
03877    return ms;
03878 }

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

Definition at line 5135 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 6818 of file chan_iax2.c.

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

Referenced by socket_process().

06819 {
06820    unsigned int ourver;
06821    char rsi[80];
06822    snprintf(rsi, sizeof(rsi), "si-%s", si);
06823    if (iax_provision_version(&ourver, rsi, 1))
06824       return 0;
06825    if (option_debug)
06826       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06827    if (ourver != ver) 
06828       iax2_provision(sin, sockfd, NULL, rsi, 1);
06829    return 0;
06830 }

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

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

Referenced by peer_set_srcaddr().

09229 {
09230    int sd;
09231    int res;
09232    
09233    sd = socket(AF_INET, SOCK_DGRAM, 0);
09234    if (sd < 0) {
09235       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
09236       return -1;
09237    }
09238 
09239    res = bind(sd, sa, salen);
09240    if (res < 0) {
09241       if (option_debug)
09242          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09243       close(sd);
09244       return 1;
09245    }
09246 
09247    close(sd);
09248    return 0;
09249 }

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

Definition at line 5822 of file chan_iax2.c.

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

Referenced by socket_process().

05823 {
05824    char exten[256] = "";
05825    int status = CACHE_FLAG_UNKNOWN;
05826    int expiry = iaxdefaultdpcache;
05827    int x;
05828    int matchmore = 0;
05829    struct iax2_dpcache *dp, *prev;
05830    
05831    if (ies->called_number)
05832       ast_copy_string(exten, ies->called_number, sizeof(exten));
05833 
05834    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05835       status = CACHE_FLAG_EXISTS;
05836    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05837       status = CACHE_FLAG_CANEXIST;
05838    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05839       status = CACHE_FLAG_NONEXISTENT;
05840 
05841    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05842       /* Don't really do anything with this */
05843    }
05844    if (ies->refresh)
05845       expiry = ies->refresh;
05846    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05847       matchmore = CACHE_FLAG_MATCHMORE;
05848    ast_mutex_lock(&dpcache_lock);
05849    prev = NULL;
05850    dp = pvt->dpentries;
05851    while(dp) {
05852       if (!strcmp(dp->exten, exten)) {
05853          /* Let them go */
05854          if (prev)
05855             prev->peer = dp->peer;
05856          else
05857             pvt->dpentries = dp->peer;
05858          dp->peer = NULL;
05859          dp->callno = 0;
05860          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05861          if (dp->flags & CACHE_FLAG_PENDING) {
05862             dp->flags &= ~CACHE_FLAG_PENDING;
05863             dp->flags |= status;
05864             dp->flags |= matchmore;
05865          }
05866          /* Wake up waiters */
05867          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05868             if (dp->waiters[x] > -1)
05869                write(dp->waiters[x], "asdf", 4);
05870       }
05871       prev = dp;
05872       dp = dp->peer;
05873    }
05874    ast_mutex_unlock(&dpcache_lock);
05875    return 0;
05876 }

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

Definition at line 2432 of file chan_iax2.c.

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

02433 {
02434    int which = 0;
02435    struct iax2_peer *peer;
02436    char *res = NULL;
02437    int wordlen = strlen(word);
02438    struct ao2_iterator i;
02439 
02440    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02441    if (pos != 3)
02442       return NULL;
02443 
02444    i = ao2_iterator_init(peers, 0);
02445    while ((peer = ao2_iterator_next(&i))) {
02446       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02447          res = ast_strdup(peer->name);
02448          peer_unref(peer);
02449          break;
02450       }
02451       peer_unref(peer);
02452    }
02453 
02454    return res;
02455 }

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

Definition at line 5878 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, remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, store_by_peercallno(), chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, TRANSFER_NONE, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, chan_iax2_pvt::videoformat, and chan_iax2_pvt::voiceformat.

Referenced by socket_process().

05879 {
05880    int peercallno = 0;
05881    struct chan_iax2_pvt *pvt = iaxs[callno];
05882    struct iax_frame *cur;
05883    jb_frame frame;
05884 
05885    if (ies->callno)
05886       peercallno = ies->callno;
05887 
05888    if (peercallno < 1) {
05889       ast_log(LOG_WARNING, "Invalid transfer request\n");
05890       return -1;
05891    }
05892    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05893    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05894    /* Reset sequence numbers */
05895    pvt->oseqno = 0;
05896    pvt->rseqno = 0;
05897    pvt->iseqno = 0;
05898    pvt->aseqno = 0;
05899 
05900    if (pvt->peercallno) {
05901       remove_by_peercallno(pvt);
05902    }
05903    pvt->peercallno = peercallno;
05904    store_by_peercallno(pvt);
05905 
05906    pvt->transferring = TRANSFER_NONE;
05907    pvt->svoiceformat = -1;
05908    pvt->voiceformat = 0;
05909    pvt->svideoformat = -1;
05910    pvt->videoformat = 0;
05911    pvt->transfercallno = -1;
05912    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05913    memset(&pvt->offset, 0, sizeof(pvt->offset));
05914    /* reset jitterbuffer */
05915    while(jb_getall(pvt->jb,&frame) == JB_OK)
05916       iax2_frame_free(frame.data);
05917    jb_reset(pvt->jb);
05918    pvt->lag = 0;
05919    pvt->last = 0;
05920    pvt->lastsent = 0;
05921    pvt->nextpred = 0;
05922    pvt->pingtime = DEFAULT_RETRY_TIME;
05923    AST_LIST_LOCK(&iaxq.queue);
05924    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05925       /* We must cancel any packets that would have been transmitted
05926          because now we're talking to someone new.  It's okay, they
05927          were transmitted to someone that didn't care anyway. */
05928       if (callno == cur->callno) 
05929          cur->retries = -1;
05930    }
05931    AST_LIST_UNLOCK(&iaxq.queue);
05932    return 0; 
05933 }

static unsigned char compress_subclass ( int  subclass  )  [static]

Definition at line 1072 of file chan_iax2.c.

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

Referenced by iax2_send(), raw_hangup(), and send_apathetic_reply().

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

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

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

06833 {
06834    jb_info stats;
06835    jb_getinfo(pvt->jb, &stats);
06836    
06837    memset(iep, 0, sizeof(*iep));
06838 
06839    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06840    if(stats.frames_in == 0) stats.frames_in = 1;
06841    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06842    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06843    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06844    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06845    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06846 }

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

Definition at line 3055 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_codec_pref_prepend(), ast_copy_flags, ast_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, create_addr_info::outkey, peer_unref(), create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.

03056 {
03057    struct ast_hostent ahp;
03058    struct hostent *hp;
03059    struct iax2_peer *peer;
03060    int res = -1;
03061    struct ast_codec_pref ourprefs;
03062 
03063    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
03064    cai->sockfd = defaultsockfd;
03065    cai->maxtime = 0;
03066    sin->sin_family = AF_INET;
03067 
03068    if (!(peer = find_peer(peername, 1))) {
03069       cai->found = 0;
03070 
03071       hp = ast_gethostbyname(peername, &ahp);
03072       if (hp) {
03073          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
03074          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
03075          /* use global iax prefs for unknown peer/user */
03076          /* But move the calling channel's native codec to the top of the preference list */
03077          memcpy(&ourprefs, &prefs, sizeof(ourprefs));
03078          if (c)
03079             ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03080          ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03081          return 0;
03082       } else {
03083          ast_log(LOG_WARNING, "No such host: %s\n", peername);
03084          return -1;
03085       }
03086    }
03087 
03088    cai->found = 1;
03089    
03090    /* if the peer has no address (current or default), return failure */
03091    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr))
03092       goto return_unref;
03093 
03094    /* if the peer is being monitored and is currently unreachable, return failure */
03095    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
03096       goto return_unref;
03097 
03098    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
03099    cai->maxtime = peer->maxms;
03100    cai->capability = peer->capability;
03101    cai->encmethods = peer->encmethods;
03102    cai->sockfd = peer->sockfd;
03103    cai->adsi = peer->adsi;
03104    memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
03105    /* Move the calling channel's native codec to the top of the preference list */
03106    if (c) {
03107       ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
03108       ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03109    }
03110    ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03111    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
03112    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
03113    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
03114    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
03115    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
03116    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
03117    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
03118    if (ast_strlen_zero(peer->dbsecret)) {
03119       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
03120    } else {
03121       char *family;
03122       char *key = NULL;
03123 
03124       family = ast_strdupa(peer->dbsecret);
03125       key = strchr(family, '/');
03126       if (key)
03127          *key++ = '\0';
03128       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
03129          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
03130          goto return_unref;
03131       }
03132    }
03133 
03134    if (peer->addr.sin_addr.s_addr) {
03135       sin->sin_addr = peer->addr.sin_addr;
03136       sin->sin_port = peer->addr.sin_port;
03137    } else {
03138       sin->sin_addr = peer->defaddr.sin_addr;
03139       sin->sin_port = peer->defaddr.sin_port;
03140    }
03141 
03142    res = 0;
03143 
03144 return_unref:
03145    peer_unref(peer);
03146 
03147    return res;
03148 }

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

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

04211 {
04212    int padding;
04213    unsigned char *workspace;
04214 
04215    workspace = alloca(*datalen);
04216    memset(f, 0, sizeof(*f));
04217    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04218       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04219       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04220          return -1;
04221       /* Decrypt */
04222       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04223 
04224       padding = 16 + (workspace[15] & 0xf);
04225       if (option_debug && iaxdebug)
04226          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04227       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04228          return -1;
04229 
04230       *datalen -= padding;
04231       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04232       f->frametype = fh->type;
04233       if (f->frametype == AST_FRAME_VIDEO) {
04234          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04235       } else {
04236          f->subclass = uncompress_subclass(fh->csub);
04237       }
04238    } else {
04239       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04240       if (option_debug && iaxdebug)
04241          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04242       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04243          return -1;
04244       /* Decrypt */
04245       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04246       padding = 16 + (workspace[15] & 0x0f);
04247       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04248          return -1;
04249       *datalen -= padding;
04250       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04251    }
04252    return 0;
04253 }

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

Definition at line 4296 of file chan_iax2.c.

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

Referenced by socket_process().

04297 {
04298    int res=-1;
04299    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04300       /* Search for possible keys, given secrets */
04301       struct MD5Context md5;
04302       unsigned char digest[16];
04303       char *tmppw, *stringp;
04304       
04305       tmppw = ast_strdupa(iaxs[callno]->secret);
04306       stringp = tmppw;
04307       while ((tmppw = strsep(&stringp, ";"))) {
04308          MD5Init(&md5);
04309          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04310          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04311          MD5Final(digest, &md5);
04312          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04313          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04314          if (!res) {
04315             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04316             break;
04317          }
04318       }
04319    } else 
04320       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04321    return res;
04322 }

static void defer_full_frame ( struct iax2_thread from_here,
struct iax2_thread to_here 
) [static]

Queue the last read full frame for processing by a certain thread.

If there are already any full frames queued, they are sorted by sequence number.

Definition at line 6894 of file chan_iax2.c.

References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), and ast_iax2_full_hdr::oseqno.

Referenced by socket_read().

06895 {
06896    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06897    struct ast_iax2_full_hdr *fh, *cur_fh;
06898 
06899    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06900       return;
06901 
06902    pkt_buf->len = from_here->buf_len;
06903    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06904 
06905    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06906    ast_mutex_lock(&to_here->lock);
06907    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06908       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06909       if (fh->oseqno < cur_fh->oseqno) {
06910          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06911          break;
06912       }
06913    }
06914    AST_LIST_TRAVERSE_SAFE_END
06915 
06916    if (!cur_pkt_buf)
06917       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06918    
06919    ast_mutex_unlock(&to_here->lock);
06920 }

static void delete_users ( void   )  [static]

Definition at line 9812 of file chan_iax2.c.

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

09813 {
09814    struct iax2_registry *reg;
09815 
09816    ao2_callback(users, 0, user_delme_cb, NULL);
09817 
09818    AST_LIST_LOCK(&registrations);
09819    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09820       ast_sched_del(sched, reg->expire);
09821       if (reg->callno) {
09822          int callno = reg->callno;
09823          ast_mutex_lock(&iaxsl[callno]);
09824          if (iaxs[callno]) {
09825             iaxs[callno]->reg = NULL;
09826             iax2_destroy(callno);
09827          }
09828          ast_mutex_unlock(&iaxsl[callno]);
09829       }
09830       if (reg->dnsmgr)
09831          ast_dnsmgr_release(reg->dnsmgr);
09832       free(reg);
09833    }
09834    AST_LIST_UNLOCK(&registrations);
09835 
09836    ao2_callback(peers, 0, peer_delme_cb, NULL);
09837 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1783 of file chan_iax2.c.

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

Referenced by reload_firmware().

01784 {
01785    /* Close firmware */
01786    if (cur->fwh) {
01787       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01788    }
01789    close(cur->fd);
01790    free(cur);
01791 }

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

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

06667 {
06668    unsigned short dpstatus = 0;
06669    struct iax_ie_data ied1;
06670    int mm;
06671 
06672    memset(&ied1, 0, sizeof(ied1));
06673    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06674    /* Must be started */
06675    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06676       dpstatus = IAX_DPSTATUS_EXISTS;
06677    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06678       dpstatus = IAX_DPSTATUS_CANEXIST;
06679    } else {
06680       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06681    }
06682    if (ast_ignore_pattern(context, callednum))
06683       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06684    if (mm)
06685       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06686    if (!skiplock)
06687       ast_mutex_lock(&iaxsl[callno]);
06688    if (iaxs[callno]) {
06689       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06690       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06691       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06692       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06693    }
06694    if (!skiplock)
06695       ast_mutex_unlock(&iaxsl[callno]);
06696 }

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

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

06699 {
06700    /* Look up for dpreq */
06701    struct dpreq_data *dpr = data;
06702    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06703    if (dpr->callerid)
06704       free(dpr->callerid);
06705    free(dpr);
06706    return NULL;
06707 }

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

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

04256 {
04257    int padding;
04258    unsigned char *workspace;
04259    workspace = alloca(*datalen + 32);
04260    if (!workspace)
04261       return -1;
04262    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04263       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04264       if (option_debug && iaxdebug)
04265          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04266       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04267       padding = 16 + (padding & 0xf);
04268       memcpy(workspace, poo, padding);
04269       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04270       workspace[15] &= 0xf0;
04271       workspace[15] |= (padding & 0xf);
04272       if (option_debug && iaxdebug)
04273          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]);
04274       *datalen += padding;
04275       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04276       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04277          memcpy(poo, workspace + *datalen - 32, 32);
04278    } else {
04279       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04280       if (option_debug && iaxdebug)
04281          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04282       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04283       padding = 16 + (padding & 0xf);
04284       memcpy(workspace, poo, padding);
04285       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04286       workspace[15] &= 0xf0;
04287       workspace[15] |= (padding & 0x0f);
04288       *datalen += padding;
04289       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04290       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04291          memcpy(poo, workspace + *datalen - 32, 32);
04292    }
04293    return 0;
04294 }

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

Definition at line 6115 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

06116 {
06117 #ifdef SCHED_MULTITHREADED
06118    if (schedule_action(__expire_registry, data))
06119 #endif      
06120       __expire_registry(data);
06121    return 0;
06122 }

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

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

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

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

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

Definition at line 1683 of file chan_iax2.c.

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

01683                                                                                                                                     {
01684 
01685    return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame);
01686 }

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

Definition at line 1688 of file chan_iax2.c.

References __find_callno().

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

01688                                                                                                                                            {
01689 
01690    return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
01691 }

static struct iax2_thread* find_idle_thread ( void   )  [static]

Definition at line 907 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, iaxdynamicthreadnum, iaxmaxthreadcount, and thread.

Referenced by __schedule_action(), and socket_read().

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

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

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

Definition at line 1150 of file chan_iax2.c.

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

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

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

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

04065 {
04066    struct iax2_trunk_peer *tpeer;
04067    
04068    /* Finds and locks trunk peer */
04069    ast_mutex_lock(&tpeerlock);
04070    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
04071       /* We don't lock here because tpeer->addr *never* changes */
04072       if (!inaddrcmp(&tpeer->addr, sin)) {
04073          ast_mutex_lock(&tpeer->lock);
04074          break;
04075       }
04076    }
04077    if (!tpeer) {
04078       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
04079          ast_mutex_init(&tpeer->lock);
04080          tpeer->lastsent = 9999;
04081          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
04082          tpeer->trunkact = ast_tvnow();
04083          ast_mutex_lock(&tpeer->lock);
04084          tpeer->next = tpeers;
04085          tpeer->sockfd = fd;
04086          tpeers = tpeer;
04087 #ifdef SO_NO_CHECK
04088          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
04089 #endif
04090          if (option_debug)
04091             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
04092       }
04093    }
04094    ast_mutex_unlock(&tpeerlock);
04095    return tpeer;
04096 }

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

Definition at line 3880 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03881 {
03882    long ms; /* NOT unsigned */
03883    if (ast_tvzero(iaxs[callno]->rxcore)) {
03884       /* Initialize rxcore time if appropriate */
03885       gettimeofday(&iaxs[callno]->rxcore, NULL);
03886       /* Round to nearest 20ms so traces look pretty */
03887       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03888    }
03889    /* Calculate difference between trunk and channel */
03890    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03891    /* Return as the sum of trunk time and the difference between trunk and real time */
03892    return ms + ts;
03893 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8988 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08989 {
08990    struct iax2_context *conl;
08991    while(con) {
08992       conl = con;
08993       con = con->next;
08994       free(conl);
08995    }
08996 }

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

Definition at line 10640 of file chan_iax2.c.

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

10641 {
10642    struct iax2_peer *peer;
10643    char *peername, *colname;
10644 
10645    peername = ast_strdupa(data);
10646 
10647    /* if our channel, return the IP address of the endpoint of current channel */
10648    if (!strcmp(peername,"CURRENTCHANNEL")) {
10649            unsigned short callno;
10650       if (chan->tech != &iax2_tech)
10651          return -1;
10652       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10653       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10654       return 0;
10655    }
10656 
10657    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10658       *colname++ = '\0';
10659    else if ((colname = strchr(peername, '|')))
10660       *colname++ = '\0';
10661    else
10662       colname = "ip";
10663 
10664    if (!(peer = find_peer(peername, 1)))
10665       return -1;
10666 
10667    if (!strcasecmp(colname, "ip")) {
10668       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10669    } else  if (!strcasecmp(colname, "status")) {
10670       peer_status(peer, buf, len); 
10671    } else  if (!strcasecmp(colname, "mailbox")) {
10672       ast_copy_string(buf, peer->mailbox, len);
10673    } else  if (!strcasecmp(colname, "context")) {
10674       ast_copy_string(buf, peer->context, len);
10675    } else  if (!strcasecmp(colname, "expire")) {
10676       snprintf(buf, len, "%d", peer->expire);
10677    } else  if (!strcasecmp(colname, "dynamic")) {
10678       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10679    } else  if (!strcasecmp(colname, "callerid_name")) {
10680       ast_copy_string(buf, peer->cid_name, len);
10681    } else  if (!strcasecmp(colname, "callerid_num")) {
10682       ast_copy_string(buf, peer->cid_num, len);
10683    } else  if (!strcasecmp(colname, "codecs")) {
10684       ast_getformatname_multiple(buf, len -1, peer->capability);
10685    } else  if (!strncasecmp(colname, "codec[", 6)) {
10686       char *codecnum, *ptr;
10687       int index = 0, codec = 0;
10688       
10689       codecnum = strchr(colname, '[');
10690       *codecnum = '\0';
10691       codecnum++;
10692       if ((ptr = strchr(codecnum, ']'))) {
10693          *ptr = '\0';
10694       }
10695       index = atoi(codecnum);
10696       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10697          ast_copy_string(buf, ast_getformatname(codec), len);
10698       }
10699    }
10700 
10701    peer_unref(peer);
10702 
10703    return 0;
10704 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9212 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09213 {
09214    int methods = 0;
09215    if (strstr(value, "rsa"))
09216       methods |= IAX_AUTH_RSA;
09217    if (strstr(value, "md5"))
09218       methods |= IAX_AUTH_MD5;
09219    if (strstr(value, "plaintext"))
09220       methods |= IAX_AUTH_PLAINTEXT;
09221    return methods;
09222 }

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

Definition at line 1027 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

01028 {
01029    int e;
01030    if (!strcasecmp(s, "aes128"))
01031       e = IAX_ENCRYPT_AES128;
01032    else if (ast_true(s))
01033       e = IAX_ENCRYPT_AES128;
01034    else
01035       e = 0;
01036    return e;
01037 }

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

Definition at line 2669 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02670 {
02671 #ifdef SCHED_MULTITHREADED
02672    if (schedule_action(__get_from_jb, data))
02673 #endif      
02674       __get_from_jb(data);
02675    return 0;
02676 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6864 of file chan_iax2.c.

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

06865 {
06866    struct iax2_pkt_buf *pkt_buf;
06867 
06868    ast_mutex_lock(&thread->lock);
06869 
06870    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06871       ast_mutex_unlock(&thread->lock);
06872 
06873       thread->buf = pkt_buf->buf;
06874       thread->buf_len = pkt_buf->len;
06875       thread->buf_size = pkt_buf->len + 1;
06876       
06877       socket_process(thread);
06878 
06879       thread->buf = NULL;
06880       ast_free(pkt_buf);
06881 
06882       ast_mutex_lock(&thread->lock);
06883    }
06884 
06885    ast_mutex_unlock(&thread->lock);
06886 }

static int handle_error ( void   )  [static]

Definition at line 2071 of file chan_iax2.c.

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

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

02072 {
02073    /* XXX Ideally we should figure out why an error occured and then abort those
02074       rather than continuing to try.  Unfortunately, the published interface does
02075       not seem to work XXX */
02076 #if 0
02077    struct sockaddr_in *sin;
02078    int res;
02079    struct msghdr m;
02080    struct sock_extended_err e;
02081    m.msg_name = NULL;
02082    m.msg_namelen = 0;
02083    m.msg_iov = NULL;
02084    m.msg_control = &e;
02085    m.msg_controllen = sizeof(e);
02086    m.msg_flags = 0;
02087    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
02088    if (res < 0)
02089       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
02090    else {
02091       if (m.msg_controllen) {
02092          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
02093          if (sin) 
02094             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
02095          else
02096             ast_log(LOG_WARNING, "No address detected??\n");
02097       } else {
02098          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
02099       }
02100    }
02101 #endif
02102    return 0;
02103 }

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

Acknowledgment received for OUR registration.

Definition at line 5936 of file chan_iax2.c.

References iax2_registry::addr, ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_add(), 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().

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

static int iax2_answer ( struct ast_channel c  )  [static]

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

03679 {
03680    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03681    if (option_debug)
03682       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03683    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03684 }

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

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

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

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

Definition at line 3269 of file chan_iax2.c.

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

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

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

10543 {
10544    int res = 0;
10545    struct iax2_dpcache *dp;
10546 #if 0
10547    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10548 #endif
10549    if ((priority != 1) && (priority != 2))
10550       return 0;
10551    ast_mutex_lock(&dpcache_lock);
10552    dp = find_cache(chan, data, context, exten, priority);
10553    if (dp) {
10554       if (dp->flags & CACHE_FLAG_CANEXIST)
10555          res= 1;
10556    }
10557    ast_mutex_unlock(&dpcache_lock);
10558    if (!dp) {
10559       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10560    }
10561    return res;
10562 }

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

Definition at line 3172 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03173 {
03174    time_t t;
03175    struct tm tm;
03176    unsigned int tmp;
03177    time(&t);
03178    if (!ast_strlen_zero(tz))
03179       ast_localtime(&t, &tm, tz);
03180    else
03181       ast_localtime(&t, &tm, NULL);
03182    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03183    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03184    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03185    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03186    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03187    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03188    return tmp;
03189 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1290 of file chan_iax2.c.

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

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

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1220 of file chan_iax2.c.

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

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

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

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 10729 of file chan_iax2.c.

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

10730 {
10731    struct parsed_dial_string pds;
10732    char *tmp = ast_strdupa(data);
10733    struct iax2_peer *p;
10734    int res = AST_DEVICE_INVALID;
10735 
10736    memset(&pds, 0, sizeof(pds));
10737    parse_dial_string(tmp, &pds);
10738 
10739    if (ast_strlen_zero(pds.peer)) {
10740       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10741       return res;
10742    }
10743    
10744    if (option_debug > 2)
10745       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10746 
10747    /* SLD: FIXME: second call to find_peer during registration */
10748    if (!(p = find_peer(pds.peer, 1)))
10749       return res;
10750 
10751    res = AST_DEVICE_UNAVAILABLE;
10752    if (option_debug > 2) 
10753       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10754          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10755    
10756    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10757        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10758       /* Peer is registered, or have default IP address
10759          and a valid registration */
10760       if (p->historicms == 0 || p->historicms <= p->maxms)
10761          /* let the core figure out whether it is in use or not */
10762          res = AST_DEVICE_UNKNOWN;  
10763    }
10764 
10765    peer_unref(p);
10766 
10767    return res;
10768 }

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

Definition at line 2788 of file chan_iax2.c.

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

02789 {
02790    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02791 }

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

Definition at line 2793 of file chan_iax2.c.

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

02794 {
02795    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02796 }

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

Definition at line 4986 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04987 {
04988    if (argc < 2 || argc > 3)
04989       return RESULT_SHOWUSAGE;
04990    iaxdebug = 1;
04991    ast_cli(fd, "IAX2 Debugging Enabled\n");
04992    return RESULT_SUCCESS;
04993 }

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

Definition at line 5004 of file chan_iax2.c.

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

05005 {
05006    if (argc < 3 || argc > 4)
05007       return RESULT_SHOWUSAGE;
05008    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
05009    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
05010    return RESULT_SUCCESS;
05011 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8706 of file chan_iax2.c.

References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_add(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_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().

08707 {
08708    struct iax_ie_data ied;
08709    if (option_debug && iaxdebug)
08710       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08711 
08712    if (reg->dnsmgr && 
08713        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08714       /* Maybe the IP has changed, force DNS refresh */
08715       ast_dnsmgr_refresh(reg->dnsmgr);
08716    }
08717    
08718    /*
08719     * if IP has Changed, free allocated call to create a new one with new IP
08720     * call has the pointer to IP and must be updated to the new one
08721     */
08722    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08723       int callno = reg->callno;
08724       ast_mutex_lock(&iaxsl[callno]);
08725       iax2_destroy(callno);
08726       ast_mutex_unlock(&iaxsl[callno]);
08727       reg->callno = 0;
08728    }
08729    if (!reg->addr.sin_addr.s_addr) {
08730       if (option_debug && iaxdebug)
08731          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08732       /* Setup the next registration attempt */
08733       AST_SCHED_DEL(sched, reg->expire);
08734       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08735       return -1;
08736    }
08737 
08738    if (!reg->callno) {
08739       if (option_debug)
08740          ast_log(LOG_DEBUG, "Allocate call number\n");
08741       reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
08742       if (reg->callno < 1) {
08743          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08744          return -1;
08745       } else if (option_debug)
08746          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08747       iaxs[reg->callno]->reg = reg;
08748       ast_mutex_unlock(&iaxsl[reg->callno]);
08749    }
08750    /* Schedule the next registration attempt */
08751    AST_SCHED_DEL(sched, reg->expire);
08752    /* Setup the next registration a little early */
08753    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08754    /* Send the request */
08755    memset(&ied, 0, sizeof(ied));
08756    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08757    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08758    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08759    reg->regstate = REG_STATE_REGSENT;
08760    return 0;
08761 }

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

Definition at line 5784 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05785 {
05786 #ifdef SCHED_MULTITHREADED
05787    if (schedule_action(__iax2_do_register_s, data))
05788 #endif      
05789       __iax2_do_register_s(data);
05790    return 0;
05791 }

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

Definition at line 4995 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04996 {
04997    if (argc < 3 || argc > 4)
04998       return RESULT_SHOWUSAGE;
04999    iaxtrunkdebug = 1;
05000    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
05001    return RESULT_SUCCESS;
05002 }

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

Definition at line 6475 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

06476 {
06477    struct iax_ie_data ied;
06478    /* Auto-hangup with 30 seconds of inactivity */
06479    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06480    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06481    memset(&ied, 0, sizeof(ied));
06482    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06483    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06484    dp->flags |= CACHE_FLAG_TRANSMITTED;
06485 }

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

10589 {
10590    char odata[256];
10591    char req[256];
10592    char *ncontext;
10593    struct iax2_dpcache *dp;
10594    struct ast_app *dial;
10595 #if 0
10596    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);
10597 #endif
10598    if (priority == 2) {
10599       /* Indicate status, can be overridden in dialplan */
10600       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10601       if (dialstatus) {
10602          dial = pbx_findapp(dialstatus);
10603          if (dial) 
10604             pbx_exec(chan, dial, "");
10605       }
10606       return -1;
10607    } else if (priority != 1)
10608       return -1;
10609    ast_mutex_lock(&dpcache_lock);
10610    dp = find_cache(chan, data, context, exten, priority);
10611    if (dp) {
10612       if (dp->flags & CACHE_FLAG_EXISTS) {
10613          ast_copy_string(odata, data, sizeof(odata));
10614          ncontext = strchr(odata, '/');
10615          if (ncontext) {
10616             *ncontext = '\0';
10617             ncontext++;
10618             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10619          } else {
10620             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10621          }
10622          if (option_verbose > 2)
10623             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10624       } else {
10625          ast_mutex_unlock(&dpcache_lock);
10626          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10627          return -1;
10628       }
10629    }
10630    ast_mutex_unlock(&dpcache_lock);
10631    dial = pbx_findapp("Dial");
10632    if (dial) {
10633       return pbx_exec(chan, dial, req);
10634    } else {
10635       ast_log(LOG_WARNING, "No dial application registered\n");
10636    }
10637    return -1;
10638 }

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

10520 {
10521    struct iax2_dpcache *dp;
10522    int res = 0;
10523 #if 0
10524    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10525 #endif
10526    if ((priority != 1) && (priority != 2))
10527       return 0;
10528    ast_mutex_lock(&dpcache_lock);
10529    dp = find_cache(chan, data, context, exten, priority);
10530    if (dp) {
10531       if (dp->flags & CACHE_FLAG_EXISTS)
10532          res= 1;
10533    }
10534    ast_mutex_unlock(&dpcache_lock);
10535    if (!dp) {
10536       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10537    }
10538    return res;
10539 }

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

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

02816 {
02817    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02818    ast_mutex_lock(&iaxsl[callno]);
02819    if (iaxs[callno])
02820       iaxs[callno]->owner = newchan;
02821    else
02822       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02823    ast_mutex_unlock(&iaxsl[callno]);
02824    return 0;
02825 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1284 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(), pvt_destructor(), and schedule_delivery().

01285 {
01286    AST_SCHED_DEL(sched, fr->retrans);
01287    iax_frame_free(fr);
01288 }

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

Definition at line 1190 of file chan_iax2.c.

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), peer_unref(), peers, and realtime_peer().

Referenced by __find_callno().

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

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

Definition at line 3753 of file chan_iax2.c.

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_TRUNK, peer_unref(), and peers.

Referenced by check_access().

03754 {
03755    struct iax2_peer *peer;
03756    int res = 0;
03757    struct ao2_iterator i;
03758 
03759    i = ao2_iterator_init(peers, 0);
03760    while ((peer = ao2_iterator_next(&i))) {
03761       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03762           (peer->addr.sin_port == sin.sin_port)) {
03763          res = ast_test_flag(peer, IAX_TRUNK);
03764          peer_unref(peer);
03765          break;
03766       }
03767       peer_unref(peer);
03768    }
03769 
03770    return res;
03771 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3416 of file chan_iax2.c.

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

03417 {
03418    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03419    struct iax_ie_data ied;
03420    memset(&ied, 0, sizeof(ied));
03421    ast_mutex_lock(&iaxsl[callno]);
03422    if (callno && iaxs[callno]) {
03423       if (option_debug)
03424          ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
03425       /* Send the hangup unless we have had a transmission error or are already gone */
03426       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03427       if (!iaxs[callno]->error && !ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
03428          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03429          if (!iaxs[callno]) {
03430             ast_mutex_unlock(&iaxsl[callno]);
03431             return 0;
03432          }
03433       }
03434       /* Explicitly predestroy it */
03435       iax2_predestroy(callno);
03436       /* If we were already gone to begin with, destroy us now */
03437       if (iaxs[callno]) {
03438          if (option_debug)
03439             ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03440          iax2_destroy(callno);
03441       }
03442    } else if (c->tech_pvt) {
03443       /* If this call no longer exists, but the channel still
03444        * references it we need to set the channel's tech_pvt to null
03445        * to avoid ast_channel_free() trying to free it.
03446        */
03447       c->tech_pvt = NULL;
03448    }
03449    ast_mutex_unlock(&iaxsl[callno]);
03450    if (option_verbose > 2) 
03451       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03452    return 0;
03453 }

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

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

03687 {
03688    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03689    struct chan_iax2_pvt *pvt;
03690    int res = 0;
03691 
03692    if (option_debug && iaxdebug)
03693       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03694 
03695    ast_mutex_lock(&iaxsl[callno]);
03696    pvt = iaxs[callno];
03697 
03698    if (!pvt->peercallno) {
03699       /* We don't know the remote side's call number, yet.  :( */
03700       int count = 10;
03701       while (count-- && pvt && !pvt->peercallno) {
03702          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
03703          pvt = iaxs[callno];
03704       }
03705       if (!pvt->peercallno) {
03706          res = -1;
03707          goto done;
03708       }
03709    }
03710 
03711    switch (condition) {
03712    case AST_CONTROL_HOLD:
03713       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03714          ast_moh_start(c, data, pvt->mohinterpret);
03715          goto done;
03716       }
03717       break;
03718    case AST_CONTROL_UNHOLD:
03719       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03720          ast_moh_stop(c);
03721          goto done;
03722       }
03723    }
03724 
03725    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03726 
03727 done:
03728    ast_mutex_unlock(&iaxsl[callno]);
03729 
03730    return res;
03731 }

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

10566 {
10567    int res = 0;
10568    struct iax2_dpcache *dp;
10569 #if 0
10570    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10571 #endif
10572    if ((priority != 1) && (priority != 2))
10573       return 0;
10574    ast_mutex_lock(&dpcache_lock);
10575    dp = find_cache(chan, data, context, exten, priority);
10576    if (dp) {
10577       if (dp->flags & CACHE_FLAG_MATCHMORE)
10578          res= 1;
10579    }
10580    ast_mutex_unlock(&dpcache_lock);
10581    if (!dp) {
10582       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10583    }
10584    return res;
10585 }

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

Definition at line 5013 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05014 {
05015    if (argc < 3 || argc > 4)
05016       return RESULT_SHOWUSAGE;
05017    iaxdebug = 0;
05018    ast_cli(fd, "IAX2 Debugging Disabled\n");
05019    return RESULT_SUCCESS;
05020 }

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

Definition at line 5031 of file chan_iax2.c.

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

05032 {
05033    if (argc < 4 || argc > 5)
05034       return RESULT_SHOWUSAGE;
05035    jb_setoutput(jb_error_output, jb_warning_output, NULL);
05036    jb_debug_output("\n");
05037    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
05038    return RESULT_SUCCESS;
05039 }

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

Definition at line 5022 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05023 {
05024    if (argc < 4 || argc > 5)
05025       return RESULT_SHOWUSAGE;
05026    iaxtrunkdebug = 0;
05027    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
05028    return RESULT_SUCCESS;
05029 }

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

Definition at line 8905 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08906 {
08907    struct iax2_peer *peer = (struct iax2_peer *)data;
08908    peer->pokeexpire = -1;
08909 #ifdef SCHED_MULTITHREADED
08910    if (schedule_action(__iax2_poke_noanswer, data))
08911 #endif      
08912       __iax2_poke_noanswer(data);
08913    peer_unref(peer);
08914    return 0;
08915 }

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

Definition at line 8926 of file chan_iax2.c.

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

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

08927 {
08928    int callno;
08929    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
08930       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
08931         immediately after clearing things out */
08932       peer->lastms = 0;
08933       peer->historicms = 0;
08934       peer->pokeexpire = -1;
08935       peer->callno = 0;
08936       return 0;
08937    }
08938 
08939    /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */
08940    if ((callno = peer->callno) > 0) {
08941       ast_log(LOG_NOTICE, "Still have a callno...\n");
08942       ast_mutex_lock(&iaxsl[callno]);
08943       iax2_destroy(callno);
08944       ast_mutex_unlock(&iaxsl[callno]);
08945    }
08946    if (heldcall)
08947       ast_mutex_unlock(&iaxsl[heldcall]);
08948    callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
08949    if (heldcall)
08950       ast_mutex_lock(&iaxsl[heldcall]);
08951    if (peer->callno < 1) {
08952       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08953       return -1;
08954    }
08955 
08956    /* Speed up retransmission times for this qualify call */
08957    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08958    iaxs[peer->callno]->peerpoke = peer;
08959    
08960    /* Remove any pending pokeexpire task */
08961    if (peer->pokeexpire > -1) {
08962       if (!ast_sched_del(sched, peer->pokeexpire)) {
08963          peer->pokeexpire = -1;
08964          peer_unref(peer);
08965       }
08966    }
08967 
08968    /* Queue up a new task to handle no reply */
08969    /* If the host is already unreachable then use the unreachable interval instead */
08970    if (peer->lastms < 0) {
08971       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
08972    } else
08973       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
08974 
08975    if (peer->pokeexpire == -1)
08976       peer_unref(peer);
08977 
08978    /* And send the poke */
08979    ast_mutex_lock(&iaxsl[callno]);
08980    if (iaxs[callno]) {
08981       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08982    }
08983    ast_mutex_unlock(&iaxsl[callno]);
08984 
08985    return 0;
08986 }

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

Definition at line 8917 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08918 {
08919    struct iax2_peer *peer = obj;
08920 
08921    iax2_poke_peer(peer, 0);
08922 
08923    return 0;
08924 }

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

Definition at line 6515 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06516 {
06517    struct iax2_peer *peer = (struct iax2_peer *)data;
06518    peer->pokeexpire = -1;
06519 #ifdef SCHED_MULTITHREADED
06520    if (schedule_action(__iax2_poke_peer_s, data))
06521 #endif      
06522       __iax2_poke_peer_s(data);
06523    return 0;
06524 }

static int iax2_predestroy ( int  callno  )  [static]

Note:
Since this function calls iax2_queue_hangup(), the pvt struct for the given call number may disappear during its execution.

Definition at line 2155 of file chan_iax2.c.

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

Referenced by iax2_hangup(), and send_command_final().

02156 {
02157    struct ast_channel *c;
02158    struct chan_iax2_pvt *pvt = iaxs[callno];
02159 
02160    if (!pvt)
02161       return -1;
02162    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
02163       iax2_destroy_helper(pvt);
02164       ast_set_flag(pvt, IAX_ALREADYGONE); 
02165    }
02166    c = pvt->owner;
02167    if (c) {
02168       c->tech_pvt = NULL;
02169       iax2_queue_hangup(callno);
02170       pvt->owner = NULL;
02171       ast_module_unref(ast_module_info->self);
02172    }
02173    return 0;
02174 }

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

Definition at line 8581 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

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

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8572 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08573 {
08574    struct iax2_thread *thread = data;
08575    ast_mutex_destroy(&thread->lock);
08576    ast_cond_destroy(&thread->cond);
08577    free(thread);
08578    ast_atomic_dec_and_test(&iaxactivethreadcount);
08579 }

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

Definition at line 8860 of file chan_iax2.c.

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

08861 {
08862    int force = 0;
08863    int res;
08864    if (argc < 4)
08865       return RESULT_SHOWUSAGE;
08866    if ((argc > 4)) {
08867       if (!strcasecmp(argv[4], "forced"))
08868          force = 1;
08869       else
08870          return RESULT_SHOWUSAGE;
08871    }
08872    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08873    if (res < 0)
08874       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08875    else if (res < 1)
08876       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08877    else
08878       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08879    return RESULT_SUCCESS;
08880 }

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

Definition at line 8763 of file chan_iax2.c.

References iax_prov_complete_template().

08764 {
08765    if (pos != 3)
08766       return NULL;
08767    return iax_prov_complete_template(line, word, pos, state);
08768 }

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

Definition at line 8770 of file chan_iax2.c.

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

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

08771 {
08772    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08773       is found for template */
08774    struct iax_ie_data provdata;
08775    struct iax_ie_data ied;
08776    unsigned int sig;
08777    struct sockaddr_in sin;
08778    int callno;
08779    struct create_addr_info cai;
08780 
08781    memset(&cai, 0, sizeof(cai));
08782 
08783    if (option_debug)
08784       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08785 
08786    if (iax_provision_build(&provdata, &sig, template, force)) {
08787       if (option_debug)
08788          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08789       return 0;
08790    }
08791 
08792    if (end) {
08793       memcpy(&sin, end, sizeof(sin));
08794       cai.sockfd = sockfd;
08795    } else if (create_addr(dest, NULL, &sin, &cai))
08796       return -1;
08797 
08798    /* Build the rest of the message */
08799    memset(&ied, 0, sizeof(ied));
08800    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08801 
08802    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08803    if (!callno)
08804       return -1;
08805 
08806    if (iaxs[callno]) {
08807       /* Schedule autodestruct in case they don't ever give us anything back */
08808       AST_SCHED_DEL(sched, iaxs[callno]->autoid);
08809       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08810       ast_set_flag(iaxs[callno], IAX_PROVISION);
08811       /* Got a call number now, so go ahead and send the provisioning information */
08812       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08813    }
08814    ast_mutex_unlock(&iaxsl[callno]);
08815 
08816    return 1;
08817 }

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

Definition at line 2279 of file chan_iax2.c.

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

02280 {
02281    struct iax2_peer *peer;
02282 
02283    if (argc != 4)
02284         return RESULT_SHOWUSAGE;
02285    if (!strcmp(argv[3],"all")) {
02286       reload_config();
02287       ast_cli(fd, "OK cache is flushed.\n");
02288    } else if ((peer = find_peer(argv[3], 0))) {
02289       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02290          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02291          expire_registry(peer_ref(peer));
02292          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02293       } else {
02294          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02295       }
02296       peer_unref(peer);
02297    } else {
02298       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02299    }
02300    
02301    return RESULT_SUCCESS;
02302 }

static int iax2_queue_control_data ( int  callno,
enum ast_control_frame_type  control,
const void *  data,
size_t  datalen 
) [static]

Queue a control frame on the ast_channel owner.

This function queues a control frame on the owner of the IAX2 pvt struct that is active for the given call number.

Precondition:
Assumes lock for callno is already held.
Note:
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it. This function may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 1765 of file chan_iax2.c.

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

Referenced by socket_process().

01767 {
01768    for (;;) {
01769       if (iaxs[callno] && iaxs[callno]->owner) {
01770          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01771             /* Avoid deadlock by pausing and trying again */
01772             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01773          } else {
01774             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01775             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01776             break;
01777          }
01778       } else
01779          break;
01780    }
01781    return 0;
01782 }

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

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

Precondition:
This function assumes that iaxsl[callno] is locked when called.
Note:
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it. This function may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 1703 of file chan_iax2.c.

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

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

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

static int iax2_queue_hangup ( int  callno  )  [static]

Queue a hangup frame on the ast_channel owner.

This function queues a hangup frame on the owner of the IAX2 pvt struct that is active for the given call number.

Precondition:
Assumes lock for callno is already held.
Note:
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it. This function may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.

Definition at line 1734 of file chan_iax2.c.

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

Referenced by iax2_predestroy().

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

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

Definition at line 3481 of file chan_iax2.c.

References ast_log(), and LOG_NOTICE.

03482 {
03483    ast_log(LOG_NOTICE, "I should never be called! Hanging up.\n");
03484    return NULL;
03485 }

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

Definition at line 5997 of file chan_iax2.c.

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

Referenced by set_config().

05998 {
05999    struct iax2_registry *reg;
06000    char copy[256];
06001    char *username, *hostname, *secret;
06002    char *porta;
06003    char *stringp=NULL;
06004    
06005    if (!value)
06006       return -1;
06007    ast_copy_string(copy, value, sizeof(copy));
06008    stringp=copy;
06009    username = strsep(&stringp, "@");
06010    hostname = strsep(&stringp, "@");
06011    if (!hostname) {
06012       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
06013       return -1;
06014    }
06015    stringp=username;
06016    username = strsep(&stringp, ":");
06017    secret = strsep(&stringp, ":");
06018    stringp=hostname;
06019    hostname = strsep(&stringp, ":");
06020    porta = strsep(&stringp, ":");
06021    
06022    if (porta && !atoi(porta)) {
06023       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
06024       return -1;
06025    }
06026    if (!(reg = ast_calloc(1, sizeof(*reg))))
06027       return -1;
06028    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
06029       free(reg);
06030       return -1;
06031    }
06032    ast_copy_string(reg->username, username, sizeof(reg->username));
06033    if (secret)
06034       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
06035    reg->expire = -1;
06036    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
06037    reg->addr.sin_family = AF_INET;
06038    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
06039    AST_LIST_LOCK(&registrations);
06040    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
06041    AST_LIST_UNLOCK(&registrations);
06042    
06043    return 0;
06044 }

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

Definition at line 10288 of file chan_iax2.c.

References reload_config().

10289 {
10290    return reload_config();
10291 }

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

Definition at line 8998 of file chan_iax2.c.

References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_translator_best_choice(), create_addr(), find_callno_locked(), 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.

08999 {
09000    int callno;
09001    int res;
09002    int fmt, native;
09003    struct sockaddr_in sin;
09004    struct ast_channel *c;
09005    struct parsed_dial_string pds;
09006    struct create_addr_info cai;
09007    char *tmpstr;
09008 
09009    memset(&pds, 0, sizeof(pds));
09010    tmpstr = ast_strdupa(data);
09011    parse_dial_string(tmpstr, &pds);
09012 
09013    if (ast_strlen_zero(pds.peer)) {
09014       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
09015       return NULL;
09016    }
09017           
09018    memset(&cai, 0, sizeof(cai));
09019    cai.capability = iax2_capability;
09020 
09021    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
09022    
09023    /* Populate our address from the given */
09024    if (create_addr(pds.peer, NULL, &sin, &cai)) {
09025       *cause = AST_CAUSE_UNREGISTERED;
09026       return NULL;
09027    }
09028 
09029    if (pds.port)
09030       sin.sin_port = htons(atoi(pds.port));
09031 
09032    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
09033    if (callno < 1) {
09034       ast_log(LOG_WARNING, "Unable to create call\n");
09035       *cause = AST_CAUSE_CONGESTION;
09036       return NULL;
09037    }
09038 
09039    /* If this is a trunk, update it now */
09040    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
09041    if (ast_test_flag(&cai, IAX_TRUNK)) {
09042       int new_callno;
09043       if ((new_callno = make_trunk(callno, 1)) != -1)
09044          callno = new_callno;
09045    }
09046    iaxs[callno]->maxtime = cai.maxtime;
09047    if (cai.found)
09048       ast_string_field_set(iaxs[callno], host, pds.peer);
09049 
09050    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
09051 
09052    ast_mutex_unlock(&iaxsl[callno]);
09053 
09054    if (c) {
09055       /* Choose a format we can live with */
09056       if (c->nativeformats & format) 
09057          c->nativeformats &= format;
09058       else {
09059          native = c->nativeformats;
09060          fmt = format;
09061          res = ast_translator_best_choice(&fmt, &native);
09062          if (res < 0) {
09063             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
09064                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
09065             ast_hangup(c);
09066             return NULL;
09067          }
09068          c->nativeformats = native;
09069       }
09070       c->readformat = ast_best_codec(c->nativeformats);
09071       c->writeformat = c->readformat;
09072    }
09073 
09074    return c;
09075 }

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

Definition at line 984 of file chan_iax2.c.

References ast_sched_add(), and signal_condition().

Referenced by __attempt_transmit(), __find_callno(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), auth_fail(), iax2_ack_registry(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_poke_peer(), iax2_provision(), make_trunk(), network_thread(), reg_source_db(), socket_process(), update_jbsched(), and update_registry().

00985 {
00986    int res;
00987 
00988    res = ast_sched_add(con, when, callback, data);
00989    signal_condition(&sched_lock, &sched_cond);
00990 
00991    return res;
00992 }

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

References iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, ast_frame::datalen, iax_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, encrypt_frame(), f, iax_frame::final, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, 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().

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

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

Definition at line 2810 of file chan_iax2.c.

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

02811 {
02812    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02813 }

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

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

02806 {
02807    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02808 }

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

Definition at line 2798 of file chan_iax2.c.

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

02799 {
02800    
02801    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02802       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02803 }

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

Definition at line 3455 of file chan_iax2.c.

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

03456 {
03457    struct ast_option_header *h;
03458    int res;
03459 
03460    switch (option) {
03461    case AST_OPTION_TXGAIN:
03462    case AST_OPTION_RXGAIN:
03463       /* these two cannot be sent, because they require a result */
03464       errno = ENOSYS;
03465       return -1;
03466    default:
03467       if (!(h = ast_malloc(datalen + sizeof(*h))))
03468          return -1;
03469 
03470       h->flag = AST_OPTION_FLAG_REQUEST;
03471       h->option = htons(option);
03472       memcpy(h->data, data, datalen);
03473       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03474                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03475                  datalen + sizeof(*h), -1);
03476       free(h);
03477       return res;
03478    }
03479 }

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

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

02484 {
02485    struct iax2_dpcache *dp;
02486    char tmp[1024], *pc;
02487    int s;
02488    int x,y;
02489    struct timeval tv;
02490    gettimeofday(&tv, NULL);
02491    ast_mutex_lock(&dpcache_lock);
02492    dp = dpcache;
02493    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02494    while(dp) {
02495       s = dp->expiry.tv_sec - tv.tv_sec;
02496       tmp[0] = '\0';
02497       if (dp->flags & CACHE_FLAG_EXISTS)
02498          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02499       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02500          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02501       if (dp->flags & CACHE_FLAG_CANEXIST)
02502          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02503       if (dp->flags & CACHE_FLAG_PENDING)
02504          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02505       if (dp->flags & CACHE_FLAG_TIMEOUT)
02506          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02507       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02508          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02509       if (dp->flags & CACHE_FLAG_MATCHMORE)
02510          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02511       if (dp->flags & CACHE_FLAG_UNKNOWN)
02512          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02513       /* Trim trailing pipe */
02514       if (!ast_strlen_zero(tmp))
02515          tmp[strlen(tmp) - 1] = '\0';
02516       else
02517          ast_copy_string(tmp, "(none)", sizeof(tmp));
02518       y=0;
02519       pc = strchr(dp->peercontext, '@');
02520       if (!pc)
02521          pc = dp->peercontext;
02522       else
02523          pc++;
02524       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02525          if (dp->waiters[x] > -1)
02526             y++;
02527       if (s > 0)
02528          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02529       else
02530          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02531       dp = dp->next;
02532    }
02533    ast_mutex_unlock(&dpcache_lock);
02534    return RESULT_SUCCESS;
02535 }

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

Definition at line 4851 of file chan_iax2.c.

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

04852 {
04853 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04854 #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"
04855 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04856    int x;
04857    int numchans = 0;
04858 
04859    if (argc != 3)
04860       return RESULT_SHOWUSAGE;
04861    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04862    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04863       ast_mutex_lock(&iaxsl[x]);
04864       if (iaxs[x]) {
04865          int lag, jitter, localdelay;
04866          jb_info jbinfo;
04867          
04868          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04869             jb_getinfo(iaxs[x]->jb, &jbinfo);
04870             jitter = jbinfo.jitter;
04871             localdelay = jbinfo.current - jbinfo.min;
04872          } else {
04873             jitter = -1;
04874             localdelay = 0;
04875          }
04876          lag = iaxs[x]->remote_rr.delay;
04877          ast_cli(fd, FORMAT,
04878             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04879             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04880             S_OR(iaxs[x]->username, "(None)"),
04881             iaxs[x]->callno, iaxs[x]->peercallno,
04882             iaxs[x]->oseqno, iaxs[x]->iseqno,
04883             lag,
04884             jitter,
04885             localdelay,
04886             ast_getformatname(iaxs[x]->voiceformat) );
04887          numchans++;
04888       }
04889       ast_mutex_unlock(&iaxsl[x]);
04890    }
04891    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04892    return RESULT_SUCCESS;
04893 #undef FORMAT
04894 #undef FORMAT2
04895 #undef FORMATB
04896 }

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

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

04763 {
04764 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04765 #if !defined(__FreeBSD__)
04766 #define FORMAT "%-15.15s  %-15d %-15d\n"
04767 #else /* __FreeBSD__ */
04768 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04769 #endif /* __FreeBSD__ */
04770    struct iax_firmware *cur;
04771    if ((argc != 3) && (argc != 4))
04772       return RESULT_SHOWUSAGE;
04773    ast_mutex_lock(&waresl.lock);
04774    
04775    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04776    for (cur = waresl.wares;cur;cur = cur->next) {
04777       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04778          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04779             (int)ntohl(cur->fwh->datalen));
04780    }
04781    ast_mutex_unlock(&waresl.lock);
04782    return RESULT_SUCCESS;
04783 #undef FORMAT
04784 #undef FORMAT2
04785 }

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

Definition at line 4974 of file chan_iax2.c.

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

04975 {
04976    int numchans = 0;
04977    if (argc != 3)
04978       return RESULT_SHOWUSAGE;
04979    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04980    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04981    numchans = ast_cli_netstats(NULL, fd, 1);
04982    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04983    return RESULT_SUCCESS;
04984 }

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

Show one peer in detail.

Definition at line 2373 of file chan_iax2.c.

References iax2_peer::addr, ast_callerid_merge(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, iax2_peer::capability, iax2_peer::defaddr, iax2_peer::expire, find_peer(), iax2_peer::ha, IAX_DYNAMIC, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_peer::prefs, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax2_peer::smoothing.

02374 {
02375    char status[30];
02376    char cbuf[256];
02377    struct iax2_peer *peer;
02378    char codec_buf[512];
02379    int x = 0, codec = 0, load_realtime = 0;
02380 
02381    if (argc < 4)
02382       return RESULT_SHOWUSAGE;
02383 
02384    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02385 
02386    peer = find_peer(argv[3], load_realtime);
02387    if (peer) {
02388       ast_cli(fd,"\n\n");
02389       ast_cli(fd, "  * Name       : %s\n", peer->name);
02390       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02391       ast_cli(fd, "  Context      : %s\n", peer->context);
02392       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02393       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02394       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02395       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02396       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02397       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));
02398       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02399       ast_cli(fd, "  Username     : %s\n", peer->username);
02400       ast_cli(fd, "  Codecs       : ");
02401       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02402       ast_cli(fd, "%s\n", codec_buf);
02403 
02404       ast_cli(fd, "  Codec Order  : (");
02405       for(x = 0; x < 32 ; x++) {
02406          codec = ast_codec_pref_index(&peer->prefs,x);
02407          if(!codec)
02408             break;
02409          ast_cli(fd, "%s", ast_getformatname(codec));
02410          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02411             ast_cli(fd, "|");
02412       }
02413 
02414       if (!x)
02415          ast_cli(fd, "none");
02416       ast_cli(fd, ")\n");
02417 
02418       ast_cli(fd, "  Status       : ");
02419       peer_status(peer, status, sizeof(status));   
02420       ast_cli(fd, "%s\n",status);
02421       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02422       ast_cli(fd,"\n");
02423       peer_unref(peer);
02424    } else {
02425       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02426       ast_cli(fd,"\n");
02427    }
02428 
02429    return RESULT_SUCCESS;
02430 }

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

Definition at line 4751 of file chan_iax2.c.

References __iax2_show_peers().

04752 {
04753    return __iax2_show_peers(0, fd, NULL, argc, argv);
04754 }

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

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

04824 {
04825 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04826 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04827    struct iax2_registry *reg = NULL;
04828 
04829    char host[80];
04830    char perceived[80];
04831    if (argc != 3)
04832       return RESULT_SHOWUSAGE;
04833    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04834    AST_LIST_LOCK(&registrations);
04835    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04836       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04837       if (reg->us.sin_addr.s_addr) 
04838          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04839       else
04840          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04841       ast_cli(fd, FORMAT, host, 
04842                (reg->dnsmgr) ? "Y" : "N", 
04843                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04844    }
04845    AST_LIST_UNLOCK(&registrations);
04846    return RESULT_SUCCESS;
04847 #undef FORMAT
04848 #undef FORMAT2
04849 }

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

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

02458 {
02459    struct iax_frame *cur;
02460    int cnt = 0, dead=0, final=0;
02461 
02462    if (argc != 3)
02463       return RESULT_SHOWUSAGE;
02464 
02465    AST_LIST_LOCK(&iaxq.queue);
02466    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02467       if (cur->retries < 0)
02468          dead++;
02469       if (cur->final)
02470          final++;
02471       cnt++;
02472    }
02473    AST_LIST_UNLOCK(&iaxq.queue);
02474 
02475    ast_cli(fd, "    IAX Statistics\n");
02476    ast_cli(fd, "---------------------\n");
02477    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02478    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02479    
02480    return RESULT_SUCCESS;
02481 }

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

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

04693 {
04694    struct iax2_thread *thread = NULL;
04695    time_t t;
04696    int threadcount = 0, dynamiccount = 0;
04697    char type;
04698 
04699    if (argc != 3)
04700       return RESULT_SHOWUSAGE;
04701       
04702    ast_cli(fd, "IAX2 Thread Information\n");
04703    time(&t);
04704    ast_cli(fd, "Idle Threads:\n");
04705    AST_LIST_LOCK(&idle_list);
04706    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04707 #ifdef DEBUG_SCHED_MULTITHREAD
04708       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04709          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04710 #else
04711       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04712          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04713 #endif
04714       threadcount++;
04715    }
04716    AST_LIST_UNLOCK(&idle_list);
04717    ast_cli(fd, "Active Threads:\n");
04718    AST_LIST_LOCK(&active_list);
04719    AST_LIST_TRAVERSE(&active_list, thread, list) {
04720       if (thread->type == IAX_TYPE_DYNAMIC)
04721          type = 'D';
04722       else
04723          type = 'P';
04724 #ifdef DEBUG_SCHED_MULTITHREAD
04725       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04726          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04727 #else
04728       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04729          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04730 #endif
04731       threadcount++;
04732    }
04733    AST_LIST_UNLOCK(&active_list);
04734    ast_cli(fd, "Dynamic Threads:\n");
04735         AST_LIST_LOCK(&dynamic_list);
04736         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04737 #ifdef DEBUG_SCHED_MULTITHREAD
04738                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04739                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04740 #else
04741                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04742                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04743 #endif
04744       dynamiccount++;
04745         }
04746         AST_LIST_UNLOCK(&dynamic_list);
04747    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04748    return RESULT_SUCCESS;
04749 }

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

Definition at line 4509 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_strlen_zero(), ast_test_flag, iax2_user::authmethods, iax2_context::context, iax2_user::contexts, FORMAT, FORMAT2, iax2_user::ha, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, RESULT_SHOWUSAGE, RESULT_SUCCESS, user_unref(), and users.

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

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

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

03488 {
03489    int res;
03490    struct iax_ie_data ied0;
03491    struct iax_ie_data ied1;
03492    unsigned int transferid = (unsigned int)ast_random();
03493    memset(&ied0, 0, sizeof(ied0));
03494    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03495    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03496    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03497 
03498    memset(&ied1, 0, sizeof(ied1));
03499    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03500    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03501    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03502    
03503    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03504    if (res)
03505       return -1;
03506    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03507    if (res)
03508       return -1;
03509    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03510    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03511    return 0;
03512 }

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

Definition at line 2304 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02305 {
02306        if (argc != 4)
02307                return RESULT_SHOWUSAGE;
02308 
02309        test_losspct = atoi(argv[3]);
02310 
02311        return RESULT_SUCCESS;
02312 }

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

Definition at line 3733 of file chan_iax2.c.

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

03734 {
03735    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03736    struct iax_ie_data ied;
03737    char tmp[256], *context;
03738    ast_copy_string(tmp, dest, sizeof(tmp));
03739    context = strchr(tmp, '@');
03740    if (context) {
03741       *context = '\0';
03742       context++;
03743    }
03744    memset(&ied, 0, sizeof(ied));
03745    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03746    if (context)
03747       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03748    if (option_debug)
03749       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03750    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03751 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

Definition at line 2769 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, iaxq, iax_frame::sentyet, and signal_condition().

Referenced by iax2_send().

02770 {
02771    /* Lock the queue and place this packet at the end */
02772    /* By setting this to 0, the network thread will send it for us, and
02773       queue retransmission if necessary */
02774    fr->sentyet = 0;
02775    AST_LIST_LOCK(&iaxq.queue);
02776    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02777    iaxq.count++;
02778    AST_LIST_UNLOCK(&iaxq.queue);
02779    /* Wake up the network and scheduler thread */
02780    if (netthreadid != AST_PTHREADT_NULL)
02781       pthread_kill(netthreadid, SIGURG);
02782    signal_condition(&sched_lock, &sched_cond);
02783    return 0;
02784 }

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

Definition at line 6570 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06571 {
06572    /* Drop when trunk is about 5 seconds idle */
06573    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06574       return 1;
06575    return 0;
06576 }

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

Definition at line 4098 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, option_debug, chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.

Referenced by iax2_send().

04099 {
04100    struct ast_frame *f;
04101    struct iax2_trunk_peer *tpeer;
04102    void *tmp, *ptr;
04103    struct ast_iax2_meta_trunk_entry *met;
04104    struct ast_iax2_meta_trunk_mini *mtm;
04105 
04106    f = &fr->af;
04107    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
04108    if (tpeer) {
04109       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
04110          /* Need to reallocate space */
04111          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
04112             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
04113                ast_mutex_unlock(&tpeer->lock);
04114                return -1;
04115             }
04116             
04117             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
04118             tpeer->trunkdata = tmp;
04119             if (option_debug)
04120                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);
04121          } else {
04122             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));
04123             ast_mutex_unlock(&tpeer->lock);
04124             return -1;
04125          }
04126       }
04127 
04128       /* Append to meta frame */
04129       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
04130       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
04131          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
04132          mtm->len = htons(f->datalen);
04133          mtm->mini.callno = htons(pvt->callno);
04134          mtm->mini.ts = htons(0xffff & fr->ts);
04135          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
04136          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
04137       } else {
04138          met = (struct ast_iax2_meta_trunk_entry *)ptr;
04139          /* Store call number and length in meta header */
04140          met->callno = htons(pvt->callno);
04141          met->len = htons(f->datalen);
04142          /* Advance pointers/decrease length past trunk entry header */
04143          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
04144          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
04145       }
04146       /* Copy actual trunk data */
04147       memcpy(ptr, f->data, f->datalen);
04148       tpeer->trunkdatalen += f->datalen;
04149 
04150       tpeer->calls++;
04151       ast_mutex_unlock(&tpeer->lock);
04152    }
04153    return 0;
04154 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6487 of file chan_iax2.c.

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

Referenced by socket_process().

06488 {
06489    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06490 }

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

Definition at line 5041 of file chan_iax2.c.

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

05042 {
05043    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
05044    int res = -1;
05045    ast_mutex_lock(&iaxsl[callno]);
05046    if (iaxs[callno]) {
05047    /* If there's an outstanding error, return failure now */
05048       if (!iaxs[callno]->error) {
05049          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
05050             res = 0;
05051             /* Don't waste bandwidth sending null frames */
05052          else if (f->frametype == AST_FRAME_NULL)
05053             res = 0;
05054          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
05055             res = 0;
05056          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
05057             res = 0;
05058          else
05059          /* Simple, just queue for transmission */
05060             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
05061       } else {
05062          if (option_debug)
05063             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
05064       }
05065    }
05066    /* If it's already gone, just return */
05067    ast_mutex_unlock(&iaxsl[callno]);
05068    return res;
05069 }

static int iax_check_version ( char *  dev  )  [static]

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

01939 {
01940    int res = 0;
01941    struct iax_firmware *cur;
01942    if (!ast_strlen_zero(dev)) {
01943       ast_mutex_lock(&waresl.lock);
01944       cur = waresl.wares;
01945       while(cur) {
01946          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01947             res = ntohs(cur->fwh->version);
01948             break;
01949          }
01950          cur = cur->next;
01951       }
01952       ast_mutex_unlock(&waresl.lock);
01953    }
01954    return res;
01955 }

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

Definition at line 762 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 768 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

01958 {
01959    int res = -1;
01960    unsigned int bs = desc & 0xff;
01961    unsigned int start = (desc >> 8) & 0xffffff;
01962    unsigned int bytes;
01963    struct iax_firmware *cur;
01964    if (!ast_strlen_zero((char *)dev) && bs) {
01965       start *= bs;
01966       ast_mutex_lock(&waresl.lock);
01967       cur = waresl.wares;
01968       while(cur) {
01969          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01970             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01971             if (start < ntohl(cur->fwh->datalen)) {
01972                bytes = ntohl(cur->fwh->datalen) - start;
01973                if (bytes > bs)
01974                   bytes = bs;
01975                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01976             } else {
01977                bytes = 0;
01978                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01979             }
01980             if (bytes == bs)
01981                res = 0;
01982             else
01983                res = 1;
01984             break;
01985          }
01986          cur = cur->next;
01987       }
01988       ast_mutex_unlock(&waresl.lock);
01989    }
01990    return res;
01991 }

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

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

06759 {
06760    struct iax_dual *d;
06761    struct ast_channel *chan1m, *chan2m;
06762    pthread_t th;
06763    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06764    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06765    if (chan2m && chan1m) {
06766       /* Make formats okay */
06767       chan1m->readformat = chan1->readformat;
06768       chan1m->writeformat = chan1->writeformat;
06769       ast_channel_masquerade(chan1m, chan1);
06770       /* Setup the extensions and such */
06771       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06772       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06773       chan1m->priority = chan1->priority;
06774       
06775       /* We make a clone of the peer channel too, so we can play
06776          back the announcement */
06777       /* Make formats okay */
06778       chan2m->readformat = chan2->readformat;
06779       chan2m->writeformat = chan2->writeformat;
06780       ast_channel_masquerade(chan2m, chan2);
06781       /* Setup the extensions and such */
06782       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06783       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06784       chan2m->priority = chan2->priority;
06785       if (ast_do_masquerade(chan2m)) {
06786          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06787          ast_hangup(chan2m);
06788          return -1;
06789       }
06790    } else {
06791       if (chan1m)
06792          ast_hangup(chan1m);
06793       if (chan2m)
06794          ast_hangup(chan2m);
06795       return -1;
06796    }
06797    if ((d = ast_calloc(1, sizeof(*d)))) {
06798       pthread_attr_t attr;
06799 
06800       pthread_attr_init(&attr);
06801       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06802 
06803       d->chan1 = chan1m;
06804       d->chan2 = chan2m;
06805       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06806          pthread_attr_destroy(&attr);
06807          return 0;
06808       }
06809       pthread_attr_destroy(&attr);
06810       free(d);
06811    }
06812    return -1;
06813 }

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

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

06739 {
06740    struct ast_channel *chan1, *chan2;
06741    struct iax_dual *d;
06742    struct ast_frame *f;
06743    int ext;
06744    int res;
06745    d = stuff;
06746    chan1 = d->chan1;
06747    chan2 = d->chan2;
06748    free(d);
06749    f = ast_read(chan1);
06750    if (f)
06751       ast_frfree(f);
06752    res = ast_park_call(chan1, chan2, 0, &ext);
06753    ast_hangup(chan2);
06754    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06755    return NULL;
06756 }

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

Definition at line 1422 of file chan_iax2.c.

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

Referenced by socket_process().

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

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

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

00893 {
00894    if (thread->type == IAX_TYPE_DYNAMIC) {
00895       AST_LIST_LOCK(&dynamic_list);
00896       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00897       AST_LIST_UNLOCK(&dynamic_list);
00898    } else {
00899       AST_LIST_LOCK(&idle_list);
00900       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00901       AST_LIST_UNLOCK(&idle_list);
00902    }
00903 
00904    return;
00905 }

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

Definition at line 797 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 773 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 785 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 11124 of file chan_iax2.c.

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

11125 {
11126    char *config = "iax.conf";
11127    int res = 0;
11128    int x;
11129    struct iax2_registry *reg = NULL;
11130 
11131    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
11132    if (!peers)
11133       return AST_MODULE_LOAD_FAILURE;
11134    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
11135    if (!users) {
11136       ao2_ref(peers, -1);
11137       return AST_MODULE_LOAD_FAILURE;
11138    }
11139    iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
11140    if (!iax_peercallno_pvts) {
11141       ao2_ref(peers, -1);
11142       ao2_ref(users, -1);
11143       return AST_MODULE_LOAD_FAILURE;
11144    }
11145 
11146    ast_custom_function_register(&iaxpeer_function);
11147 
11148    iax_set_output(iax_debug_output);
11149    iax_set_error(iax_error_output);
11150    jb_setoutput(jb_error_output, jb_warning_output, NULL);
11151    
11152 #ifdef HAVE_ZAPTEL
11153 #ifdef ZAPTEL_TIMERACK
11154    timingfd = open("/dev/zap/timer", O_RDWR);
11155    if (timingfd < 0)
11156 #endif
11157       timingfd = open("/dev/zap/pseudo", O_RDWR);
11158    if (timingfd < 0) 
11159       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
11160 #elif defined(HAVE_DAHDI)
11161 #ifdef DAHDI_TIMERACK
11162    timingfd = open("/dev/dahdi/timer", O_RDWR);
11163    if (timingfd < 0)
11164 #endif
11165       timingfd = open("/dev/dahdi/pseudo", O_RDWR);
11166    if (timingfd < 0) 
11167       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
11168 #endif
11169 
11170    memset(iaxs, 0, sizeof(iaxs));
11171 
11172    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11173       ast_mutex_init(&iaxsl[x]);
11174    }
11175    
11176    ast_cond_init(&sched_cond, NULL);
11177 
11178    io = io_context_create();
11179    sched = sched_context_create();
11180    
11181    if (!io || !sched) {
11182       ast_log(LOG_ERROR, "Out of memory\n");
11183       return -1;
11184    }
11185 
11186    netsock = ast_netsock_list_alloc();
11187    if (!netsock) {
11188       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
11189       return -1;
11190    }
11191    ast_netsock_init(netsock);
11192 
11193    outsock = ast_netsock_list_alloc();
11194    if (!outsock) {
11195       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
11196       return -1;
11197    }
11198    ast_netsock_init(outsock);
11199 
11200    ast_mutex_init(&waresl.lock);
11201 
11202    AST_LIST_HEAD_INIT(&iaxq.queue);
11203    
11204    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11205 
11206    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
11207    
11208    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
11209    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
11210 
11211    if(set_config(config, 0) == -1)
11212       return AST_MODULE_LOAD_DECLINE;
11213 
11214    if (ast_channel_register(&iax2_tech)) {
11215       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
11216       __unload_module();
11217       return -1;
11218    }
11219 
11220    if (ast_register_switch(&iax2_switch)) 
11221       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
11222 
11223    res = start_network_thread();
11224    if (!res) {
11225       if (option_verbose > 1) 
11226          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
11227    } else {
11228       ast_log(LOG_ERROR, "Unable to start network thread\n");
11229       ast_netsock_release(netsock);
11230       ast_netsock_release(outsock);
11231    }
11232 
11233    AST_LIST_LOCK(&registrations);
11234    AST_LIST_TRAVERSE(&registrations, reg, entry)
11235       iax2_do_register(reg);
11236    AST_LIST_UNLOCK(&registrations); 
11237 
11238    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
11239    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
11240 
11241    reload_firmware(0);
11242    iax_provision_reload();
11243    return res;
11244 }

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

Definition at line 3514 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03515 {
03516    ast_mutex_lock(&iaxsl[callno0]);
03517    while (ast_mutex_trylock(&iaxsl[callno1])) {
03518       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03519    }
03520 }

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

Definition at line 1476 of file chan_iax2.c.

References ARRAY_LEN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_sched_add(), iaxsl, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, option_debug, sched, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().

Referenced by iax2_request(), and socket_process().

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

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

Definition at line 4755 of file chan_iax2.c.

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

Referenced by load_module().

04756 {
04757    ast_cli_netstats(s, -1, 0);
04758    astman_append(s, "\r\n");
04759    return RESULT_SUCCESS;
04760 }

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

Definition at line 4788 of file chan_iax2.c.

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

Referenced by load_module().

04789 {
04790    char *a[] = { "iax2", "show", "users" };
04791    int ret;
04792    const char *id = astman_get_header(m,"ActionID");
04793 
04794    if (!ast_strlen_zero(id))
04795       astman_append(s, "ActionID: %s\r\n",id);
04796    ret = __iax2_show_peers(1, -1, s, 3, a );
04797    astman_append(s, "\r\n\r\n" );
04798    return ret;
04799 } /* /JDG */

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

Definition at line 1442 of file chan_iax2.c.

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

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

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

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

Definition at line 4162 of file chan_iax2.c.

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

Referenced by decode_frame().

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

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

Definition at line 4186 of file chan_iax2.c.

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

Referenced by encrypt_frame().

04187 {
04188 #if 0
04189    /* Debug with "fake encryption" */
04190    int x;
04191    if (len % 16)
04192       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04193    for (x=0;x<len;x++)
04194       dst[x] = src[x] ^ 0xff;
04195 #else
04196    unsigned char curblock[16] = { 0 };
04197    int x;
04198    while(len > 0) {
04199       for (x=0;x<16;x++)
04200          curblock[x] ^= src[x];
04201       aes_encrypt(curblock, dst, ecx);
04202       memcpy(curblock, dst, sizeof(curblock)); 
04203       dst += 16;
04204       src += 16;
04205       len -= 16;
04206    }
04207 #endif
04208 }

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

Definition at line 5363 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

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

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

Definition at line 9104 of file chan_iax2.c.

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

Referenced by start_network_thread().

09105 {
09106    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
09107       from the network, and queue them for delivery to the channels */
09108    int res, count, wakeup;
09109    struct iax_frame *f;
09110 
09111    if (timingfd > -1)
09112       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
09113    
09114    for(;;) {
09115       pthread_testcancel();
09116 
09117       /* Go through the queue, sending messages which have not yet been
09118          sent, and scheduling retransmissions if appropriate */
09119       AST_LIST_LOCK(&iaxq.queue);
09120       count = 0;
09121       wakeup = -1;
09122       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
09123          if (f->sentyet)
09124             continue;
09125          
09126          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
09127          if (ast_mutex_trylock(&iaxsl[f->callno])) {
09128             wakeup = 1;
09129             continue;
09130          }
09131 
09132          f->sentyet++;
09133 
09134          if (iaxs[f->callno]) {
09135             send_packet(f);
09136             count++;
09137          } 
09138 
09139          ast_mutex_unlock(&iaxsl[f->callno]);
09140 
09141          if (f->retries < 0) {
09142             /* This is not supposed to be retransmitted */
09143             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
09144             iaxq.count--;
09145             /* Free the iax frame */
09146             iax_frame_free(f);
09147          } else {
09148             /* We need reliable delivery.  Schedule a retransmission */
09149             f->retries++;
09150             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
09151          }
09152       }
09153       AST_LIST_TRAVERSE_SAFE_END
09154       AST_LIST_UNLOCK(&iaxq.queue);
09155 
09156       pthread_testcancel();
09157 
09158       if (option_debug && count >= 20)
09159          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
09160 
09161       /* Now do the IO, and run scheduled tasks */
09162       res = ast_io_wait(io, wakeup);
09163       if (res >= 0) {
09164          if (option_debug && res >= 20)
09165             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
09166       }
09167    }
09168    return NULL;
09169 }

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

Definition at line 1383 of file chan_iax2.c.

References ao2_alloc(), ao2_ref(), ast_string_field_init, ast_string_field_set, exten, jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, prefs, pvt_destructor(), and jb_conf::resync_threshold.

Referenced by __find_callno().

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

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

03230 {
03231    if (ast_strlen_zero(data))
03232       return;
03233 
03234    pds->peer = strsep(&data, "/");
03235    pds->exten = strsep(&data, "/");
03236    pds->options = data;
03237 
03238    if (pds->exten) {
03239       data = pds->exten;
03240       pds->exten = strsep(&data, "@");
03241       pds->context = data;
03242    }
03243 
03244    if (strchr(pds->peer, '@')) {
03245       data = pds->peer;
03246       pds->username = strsep(&data, "@");
03247       pds->peer = data;
03248    }
03249 
03250    if (pds->username) {
03251       data = pds->username;
03252       pds->username = strsep(&data, ":");
03253       pds->password = data;
03254    }
03255 
03256    data = pds->peer;
03257    pds->peer = strsep(&data, ":");
03258    pds->port = data;
03259 
03260    /* check for a key name wrapped in [] in the secret position, if found,
03261       move it to the key field instead
03262    */
03263    if (pds->password && (pds->password[0] == '[')) {
03264       pds->key = ast_strip_quoted(pds->password, "[", "]");
03265       pds->password = NULL;
03266    }
03267 }

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

Note:
The only member of the peer passed here guaranteed to be set is the name field

Definition at line 1119 of file chan_iax2.c.

Referenced by load_module().

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

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

Definition at line 9794 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09795 {
09796    struct iax2_peer *peer = obj;
09797 
09798    ast_set_flag(peer, IAX_DELME);
09799 
09800    return 0;
09801 }

static void peer_destructor ( void *  obj  )  [static]

Definition at line 9327 of file chan_iax2.c.

References ast_dnsmgr_release(), ast_free_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_free_memory, iax2_peer::callno, iax2_peer::dnsmgr, iax2_peer::ha, iax2_destroy(), iaxsl, and register_peer_exten().

Referenced by build_peer().

09328 {
09329    struct iax2_peer *peer = obj;
09330    int callno = peer->callno;
09331 
09332    ast_free_ha(peer->ha);
09333 
09334    if (callno > 0) {
09335       ast_mutex_lock(&iaxsl[callno]);
09336       iax2_destroy(callno);
09337       ast_mutex_unlock(&iaxsl[callno]);
09338    }
09339 
09340    register_peer_exten(peer, 0);
09341 
09342    if (peer->dnsmgr)
09343       ast_dnsmgr_release(peer->dnsmgr);
09344 
09345    ast_string_field_free_memory(peer);
09346 }

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

Note:
The only member of the peer passed here guaranteed to be set is the name field

Definition at line 1109 of file chan_iax2.c.

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1166 of file chan_iax2.c.

References ao2_ref().

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

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

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

Definition at line 11095 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

11096 {
11097    struct iax2_peer *peer = obj;
11098 
11099    if (peer->sockfd < 0)
11100       peer->sockfd = defaultsockfd;
11101 
11102    return 0;
11103 }

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 9254 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, option_debug, outsock, socket_read(), iax2_peer::sockfd, and strsep().

Referenced by build_peer().

09255 {
09256    struct sockaddr_in sin;
09257    int nonlocal = 1;
09258    int port = IAX_DEFAULT_PORTNO;
09259    int sockfd = defaultsockfd;
09260    char *tmp;
09261    char *addr;
09262    char *portstr;
09263 
09264    if (!(tmp = ast_strdupa(srcaddr)))
09265       return -1;
09266 
09267    addr = strsep(&tmp, ":");
09268    portstr = tmp;
09269 
09270    if (portstr) {
09271       port = atoi(portstr);
09272       if (port < 1)
09273          port = IAX_DEFAULT_PORTNO;
09274    }
09275    
09276    if (!ast_get_ip(&sin, addr)) {
09277       struct ast_netsock *sock;
09278       int res;
09279 
09280       sin.sin_port = 0;
09281       sin.sin_family = AF_INET;
09282       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
09283       if (res == 0) {
09284          /* ip address valid. */
09285          sin.sin_port = htons(port);
09286          if (!(sock = ast_netsock_find(netsock, &sin)))
09287             sock = ast_netsock_find(outsock, &sin);
09288          if (sock) {
09289             sockfd = ast_netsock_sockfd(sock);
09290             nonlocal = 0;
09291          } else {
09292             unsigned int orig_saddr = sin.sin_addr.s_addr;
09293             /* INADDR_ANY matches anyway! */
09294             sin.sin_addr.s_addr = INADDR_ANY;
09295             if (ast_netsock_find(netsock, &sin)) {
09296                sin.sin_addr.s_addr = orig_saddr;
09297                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09298                if (sock) {
09299                   sockfd = ast_netsock_sockfd(sock);
09300                   ast_netsock_unref(sock);
09301                   nonlocal = 0;
09302                } else {
09303                   nonlocal = 2;
09304                }
09305             }
09306          }
09307       }
09308    }
09309       
09310    peer->sockfd = sockfd;
09311 
09312    if (nonlocal == 1) {
09313       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09314          srcaddr, peer->name);
09315       return -1;
09316         } else if (nonlocal == 2) {
09317       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09318          srcaddr, peer->name);
09319          return -1;
09320    } else {
09321       if (option_debug)
09322          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09323       return 0;
09324    }
09325 }

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

peer_status: Report Peer status in character string

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

02351 {
02352    int res = 0;
02353    if (peer->maxms) {
02354       if (peer->lastms < 0) {
02355          ast_copy_string(status, "UNREACHABLE", statuslen);
02356       } else if (peer->lastms > peer->maxms) {
02357          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02358          res = 1;
02359       } else if (peer->lastms) {
02360          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02361          res = 1;
02362       } else {
02363          ast_copy_string(status, "UNKNOWN", statuslen);
02364       }
02365    } else { 
02366       ast_copy_string(status, "Unmonitored", statuslen);
02367       res = -1;
02368    }
02369    return res;
02370 }

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

Definition at line 1172 of file chan_iax2.c.

References ao2_ref().

Referenced by __expire_registry(), __iax2_poke_noanswer(), __iax2_poke_peer_s(), __iax2_show_peers(), authenticate_reply(), build_peer(), complete_iax2_show_peer(), create_addr(), function_iaxpeer(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), iax2_show_peer(), poke_all_peers(), prune_peers(), reg_source_db(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().

01173 {
01174    ao2_ref(peer, -1);
01175    return NULL;
01176 }

static void poke_all_peers ( void   )  [static]

Definition at line 10256 of file chan_iax2.c.

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

Referenced by reload_config().

10257 {
10258    struct ao2_iterator i;
10259    struct iax2_peer *peer;
10260 
10261    i = ao2_iterator_init(peers, 0);
10262    while ((peer = ao2_iterator_next(&i))) {
10263       iax2_poke_peer(peer, 0);
10264       peer_unref(peer);
10265    }
10266 }

static void prune_peers ( void   )  [static]

Definition at line 9853 of file chan_iax2.c.

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

09854 {
09855    struct iax2_peer *peer;
09856    struct ao2_iterator i;
09857 
09858    i = ao2_iterator_init(peers, 0);
09859    while ((peer = ao2_iterator_next(&i))) {
09860       if (ast_test_flag(peer, IAX_DELME))
09861          unlink_peer(peer);
09862       peer_unref(peer);
09863    }
09864 }

static void prune_users ( void   )  [static]

Definition at line 9839 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ao2_unlink(), ast_test_flag, IAX_DELME, user_unref(), and users.

Referenced by reload_config().

09840 {
09841    struct iax2_user *user;
09842    struct ao2_iterator i;
09843 
09844    i = ao2_iterator_init(users, 0);
09845    while ((user = ao2_iterator_next(&i))) {
09846       if (ast_test_flag(user, IAX_DELME))
09847          ao2_unlink(users, user);
09848       user_unref(user);
09849    }
09850 }

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

Definition at line 11112 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

11113 {
11114    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
11115 
11116    /* The frames_received field is used to hold whether we're matching
11117     * against a full frame or not ... */
11118 
11119    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
11120       pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0;
11121 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1344 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_set_flag, ast_string_field_free_memory, ast_variables_destroy(), iax2_registry::callno, chan_iax2_pvt::callno, iax_frame::callno, jb_frame::data, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, iaxq, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, and chan_iax2_pvt::vars.

Referenced by new_iax().

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

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

Definition at line 11105 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

11106 {
11107    const struct chan_iax2_pvt *pvt = obj;
11108 
11109    return pvt->peercallno;
11110 }

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

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

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

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

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

Note:
If this one loaded something, then we need to ensure that the host field matched. The only reason why we can't have this as a criteria is because we only have the IP address and the host field might be set as a name (and the reverse PTR might not match).

Definition at line 2831 of file chan_iax2.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.

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

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

Definition at line 3024 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

03025 {
03026    char port[10];
03027    char regseconds[20];
03028    
03029    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
03030    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
03031    ast_update_realtime("iaxpeers", "name", peername, 
03032       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
03033       "regseconds", regseconds, NULL);
03034 }

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

Definition at line 2953 of file chan_iax2.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.

02954 {
02955    struct ast_variable *var;
02956    struct ast_variable *tmp;
02957    struct iax2_user *user=NULL;
02958 
02959    var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL);
02960    if (!var)
02961       var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02962    if (!var && sin) {
02963       char porta[6];
02964       snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port));
02965       var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02966       if (!var)
02967          var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02968    }
02969    if (!var) { /* Last ditch effort */
02970       var = ast_load_realtime("iaxusers", "name", username, NULL);
02971       /*!\note
02972        * If this one loaded something, then we need to ensure that the host
02973        * field matched.  The only reason why we can't have this as a criteria
02974        * is because we only have the IP address and the host field might be
02975        * set as a name (and the reverse PTR might not match).
02976        */
02977       if (var) {
02978          for (tmp = var; tmp; tmp = tmp->next) {
02979             if (!strcasecmp(tmp->name, "host")) {
02980                struct ast_hostent ahp;
02981                struct hostent *hp;
02982                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02983                   /* No match */
02984                   ast_variables_destroy(var);
02985                   var = NULL;
02986                }
02987                break;
02988             }
02989          }
02990       }
02991    }
02992    if (!var)
02993       return NULL;
02994 
02995    tmp = var;
02996    while(tmp) {
02997       /* Make sure it's not a peer only... */
02998       if (!strcasecmp(tmp->name, "type")) {
02999          if (strcasecmp(tmp->value, "friend") &&
03000              strcasecmp(tmp->value, "user")) {
03001             return NULL;
03002          } 
03003       }
03004       tmp = tmp->next;
03005    }
03006 
03007    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
03008 
03009    ast_variables_destroy(var);
03010 
03011    if (!user)
03012       return NULL;
03013 
03014    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
03015       ast_set_flag(user, IAX_RTCACHEFRIENDS);
03016       ao2_link(users, user);
03017    } else {
03018       ast_set_flag(user, IAX_TEMPONLY);   
03019    }
03020 
03021    return user;
03022 }

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 6126 of file chan_iax2.c.

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

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

06127 {
06128    char data[80];
06129    struct in_addr in;
06130    char *c, *d;
06131    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
06132       c = strchr(data, ':');
06133       if (c) {
06134          *c = '\0';
06135          c++;
06136          if (inet_aton(data, &in)) {
06137             d = strchr(c, ':');
06138             if (d) {
06139                *d = '\0';
06140                d++;
06141                if (option_verbose > 2)
06142                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
06143                   ast_inet_ntoa(in), atoi(c), atoi(d));
06144                iax2_poke_peer(p, 0);
06145                p->expiry = atoi(d);
06146                memset(&p->addr, 0, sizeof(p->addr));
06147                p->addr.sin_family = AF_INET;
06148                p->addr.sin_addr = in;
06149                p->addr.sin_port = htons(atoi(c));
06150                if (p->expire > -1) {
06151                   if (!ast_sched_del(sched, p->expire)) {
06152                      p->expire = -1;
06153                      peer_unref(p);
06154                   }
06155                }
06156                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06157                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06158                if (p->expire == -1)
06159                   peer_unref(p);
06160                if (iax2_regfunk)
06161                   iax2_regfunk(p->name, 1);
06162                register_peer_exten(p, 1);
06163             }              
06164                
06165          }
06166       }
06167    }
06168 }

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

Definition at line 6046 of file chan_iax2.c.

References ast_add_extension(), ast_context_remove_extension(), ast_exists_extension(), ast_free, ast_strdup, ast_strlen_zero(), ext, S_OR, and strsep().

Referenced by __expire_registry(), expire_register(), parse_register_contact(), peer_destructor(), reg_source_db(), sip_destroy_peer(), and update_registry().

06047 {
06048    char multi[256];
06049    char *stringp, *ext;
06050    if (!ast_strlen_zero(regcontext)) {
06051       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
06052       stringp = multi;
06053       while((ext = strsep(&stringp, "&"))) {
06054          if (onoff) {
06055             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
06056                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
06057                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
06058          } else
06059             ast_context_remove_extension(regcontext, ext, 1, NULL);
06060       }
06061    }
06062 }

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

Verify inbound registration.

Definition at line 5509 of file chan_iax2.c.

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

Referenced by handle_request_register(), and socket_process().

05510 {
05511    char requeststr[256] = "";
05512    char peer[256] = "";
05513    char md5secret[256] = "";
05514    char rsasecret[256] = "";
05515    char secret[256] = "";
05516    struct iax2_peer *p = NULL;
05517    struct ast_key *key;
05518    char *keyn;
05519    int x;
05520    int expire = 0;
05521    int res = -1;
05522 
05523    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
05524    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05525    if (ies->username)
05526       ast_copy_string(peer, ies->username, sizeof(peer));
05527    if (ies->password)
05528       ast_copy_string(secret, ies->password, sizeof(secret));
05529    if (ies->md5_result)
05530       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05531    if (ies->rsa_result)
05532       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05533    if (ies->refresh)
05534       expire = ies->refresh;
05535 
05536    if (ast_strlen_zero(peer)) {
05537       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05538       return -1;
05539    }
05540 
05541    /* SLD: first call to lookup peer during registration */
05542    ast_mutex_unlock(&iaxsl[callno]);
05543    p = find_peer(peer, 1);
05544    ast_mutex_lock(&iaxsl[callno]);
05545    if (!p || !iaxs[callno]) {
05546       if (authdebug && !p)
05547          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05548       goto return_unref;
05549    }
05550 
05551    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05552       if (authdebug)
05553          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05554       goto return_unref;
05555    }
05556 
05557    if (!ast_apply_ha(p->ha, sin)) {
05558       if (authdebug)
05559          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05560       goto return_unref;
05561    }
05562    if (!inaddrcmp(&p->addr, sin))
05563       ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
05564    ast_string_field_set(iaxs[callno], secret, p->secret);
05565    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05566    /* Check secret against what we have on file */
05567    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05568       if (!ast_strlen_zero(p->inkeys)) {
05569          char tmpkeys[256];
05570          char *stringp=NULL;
05571          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05572          stringp=tmpkeys;
05573          keyn = strsep(&stringp, ":");
05574          while(keyn) {
05575             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05576             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05577                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05578                break;
05579             } else if (!key) 
05580                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05581             keyn = strsep(&stringp, ":");
05582          }
05583          if (!keyn) {
05584             if (authdebug)
05585                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05586             goto return_unref;
05587          }
05588       } else {
05589          if (authdebug)
05590             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05591          goto return_unref;
05592       }
05593    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05594       struct MD5Context md5;
05595       unsigned char digest[16];
05596       char *tmppw, *stringp;
05597       
05598       tmppw = ast_strdupa(p->secret);
05599       stringp = tmppw;
05600       while((tmppw = strsep(&stringp, ";"))) {
05601          MD5Init(&md5);
05602          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05603          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05604          MD5Final(digest, &md5);
05605          for (x=0;x<16;x++)
05606             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05607          if (!strcasecmp(requeststr, md5secret)) 
05608             break;
05609       }
05610       if (tmppw) {
05611          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05612       } else {
05613          if (authdebug)
05614             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05615          goto return_unref;
05616       }
05617    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05618       /* They've provided a plain text password and we support that */
05619       if (strcmp(secret, p->secret)) {
05620          if (authdebug)
05621             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05622          goto return_unref;
05623       } else
05624          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05625    } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) {
05626       if (authdebug)
05627          ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
05628       goto return_unref;
05629    }
05630    ast_string_field_set(iaxs[callno], peer, peer);
05631    /* Choose lowest expiry number */
05632    if (expire && (expire < iaxs[callno]->expiry)) 
05633       iaxs[callno]->expiry = expire;
05634 
05635    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05636 
05637    res = 0;
05638 
05639 return_unref:
05640    if (p)
05641       peer_unref(p);
05642 
05643    return res;
05644 }

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6305 of file chan_iax2.c.

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

Referenced by socket_process().

06306 {
06307    struct iax_ie_data ied;
06308    struct iax2_peer *p;
06309    char challenge[10];
06310    const char *peer_name;
06311    int res = -1;
06312 
06313    peer_name = ast_strdupa(iaxs[callno]->peer);
06314 
06315    /* SLD: third call to find_peer in registration */
06316    ast_mutex_unlock(&iaxsl[callno]);
06317    p = find_peer(peer_name, 1);
06318    ast_mutex_lock(&iaxsl[callno]);
06319    if (!iaxs[callno])
06320       goto return_unref;
06321    if (!p) {
06322       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06323       goto return_unref;
06324    }
06325    
06326    memset(&ied, 0, sizeof(ied));
06327    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06328    if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06329       /* Build the challenge */
06330       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06331       ast_string_field_set(iaxs[callno], challenge, challenge);
06332       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06333    }
06334    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06335 
06336    res = 0;
06337 
06338 return_unref:
06339    peer_unref(p);
06340 
06341    return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
06342 }

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

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

06345 {
06346    struct iax2_registry *reg;
06347    /* Start pessimistic */
06348    struct iax_ie_data ied;
06349    char peer[256] = "";
06350    char challenge[256] = "";
06351    int res;
06352    int authmethods = 0;
06353    if (ies->authmethods)
06354       authmethods = ies->authmethods;
06355    if (ies->username)
06356       ast_copy_string(peer, ies->username, sizeof(peer));
06357    if (ies->challenge)
06358       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06359    memset(&ied, 0, sizeof(ied));
06360    reg = iaxs[callno]->reg;
06361    if (reg) {
06362          if (inaddrcmp(&reg->addr, sin)) {
06363             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06364             return -1;
06365          }
06366          if (ast_strlen_zero(reg->secret)) {
06367             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06368             reg->regstate = REG_STATE_NOAUTH;
06369             return -1;
06370          }
06371          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06372          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06373          if (reg->secret[0] == '[') {
06374             char tmpkey[256];
06375             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06376             tmpkey[strlen(tmpkey) - 1] = '\0';
06377             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
06378          } else
06379             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
06380          if (!res) {
06381             reg->regstate = REG_STATE_AUTHSENT;
06382             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06383          } else
06384             return -1;
06385          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06386    } else   
06387       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06388    return -1;
06389 }

static char* regstate2str ( int  regstate  )  [static]

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

04802 {
04803    switch(regstate) {
04804    case REG_STATE_UNREGISTERED:
04805       return "Unregistered";
04806    case REG_STATE_REGSENT:
04807       return "Request Sent";
04808    case REG_STATE_AUTHSENT:
04809       return "Auth. Sent";
04810    case REG_STATE_REGISTERED:
04811       return "Registered";
04812    case REG_STATE_REJECTED:
04813       return "Rejected";
04814    case REG_STATE_TIMEOUT:
04815       return "Timeout";
04816    case REG_STATE_NOAUTH:
04817       return "No Authentication";
04818    default:
04819       return "Unknown";
04820    }
04821 }

static int reload ( void   )  [static]

Definition at line 10293 of file chan_iax2.c.

References reload_config().

10294 {
10295    return reload_config();
10296 }

static int reload_config ( void   )  [static]

Definition at line 10267 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, iax2_do_register(), iax_provision_reload(), poke_all_peers(), prune_peers(), prune_users(), reload_firmware(), and set_config().

10268 {
10269    char *config = "iax.conf";
10270    struct iax2_registry *reg;
10271 
10272    if (set_config(config, 1) > 0) {
10273       prune_peers();
10274       prune_users();
10275       AST_LIST_LOCK(&registrations);
10276       AST_LIST_TRAVERSE(&registrations, reg, entry)
10277          iax2_do_register(reg);
10278       AST_LIST_UNLOCK(&registrations);
10279       /* Qualify hosts, too */
10280       poke_all_peers();
10281    }
10282    reload_firmware(0);
10283    iax_provision_reload();
10284 
10285    return 0;
10286 }

static void reload_firmware ( int  unload  )  [static]

Definition at line 1994 of file chan_iax2.c.

References ast_config_AST_DATA_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), iax_firmware::dead, destroy_firmware(), errno, ast_firmware_list::lock, LOG_WARNING, iax_firmware::next, option_verbose, try_firmware(), VERBOSE_PREFIX_2, ast_firmware_list::wares, and waresl.

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

01995 {
01996    struct iax_firmware *cur, *curl, *curp;
01997    DIR *fwd;
01998    struct dirent *de;
01999    char dir[256];
02000    char fn[256];
02001    /* Mark all as dead */
02002    ast_mutex_lock(&waresl.lock);
02003    cur = waresl.wares;
02004    while(cur) {
02005       cur->dead = 1;
02006       cur = cur->next;
02007    }
02008 
02009    /* Now that we've freed them, load the new ones */
02010    if (!unload) {
02011       snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
02012       fwd = opendir(dir);
02013       if (fwd) {
02014          while((de = readdir(fwd))) {
02015             if (de->d_name[0] != '.') {
02016                snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
02017                if (!try_firmware(fn)) {
02018                   if (option_verbose > 1)
02019                      ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
02020                }
02021             }
02022          }
02023          closedir(fwd);
02024       } else 
02025          ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
02026    }
02027 
02028    /* Clean up leftovers */
02029    cur = waresl.wares;
02030    curp = NULL;
02031    while(cur) {
02032       curl = cur;
02033       cur = cur->next;
02034       if (curl->dead) {
02035          if (curp) {
02036             curp->next = cur;
02037          } else {
02038             waresl.wares = cur;
02039          }
02040          destroy_firmware(curl);
02041       } else {
02042          curp = cur;
02043       }
02044    }
02045    ast_mutex_unlock(&waresl.lock);
02046 }

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1257 of file chan_iax2.c.

References ao2_unlink(), ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.

Referenced by complete_transfer(), iax2_destroy(), and socket_process().

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

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

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

06849 {
06850    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06851    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06852    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06853    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06854    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06855    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06856    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06857 }

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

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

Referenced by start_network_thread().

09078 {
09079    int count;
09080    int res;
09081    struct timeval tv;
09082    struct timespec ts;
09083 
09084    for (;;) {
09085       pthread_testcancel();
09086       ast_mutex_lock(&sched_lock);
09087       res = ast_sched_wait(sched);
09088       if ((res > 1000) || (res < 0))
09089          res = 1000;
09090       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
09091       ts.tv_sec = tv.tv_sec;
09092       ts.tv_nsec = tv.tv_usec * 1000;
09093       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
09094       ast_mutex_unlock(&sched_lock);
09095       pthread_testcancel();
09096 
09097       count = ast_sched_runq(sched);
09098       if (option_debug && count >= 20)
09099          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
09100    }
09101    return NULL;
09102 }

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

Note:
This function assumes fr->callno is locked

IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it.

Definition at line 2684 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, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, len, LOG_DEBUG, option_debug, ast_channel_tech::properties, sched, ast_channel::tech, iax_frame::ts, type, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

02685 {
02686    int type, len;
02687    int ret;
02688    int needfree = 0;
02689    struct ast_channel *owner = NULL;
02690    struct ast_channel *bridge = NULL;
02691    
02692    /* Attempt to recover wrapped timestamps */
02693    unwrap_timestamp(fr);
02694 
02695    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02696    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02697       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02698    else {
02699 #if 0
02700       if (option_debug)
02701          ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02702 #endif
02703       fr->af.delivery = ast_tv(0,0);
02704    }
02705 
02706    type = JB_TYPE_CONTROL;
02707    len = 0;
02708 
02709    if(fr->af.frametype == AST_FRAME_VOICE) {
02710       type = JB_TYPE_VOICE;
02711       len = ast_codec_get_samples(&fr->af) / 8;
02712    } else if(fr->af.frametype == AST_FRAME_CNG) {
02713       type = JB_TYPE_SILENCE;
02714    }
02715 
02716    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02717       if (tsout)
02718          *tsout = fr->ts;
02719       __do_deliver(fr);
02720       return -1;
02721    }
02722 
02723    if ((owner = iaxs[fr->callno]->owner))
02724       bridge = ast_bridged_channel(owner);
02725 
02726    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02727     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02728    if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
02729       jb_frame frame;
02730 
02731       /* deliver any frames in the jb */
02732       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
02733          __do_deliver(frame.data);
02734          /* __do_deliver() can make the call disappear */
02735          if (!iaxs[fr->callno])
02736             return -1;
02737       }
02738 
02739       jb_reset(iaxs[fr->callno]->jb);
02740 
02741       AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
02742 
02743       /* deliver this frame now */
02744       if (tsout)
02745          *tsout = fr->ts;
02746       __do_deliver(fr);
02747       return -1;
02748    }
02749 
02750    /* insert into jitterbuffer */
02751    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02752    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02753          calc_rxstamp(iaxs[fr->callno],fr->ts));
02754    if (ret == JB_DROP) {
02755       needfree++;
02756    } else if (ret == JB_SCHED) {
02757       update_jbsched(iaxs[fr->callno]);
02758    }
02759    if (tsout)
02760       *tsout = fr->ts;
02761    if (needfree) {
02762       /* Free our iax frame */
02763       iax2_frame_free(fr);
02764       return -1;
02765    }
02766    return 0;
02767 }

static int send_apathetic_reply ( unsigned short  callno,
unsigned short  dcallno,
struct sockaddr_in *  sin,
int  command,
int  ts,
unsigned char  seqno 
) [static]

Definition at line 3202 of file chan_iax2.c.

References AST_FRAME_IAX, compress_subclass(), and f.

Referenced by socket_process().

03203 {
03204    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03205       .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX,
03206       .csub = compress_subclass(command) };
03207 
03208    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03209 }

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

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

05086 {
05087    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
05088 }

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

Note:
Since this function calls iax2_predestroy() -> iax2_queue_hangup(), the pvt struct for the given call number may disappear during its execution.

Definition at line 5104 of file chan_iax2.c.

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

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

05105 {
05106    int call_num = i->callno;
05107    /* It is assumed that the callno has already been locked */
05108    iax2_predestroy(i->callno);
05109    if (!iaxs[call_num])
05110       return -1;
05111    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05112 }

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

Definition at line 5114 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05115 {
05116    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05117 }

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

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

05091 {
05092    int res;
05093    ast_mutex_lock(&iaxsl[callno]);
05094    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05095    ast_mutex_unlock(&iaxsl[callno]);
05096    return res;
05097 }

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

Definition at line 5119 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

05120 {
05121    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05122 }

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

Definition at line 1062 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

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

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 2119 of file chan_iax2.c.

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

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

02120 {
02121    int res;
02122    int callno = f->callno;
02123 
02124    /* Don't send if there was an error, but return error instead */
02125    if (!callno || !iaxs[callno] || iaxs[callno]->error)
02126        return -1;
02127    
02128    /* Called with iaxsl held */
02129    if (option_debug > 2 && iaxdebug)
02130       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));
02131    if (f->transfer) {
02132       if (iaxdebug)
02133          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
02134       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
02135                sizeof(iaxs[callno]->transfer));
02136    } else {
02137       if (iaxdebug)
02138          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
02139       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
02140                sizeof(iaxs[callno]->addr));
02141    }
02142    if (res < 0) {
02143       if (option_debug && iaxdebug)
02144          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02145       handle_error();
02146    } else
02147       res = 0;
02148    return res;
02149 }

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

Definition at line 1017 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

01018 {
01019 #ifdef SCHED_MULTITHREADED
01020    if (schedule_action(__send_ping, data))
01021 #endif      
01022       __send_ping(data);
01023 
01024    return 0;
01025 }

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

Definition at line 6526 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, option_debug, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.

Referenced by timing_read().

06527 {
06528    int res = 0;
06529    struct iax_frame *fr;
06530    struct ast_iax2_meta_hdr *meta;
06531    struct ast_iax2_meta_trunk_hdr *mth;
06532    int calls = 0;
06533    
06534    /* Point to frame */
06535    fr = (struct iax_frame *)tpeer->trunkdata;
06536    /* Point to meta data */
06537    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06538    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06539    if (tpeer->trunkdatalen) {
06540       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06541       meta->zeros = 0;
06542       meta->metacmd = IAX_META_TRUNK;
06543       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06544          meta->cmddata = IAX_META_TRUNK_MINI;
06545       else
06546          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06547       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06548       /* And the rest of the ast_iax2 header */
06549       fr->direction = DIRECTION_OUTGRESS;
06550       fr->retrans = -1;
06551       fr->transfer = 0;
06552       /* Any appropriate call will do */
06553       fr->data = fr->afdata;
06554       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06555       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06556       calls = tpeer->calls;
06557 #if 0
06558       if (option_debug)
06559          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));
06560 #endif      
06561       /* Reset transmit trunk side data */
06562       tpeer->trunkdatalen = 0;
06563       tpeer->calls = 0;
06564    }
06565    if (res < 0)
06566       return res;
06567    return calls;
06568 }

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

Load configuration.

Definition at line 9897 of file chan_iax2.c.

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

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

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

static void set_config_destroy ( void   )  [static]

Definition at line 9881 of file chan_iax2.c.

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

Referenced by set_config().

09882 {
09883    strcpy(accountcode, "");
09884    strcpy(language, "");
09885    strcpy(mohinterpret, "default");
09886    strcpy(mohsuggest, "");
09887    amaflags = 0;
09888    delayreject = 0;
09889    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09890    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09891    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09892    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09893    delete_users();
09894 }

static void set_timing ( void   )  [static]

Definition at line 9866 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09867 {
09868 #ifdef HAVE_DAHDI
09869    int bs = trunkfreq * 8;
09870    if (timingfd > -1) {
09871       if (
09872 #ifdef DAHDI_TIMERACK
09873          ioctl(timingfd, DAHDI_TIMERCONFIG, &bs) &&
09874 #endif         
09875          ioctl(timingfd, DAHDI_SET_BLOCKSIZE, &bs))
09876          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09877    }
09878 #endif
09879 }

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

Definition at line 755 of file chan_iax2.c.

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

Referenced by __schedule_action(), iax2_sched_add(), iax2_transmit(), and socket_read().

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

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 7000 of file chan_iax2.c.

References ast_async_goto(), ast_best_codec(), ast_bridged_channel(), AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_device_state_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_parking_ext(), ast_sched_del(), AST_SCHED_DEL, ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax2_peer::callno, iax2_dpcache::callno, iax_frame::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, check_access(), check_provisioning(), cid_num, complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, DEADLOCK_AVOIDANCE, decrypt_frame(), dp_lookup(), EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), find_callno_locked(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, format, chan_iax2_pvt::frames_received, ast_frame::frametype, globalflags, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_vnak(), IAX_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iaxfrdup2(), iaxq, iaxs, iaxsl, ies, inaddrcmp(), chan_iax2_pvt::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_iax2_meta_trunk_mini::len, len, 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, pbx_builtin_setvar_helper(), iax2_dpcache::peer, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, raw_hangup(), REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, save_rr(), sched, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax2_peer::smoothing, spawn_dp_lookup(), stop_stuff(), store_by_peercallno(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), iax_frame::ts, ast_iax2_mini_hdr::ts, uncompress_subclass(), update_registry(), VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.

Referenced by handle_deferred_full_frames().

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

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

Definition at line 6922 of file chan_iax2.c.

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

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

06923 {
06924    struct iax2_thread *thread;
06925    socklen_t len;
06926    time_t t;
06927    static time_t last_errtime = 0;
06928    struct ast_iax2_full_hdr *fh;
06929 
06930    if (!(thread = find_idle_thread())) {
06931       time(&t);
06932       if (t != last_errtime && option_debug)
06933          ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n");
06934       last_errtime = t;
06935       usleep(1);
06936       return 1;
06937    }
06938 
06939    len = sizeof(thread->iosin);
06940    thread->iofd = fd;
06941    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06942    thread->buf_size = sizeof(thread->readbuf);
06943    thread->buf = thread->readbuf;
06944    if (thread->buf_len < 0) {
06945       if (errno != ECONNREFUSED && errno != EAGAIN)
06946          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06947       handle_error();
06948       thread->iostate = IAX_IOSTATE_IDLE;
06949       signal_condition(&thread->lock, &thread->cond);
06950       return 1;
06951    }
06952    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06953       thread->iostate = IAX_IOSTATE_IDLE;
06954       signal_condition(&thread->lock, &thread->cond);
06955       return 1;
06956    }
06957    
06958    /* Determine if this frame is a full frame; if so, and any thread is currently
06959       processing a full frame for the same callno from this peer, then drop this
06960       frame (and the peer will retransmit it) */
06961    fh = (struct ast_iax2_full_hdr *) thread->buf;
06962    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06963       struct iax2_thread *cur = NULL;
06964       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06965       
06966       AST_LIST_LOCK(&active_list);
06967       AST_LIST_TRAVERSE(&active_list, cur, list) {
06968          if ((cur->ffinfo.callno == callno) &&
06969              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06970             break;
06971       }
06972       if (cur) {
06973          /* we found another thread processing a full frame for this call,
06974             so queue it up for processing later. */
06975          defer_full_frame(thread, cur);
06976          AST_LIST_UNLOCK(&active_list);
06977          thread->iostate = IAX_IOSTATE_IDLE;
06978          signal_condition(&thread->lock, &thread->cond);
06979          return 1;
06980       } else {
06981          /* this thread is going to process this frame, so mark it */
06982          thread->ffinfo.callno = callno;
06983          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
06984          thread->ffinfo.type = fh->type;
06985          thread->ffinfo.csub = fh->csub;
06986       }
06987       AST_LIST_UNLOCK(&active_list);
06988    }
06989    
06990    /* Mark as ready and send on its way */
06991    thread->iostate = IAX_IOSTATE_READY;
06992 #ifdef DEBUG_SCHED_MULTITHREAD
06993    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06994 #endif
06995    signal_condition(&thread->lock, &thread->cond);
06996 
06997    return 1;
06998 }

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

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

06710 {
06711    pthread_t newthread;
06712    struct dpreq_data *dpr;
06713    pthread_attr_t attr;
06714    
06715    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06716       return;
06717 
06718    pthread_attr_init(&attr);
06719    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06720 
06721    dpr->callno = callno;
06722    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06723    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06724    if (callerid)
06725       dpr->callerid = ast_strdup(callerid);
06726    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06727       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06728    }
06729 
06730    pthread_attr_destroy(&attr);
06731 }

static int start_network_thread ( void   )  [static]

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

09172 {
09173    pthread_attr_t attr;
09174    int threadcount = 0;
09175    int x;
09176    for (x = 0; x < iaxthreadcount; x++) {
09177       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
09178       if (thread) {
09179          thread->type = IAX_TYPE_POOL;
09180          thread->threadnum = ++threadcount;
09181          ast_mutex_init(&thread->lock);
09182          ast_cond_init(&thread->cond, NULL);
09183          pthread_attr_init(&attr);
09184          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
09185          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
09186             ast_log(LOG_WARNING, "Failed to create new thread!\n");
09187             free(thread);
09188             thread = NULL;
09189          }
09190          AST_LIST_LOCK(&idle_list);
09191          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
09192          AST_LIST_UNLOCK(&idle_list);
09193       }
09194    }
09195    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
09196    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
09197    if (option_verbose > 1)
09198       ast_verbose(VERBOSE_PREFIX_2 "%d helper threads started\n", threadcount);
09199    return 0;
09200 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6391 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06392 {
06393    iax2_destroy_helper(iaxs[callno]);
06394 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1247 of file chan_iax2.c.

References ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.

Referenced by __find_callno(), complete_transfer(), and socket_process().

01248 {
01249    if (!pvt->peercallno) {
01250       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01251       return;
01252    }
01253 
01254    ao2_link(iax_peercallno_pvts, pvt);
01255 }

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

Definition at line 6578 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, option_debug, send_trunk(), tpeers, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.

Referenced by network_thread().

06579 {
06580    char buf[1024];
06581    int res;
06582    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06583    int processed = 0;
06584    int totalcalls = 0;
06585 #ifdef DAHDI_TIMERACK
06586    int x = 1;
06587 #endif
06588    struct timeval now;
06589    if (iaxtrunkdebug)
06590       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06591    gettimeofday(&now, NULL);
06592    if (events & AST_IO_PRI) {
06593 #ifdef DAHDI_TIMERACK
06594       /* Great, this is a timing interface, just call the ioctl */
06595       if (ioctl(fd, DAHDI_TIMERACK, &x)) {
06596          ast_log(LOG_WARNING, "Unable to acknowledge timer. IAX trunking will fail!\n");
06597          usleep(1);
06598          return -1;
06599       }
06600 #endif      
06601    } else {
06602       /* Read and ignore from the pseudo channel for timing */
06603       res = read(fd, buf, sizeof(buf));
06604       if (res < 1) {
06605          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06606          return 1;
06607       }
06608    }
06609    /* For each peer that supports trunking... */
06610    ast_mutex_lock(&tpeerlock);
06611    tpeer = tpeers;
06612    while(tpeer) {
06613       processed++;
06614       res = 0;
06615       ast_mutex_lock(&tpeer->lock);
06616       /* We can drop a single tpeer per pass.  That makes all this logic
06617          substantially easier */
06618       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06619          /* Take it out of the list, but don't free it yet, because it
06620             could be in use */
06621          if (prev)
06622             prev->next = tpeer->next;
06623          else
06624             tpeers = tpeer->next;
06625          drop = tpeer;
06626       } else {
06627          res = send_trunk(tpeer, &now);
06628          if (iaxtrunkdebug)
06629             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);
06630       }     
06631       totalcalls += res;   
06632       res = 0;
06633       ast_mutex_unlock(&tpeer->lock);
06634       prev = tpeer;
06635       tpeer = tpeer->next;
06636    }
06637    ast_mutex_unlock(&tpeerlock);
06638    if (drop) {
06639       ast_mutex_lock(&drop->lock);
06640       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06641          because by the time they could get tpeerlock, we've already grabbed it */
06642       if (option_debug)
06643          ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06644       if (drop->trunkdata) {
06645          free(drop->trunkdata);
06646          drop->trunkdata = NULL;
06647       }
06648       ast_mutex_unlock(&drop->lock);
06649       ast_mutex_destroy(&drop->lock);
06650       free(drop);
06651       
06652    }
06653    if (iaxtrunkdebug)
06654       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06655    iaxtrunkdebug =0;
06656    return 1;
06657 }

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

Definition at line 2105 of file chan_iax2.c.

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

Referenced by send_trunk().

02106 {
02107    int res;
02108    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
02109                sizeof(*sin));
02110    if (res < 0) {
02111       if (option_debug)
02112          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02113       handle_error();
02114    } else
02115       res = 0;
02116    return res;
02117 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1793 of file chan_iax2.c.

References ast_calloc, ast_log(), ast_random(), ast_strlen_zero(), MD5Context::buf, ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, errno, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, len, LOG_WARNING, 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().

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

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

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

05794 {
05795    int newcall = 0;
05796    char newip[256];
05797    struct iax_ie_data ied;
05798    struct sockaddr_in new;
05799    
05800    
05801    memset(&ied, 0, sizeof(ied));
05802    if (ies->apparent_addr)
05803       bcopy(ies->apparent_addr, &new, sizeof(new));
05804    if (ies->callno)
05805       newcall = ies->callno;
05806    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05807       ast_log(LOG_WARNING, "Invalid transfer request\n");
05808       return -1;
05809    }
05810    pvt->transfercallno = newcall;
05811    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05812    inet_aton(newip, &pvt->transfer.sin_addr);
05813    pvt->transfer.sin_family = AF_INET;
05814    pvt->transferring = TRANSFER_BEGIN;
05815    pvt->transferid = ies->transferid;
05816    if (ies->transferid)
05817       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05818    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05819    return 0; 
05820 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1092 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

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

static void unlink_peer ( struct iax2_peer peer  )  [static]

Definition at line 6065 of file chan_iax2.c.

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

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

06066 {
06067    if (peer->expire > -1) {
06068       if (!ast_sched_del(sched, peer->expire)) {
06069          peer->expire = -1;
06070          peer_unref(peer);
06071       }
06072    }
06073 
06074    if (peer->pokeexpire > -1) {
06075       if (!ast_sched_del(sched, peer->pokeexpire)) {
06076          peer->pokeexpire = -1;
06077          peer_unref(peer);
06078       }
06079    }
06080 
06081    ao2_unlink(peers, peer);
06082 }

static int unload_module ( void   )  [static]

Definition at line 11089 of file chan_iax2.c.

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

11090 {
11091    ast_custom_function_unregister(&iaxpeer_function);
11092    return __unload_module();
11093 }

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

Definition at line 3522 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03523 {
03524    ast_mutex_unlock(&iaxsl[callno1]);
03525    ast_mutex_unlock(&iaxsl[callno0]);
03526 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

Definition at line 2539 of file chan_iax2.c.

References iax_frame::af, AST_FRAME_VIDEO, ast_log(), iax_frame::callno, ast_frame::frametype, iaxs, chan_iax2_pvt::last, LOG_DEBUG, option_debug, and iax_frame::ts.

Referenced by schedule_delivery().

02540 {
02541    /* Video mini frames only encode the lower 15 bits of the session
02542     * timestamp, but other frame types (e.g. audio) encode 16 bits. */
02543    const int ts_shift = (fr->af.frametype == AST_FRAME_VIDEO) ? 15 : 16;
02544    const int lower_mask = (1 << ts_shift) - 1;
02545    const int upper_mask = ~lower_mask;
02546    const int last_upper = iaxs[fr->callno]->last & upper_mask;
02547 
02548    if ( (fr->ts & upper_mask) == last_upper ) {
02549       const int x = fr->ts - iaxs[fr->callno]->last;
02550       const int threshold = (ts_shift == 15) ? 25000 : 50000;
02551 
02552       if (x < -threshold) {
02553          /* Sudden big jump backwards in timestamp:
02554             What likely happened here is that miniframe timestamp has circled but we haven't
02555             gotten the update from the main packet.  We'll just pretend that we did, and
02556             update the timestamp appropriately. */
02557          fr->ts = (last_upper + (1 << ts_shift)) | (fr->ts & lower_mask);
02558          if (option_debug && iaxdebug)
02559             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02560       } else if (x > threshold) {
02561          /* Sudden apparent big jump forwards in timestamp:
02562             What's likely happened is this is an old miniframe belonging to the previous
02563             top 15 or 16-bit timestamp that has turned up out of order.
02564             Adjust the timestamp appropriately. */
02565          fr->ts = (last_upper - (1 << ts_shift)) | (fr->ts & lower_mask);
02566          if (option_debug && iaxdebug)
02567             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02568       }
02569    }
02570 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2574 of file chan_iax2.c.

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

Referenced by __get_from_jb(), and schedule_delivery().

02575 {
02576    int when;
02577    
02578    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02579    
02580    when = jb_next(pvt->jb) - when;
02581 
02582    AST_SCHED_DEL(sched, pvt->jbid);
02583 
02584    if(when <= 0) {
02585       /* XXX should really just empty until when > 0.. */
02586       when = 1;
02587    }
02588    
02589    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02590 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1462 of file chan_iax2.c.

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

Referenced by __find_callno(), and make_trunk().

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

static void update_max_trunk ( void   )  [static]

Definition at line 1267 of file chan_iax2.c.

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

Referenced by iax2_destroy(), and make_trunk().

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

static int update_packet ( struct iax_frame f  )  [static]

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

02177 {
02178    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02179    struct ast_iax2_full_hdr *fh = f->data;
02180    /* Mark this as a retransmission */
02181    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02182    /* Update iseqno */
02183    f->iseqno = iaxs[f->callno]->iseqno;
02184    fh->iseqno = f->iseqno;
02185    return 0;
02186 }

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

Precondition:
iaxsl[callno] is locked
Note:
Since this function calls send_command_final(), the pvt struct for the given call number may disappear while executing this function.

Definition at line 6176 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Note:
The only member of the user passed here guaranteed to be set is the name field

Definition at line 1139 of file chan_iax2.c.

Referenced by load_module().

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

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

Definition at line 9803 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09804 {
09805    struct iax2_user *user = obj;
09806 
09807    ast_set_flag(user, IAX_DELME);
09808 
09809    return 0;
09810 }

static void user_destructor ( void *  obj  )  [static]

Definition at line 9567 of file chan_iax2.c.

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

Referenced by build_user().

09568 {
09569    struct iax2_user *user = obj;
09570 
09571    ast_free_ha(user->ha);
09572    free_context(user->contexts);
09573    if(user->vars) {
09574       ast_variables_destroy(user->vars);
09575       user->vars = NULL;
09576    }
09577    ast_string_field_free_memory(user);
09578 }

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

Note:
The only member of the user passed here guaranteed to be set is the name field

Definition at line 1129 of file chan_iax2.c.

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1178 of file chan_iax2.c.

References ao2_ref().

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

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

Definition at line 1184 of file chan_iax2.c.

References ao2_ref().

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

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

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

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

06493 {
06494    struct iax_frame *f;
06495 
06496    AST_LIST_LOCK(&iaxq.queue);
06497    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06498       /* Send a copy immediately */
06499       if ((f->callno == callno) && iaxs[f->callno] &&
06500          ((unsigned char ) (f->oseqno - last) < 128) &&
06501          (f->retries >= 0)) {
06502          send_packet(f);
06503       }
06504    }
06505    AST_LIST_UNLOCK(&iaxq.queue);
06506 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 215 of file chan_iax2.c.

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

int adsi = 0 [static]

Definition at line 219 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

Definition at line 218 of file chan_iax2.c.

Referenced by build_device(), and build_gateway().

int authdebug = 1 [static]

Definition at line 155 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 156 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10905 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 10885 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 10890 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 10900 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 10895 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 10880 of file chan_iax2.c.

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

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

int defaultsockfd = -1 [static]

Definition at line 172 of file chan_iax2.c.

int delayreject = 0 [static]

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

struct ast_flags globalflags = { 0 } [static]

Definition at line 223 of file chan_iax2.c.

Referenced by __expire_registry(), __find_callno(), aji_create_client(), aji_load_config(), build_peer(), build_user(), 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(), send_trunk(), sendmail(), set_config(), set_config_destroy(), socket_process(), update_registry(), and vm_execmain().

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 201 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 221 of file chan_iax2.c.

enum { ... } iax2_flags

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

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

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10770 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

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

struct ao2_container* iax_peercallno_pvts [static]

Another container of iax2_pvt structures.

Active IAX2 pvt structs are also stored in this container, if they are a part of an active call where we know the remote side's call number. The reason for this is that incoming media frames do not contain our call number. So, instead of having to iterate the entire iaxs array, we use this container to look up calls where the remote side is using a given call number.

Definition at line 823 of file chan_iax2.c.

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

int iaxactivethreadcount = 0 [static]

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

int iaxdebug = 0 [static]

Definition at line 203 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 159 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 161 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 449 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxdynamicthreadnum = 0 [static]

Definition at line 450 of file chan_iax2.c.

Referenced by find_idle_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 448 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 10706 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_show_stats(), iax2_transmit(), load_module(), network_thread(), pvt_destructor(), socket_process(), and vnak_retransmit().

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

Definition at line 810 of file chan_iax2.c.

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

ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static]

Definition at line 811 of file chan_iax2.c.

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

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 447 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 205 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 198 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 150 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 144 of file chan_iax2.c.

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

Definition at line 812 of file chan_iax2.c.

int max_reg_expire [static]

Definition at line 166 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 148 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 147 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 151 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 153 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 830 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_nontrunk().

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 829 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_trunk().

int min_reg_expire [static]

Definition at line 165 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 216 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

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

char no_debug_jb_usage[] [static]

Initial value:

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

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

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 171 of file chan_iax2.c.

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

char* papp = "IAX2Provision" [static]

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

struct ao2_container* peers [static]

Definition at line 648 of file chan_iax2.c.

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

int ping_time = 21 [static]

Definition at line 149 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

Definition at line 138 of file chan_iax2.c.

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

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10792 of file chan_iax2.c.

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

Definition at line 8820 of file chan_iax2.c.

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 145 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 152 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 199 of file chan_iax2.c.

ast_cond_t sched_cond [static]

Definition at line 228 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 226 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 10784 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 10812 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 10830 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 10816 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 10788 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 10824 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10800 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 10834 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 10780 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 10820 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 10807 of file chan_iax2.c.

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

Definition at line 140 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 207 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 168 of file chan_iax2.c.

unsigned int tos = 0 [static]

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

struct ao2_container* users [static]

Definition at line 651 of file chan_iax2.c.

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

struct ast_firmware_list waresl [static]

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


Generated on Mon Nov 24 15:34:30 2008 for Asterisk - the Open Source PBX by  doxygen 1.4.7