Thu Oct 8 21:56:13 2009

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) }
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 iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT
struct 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 int last_authmethod = 0
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 666 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 662 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 676 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 664 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 668 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 670 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

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

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 126 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 114 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 134 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 132 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

Definition at line 200 of file chan_iax2.c.

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

#define DEFAULT_FREQ_OK   60 * 1000

Definition at line 199 of file chan_iax2.c.

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 198 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 130 of file chan_iax2.c.

Referenced by __find_callno(), and complete_transfer().

#define DEFAULT_THREAD_COUNT   10

Definition at line 128 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

Definition at line 442 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define FORMAT   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n"

#define FORMAT   "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n"

#define FORMAT   "%-15.15s %-15d %-15d\n"

#define FORMAT   "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s"

#define FORMAT   "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n"

#define FORMAT2   "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n"

#define FORMAT2   "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n"

#define FORMAT2   "%-15.15s %-15.15s %-15.15s\n"

#define FORMAT2   "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s"

#define FORMAT2   "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n"

#define FORMATB   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n"

#define GAMMA   (0.01)

Definition at line 139 of file chan_iax2.c.

#define IAX2_TRUNK_PREFACE   (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))

Definition at line 363 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 181 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 189 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 194 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 183 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 697 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 699 of file chan_iax2.c.

Referenced by iax2_process_thread().

#define IAX_IOSTATE_READY   1

Definition at line 698 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 700 of file chan_iax2.c.

Referenced by __schedule_action(), and iax2_process_thread().

#define IAX_TYPE_DYNAMIC   2

#define IAX_TYPE_POOL   1

Definition at line 702 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 117 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 439 of file chan_iax2.c.

#define MAX_PEER_BUCKETS   1

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

Definition at line 648 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

Definition at line 437 of file chan_iax2.c.

Referenced by __attempt_transmit(), and iax2_send().

#define MAX_TIMESTAMP_SKEW   160

maximum difference between actual and predicted ts for sending

Definition at line 445 of file chan_iax2.c.

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 443 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 653 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 131 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 440 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 436 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 136 of file chan_iax2.c.

Referenced by __find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1430 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

#define NEW_PREVENT   0

Definition at line 1429 of file chan_iax2.c.

Referenced by socket_process().

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

#define SCHED_MULTITHREADED

Definition at line 110 of file chan_iax2.c.

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

#define TRUNK_CALL_START   ARRAY_LEN(iaxs) / 2

Definition at line 830 of file chan_iax2.c.

Referenced by __find_callno(), make_trunk(), update_max_nontrunk(), and update_max_trunk().

#define TS_GAP_FOR_JB_RESYNC   5000

Definition at line 448 of file chan_iax2.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
IAX_STATE_STARTED 
IAX_STATE_AUTHENTICATED 
IAX_STATE_TBD 

Definition at line 234 of file chan_iax2.c.

00234      {
00235    IAX_STATE_STARTED =        (1 << 0),
00236    IAX_STATE_AUTHENTICATED =  (1 << 1),
00237    IAX_STATE_TBD =            (1 << 2),
00238 } 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 245 of file chan_iax2.c.

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

Enumerator:
REG_STATE_UNREGISTERED 
REG_STATE_REGSENT 
REG_STATE_AUTHSENT 
REG_STATE_REGISTERED 
REG_STATE_REJECTED 
REG_STATE_TIMEOUT 
REG_STATE_NOAUTH 

Definition at line 394 of file chan_iax2.c.

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

Definition at line 404 of file chan_iax2.c.


Function Documentation

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

Definition at line 2150 of file chan_iax2.c.

References chan_iax2_pvt::addr, iax_frame::af, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, iax2_registry::callno, chan_iax2_pvt::error, f, iax_frame::final, 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, iax_frame::oseqno, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_command(), send_packet(), ast_frame::subclass, iax_frame::transfer, iax_frame::ts, update_packet(), and iax2_registry::us.

Referenced by attempt_transmit().

02151 {
02152    /* Attempt to transmit the frame to the remote peer...
02153       Called without iaxsl held. */
02154    struct iax_frame *f = (struct iax_frame *)data;
02155    int freeme=0;
02156    int callno = f->callno;
02157    /* Make sure this call is still active */
02158    if (callno) 
02159       ast_mutex_lock(&iaxsl[callno]);
02160    if (callno && iaxs[callno]) {
02161       if ((f->retries < 0) /* Already ACK'd */ ||
02162           (f->retries >= max_retries) /* Too many attempts */) {
02163             /* Record an error if we've transmitted too many times */
02164             if (f->retries >= max_retries) {
02165                if (f->transfer) {
02166                   /* Transfer timeout */
02167                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
02168                } else if (f->final) {
02169                   if (f->final) 
02170                      iax2_destroy(callno);
02171                } else {
02172                   if (iaxs[callno]->owner)
02173                      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);
02174                   iaxs[callno]->error = ETIMEDOUT;
02175                   if (iaxs[callno]->owner) {
02176                      struct ast_frame fr = { 0, };
02177                      /* Hangup the fd */
02178                      fr.frametype = AST_FRAME_CONTROL;
02179                      fr.subclass = AST_CONTROL_HANGUP;
02180                      iax2_queue_frame(callno, &fr); // XXX
02181                      /* Remember, owner could disappear */
02182                      if (iaxs[callno] && iaxs[callno]->owner)
02183                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
02184                   } else {
02185                      if (iaxs[callno]->reg) {
02186                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
02187                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
02188                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
02189                      }
02190                      iax2_destroy(callno);
02191                   }
02192                }
02193 
02194             }
02195             freeme++;
02196       } else {
02197          /* Update it if it needs it */
02198          update_packet(f);
02199          /* Attempt transmission */
02200          send_packet(f);
02201          f->retries++;
02202          /* Try again later after 10 times as long */
02203          f->retrytime *= 10;
02204          if (f->retrytime > MAX_RETRY_TIME)
02205             f->retrytime = MAX_RETRY_TIME;
02206          /* Transfer messages max out at one second */
02207          if (f->transfer && (f->retrytime > 1000))
02208             f->retrytime = 1000;
02209          f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
02210       }
02211    } else {
02212       /* Make sure it gets freed */
02213       f->retries = -1;
02214       freeme++;
02215    }
02216    if (callno)
02217       ast_mutex_unlock(&iaxsl[callno]);
02218    /* Do not try again */
02219    if (freeme) {
02220       /* Don't attempt delivery, just remove it from the queue */
02221       AST_LIST_LOCK(&iaxq.queue);
02222       AST_LIST_REMOVE(&iaxq.queue, f, list);
02223       iaxq.count--;
02224       AST_LIST_UNLOCK(&iaxq.queue);
02225       f->retrans = -1;
02226       /* Free the IAX frame */
02227       iax2_frame_free(f);
02228    }
02229 }

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

Definition at line 6393 of file chan_iax2.c.

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

Referenced by auth_reject().

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

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

Definition at line 3105 of file chan_iax2.c.

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

Referenced by auto_congest().

03106 {
03107    int callno = PTR_TO_CALLNO(nothing);
03108    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03109    ast_mutex_lock(&iaxsl[callno]);
03110    if (iaxs[callno]) {
03111       iaxs[callno]->initid = -1;
03112       iax2_queue_frame(callno, &f);
03113       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03114    }
03115    ast_mutex_unlock(&iaxsl[callno]);
03116 }

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

Definition at line 6442 of file chan_iax2.c.

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

Referenced by auto_hangup().

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

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

02018 {
02019    /* Just deliver the packet by using queueing.  This is called by
02020      the IAX thread with the iaxsl lock held. */
02021    struct iax_frame *fr = data;
02022    fr->retrans = -1;
02023    ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
02024    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
02025       iax2_queue_frame(fr->callno, &fr->af);
02026    /* Free our iax frame */
02027    iax2_frame_free(fr);
02028    /* And don't run again */
02029    return 0;
02030 }

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

Definition at line 6072 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, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, LOG_DEBUG, manager_event(), option_debug, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().

Referenced by expire_registry().

06073 {
06074    struct iax2_peer *peer = (struct iax2_peer *) data;
06075 
06076    if (!peer)
06077       return;
06078 
06079    peer->expire = -1;
06080 
06081    if (option_debug)
06082       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
06083    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
06084       realtime_update_peer(peer->name, &peer->addr, 0);
06085    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
06086    /* Reset the address */
06087    memset(&peer->addr, 0, sizeof(peer->addr));
06088    /* Reset expiry value */
06089    peer->expiry = min_reg_expire;
06090    if (!ast_test_flag(peer, IAX_TEMPONLY))
06091       ast_db_del("IAX/Registry", peer->name);
06092    register_peer_exten(peer, 0);
06093    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
06094    if (iax2_regfunk)
06095       iax2_regfunk(peer->name, 0);
06096 
06097    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
06098       unlink_peer(peer);
06099 
06100    peer_unref(peer);
06101 }

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

References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, 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, chan_iax2_pvt::expiry, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, match(), maxnontrunkcall, maxtrunkcall, MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, store_by_peercallno(), TRUNK_CALL_START, and update_max_nontrunk().

Referenced by find_callno(), and find_callno_locked().

01517 {
01518    int res = 0;
01519    int x;
01520    struct timeval now;
01521    char host[80];
01522 
01523    if (new <= NEW_ALLOW) {
01524       if (callno) {
01525          struct chan_iax2_pvt *pvt;
01526          struct chan_iax2_pvt tmp_pvt = {
01527             .callno = dcallno,
01528             .peercallno = callno,
01529             /* hack!! */
01530             .frames_received = check_dcallno,
01531          };
01532  
01533          memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
01534  
01535          if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
01536             if (return_locked) {
01537                ast_mutex_lock(&iaxsl[pvt->callno]);
01538             }
01539             res = pvt->callno;
01540             ao2_ref(pvt, -1);
01541             pvt = NULL;
01542             return res;
01543          }
01544       }
01545 
01546       /* Look for an existing connection first */
01547       for (x = 1; !res && x < maxnontrunkcall; x++) {
01548          ast_mutex_lock(&iaxsl[x]);
01549          if (iaxs[x]) {
01550             /* Look for an exact match */
01551             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01552                res = x;
01553             }
01554          }
01555          if (!res || !return_locked)
01556             ast_mutex_unlock(&iaxsl[x]);
01557       }
01558       for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) {
01559          ast_mutex_lock(&iaxsl[x]);
01560          if (iaxs[x]) {
01561             /* Look for an exact match */
01562             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01563                res = x;
01564             }
01565          }
01566          if (!res || !return_locked)
01567             ast_mutex_unlock(&iaxsl[x]);
01568       }
01569    }
01570    if (!res && (new >= NEW_ALLOW)) {
01571       int start, found = 0;
01572 
01573       /* It may seem odd that we look through the peer list for a name for
01574        * this *incoming* call.  Well, it is weird.  However, users don't
01575        * have an IP address/port number that we can match against.  So,
01576        * this is just checking for a peer that has that IP/port and
01577        * assuming that we have a user of the same name.  This isn't always
01578        * correct, but it will be changed if needed after authentication. */
01579       if (!iax2_getpeername(*sin, host, sizeof(host)))
01580          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01581 
01582       now = ast_tvnow();
01583       start = 2 + (ast_random() % (TRUNK_CALL_START - 1));
01584       for (x = start; 1; x++) {
01585          if (x == TRUNK_CALL_START) {
01586             x = 1;
01587             continue;
01588          }
01589 
01590          /* Find first unused call number that hasn't been used in a while */
01591          ast_mutex_lock(&iaxsl[x]);
01592          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01593             found = 1;
01594             break;
01595          }
01596          ast_mutex_unlock(&iaxsl[x]);
01597          
01598          if (x == start - 1) {
01599             break;
01600          }
01601       }
01602       /* We've still got lock held if we found a spot */
01603       if (x == start - 1 && !found) {
01604          ast_log(LOG_WARNING, "No more space\n");
01605          return 0;
01606       }
01607       iaxs[x] = new_iax(sin, host);
01608       update_max_nontrunk();
01609       if (iaxs[x]) {
01610          if (option_debug && iaxdebug)
01611             ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
01612          iaxs[x]->sockfd = sockfd;
01613          iaxs[x]->addr.sin_port = sin->sin_port;
01614          iaxs[x]->addr.sin_family = sin->sin_family;
01615          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01616          iaxs[x]->peercallno = callno;
01617          iaxs[x]->callno = x;
01618          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01619          iaxs[x]->expiry = min_reg_expire;
01620          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01621          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01622          iaxs[x]->amaflags = amaflags;
01623          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01624          
01625          ast_string_field_set(iaxs[x], accountcode, accountcode);
01626          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01627          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01628 
01629          if (iaxs[x]->peercallno) {
01630             store_by_peercallno(iaxs[x]);
01631          }
01632       } else {
01633          ast_log(LOG_WARNING, "Out of resources\n");
01634          ast_mutex_unlock(&iaxsl[x]);
01635          return 0;
01636       }
01637       if (!return_locked)
01638          ast_mutex_unlock(&iaxsl[x]);
01639       res = x;
01640    }
01641    return res;
01642 }

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

Definition at line 2547 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(), iax2_registry::callno, 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().

02548 {
02549    int callno = PTR_TO_CALLNO(p);
02550    struct chan_iax2_pvt *pvt = NULL;
02551    struct iax_frame *fr;
02552    jb_frame frame;
02553    int ret;
02554    long now;
02555    long next;
02556    struct timeval tv;
02557    
02558    /* Make sure we have a valid private structure before going on */
02559    ast_mutex_lock(&iaxsl[callno]);
02560    pvt = iaxs[callno];
02561    if (!pvt) {
02562       /* No go! */
02563       ast_mutex_unlock(&iaxsl[callno]);
02564       return;
02565    }
02566 
02567    pvt->jbid = -1;
02568    
02569    gettimeofday(&tv,NULL);
02570    /* round up a millisecond since ast_sched_runq does; */
02571    /* prevents us from spinning while waiting for our now */
02572    /* to catch up with runq's now */
02573    tv.tv_usec += 1000;
02574    
02575    now = ast_tvdiff_ms(tv, pvt->rxcore);
02576    
02577    if(now >= (next = jb_next(pvt->jb))) {
02578       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02579       switch(ret) {
02580       case JB_OK:
02581          fr = frame.data;
02582          __do_deliver(fr);
02583          /* __do_deliver() can cause the call to disappear */
02584          pvt = iaxs[callno];
02585          break;
02586       case JB_INTERP:
02587       {
02588          struct ast_frame af = { 0, };
02589          
02590          /* create an interpolation frame */
02591          af.frametype = AST_FRAME_VOICE;
02592          af.subclass = pvt->voiceformat;
02593          af.samples  = frame.ms * 8;
02594          af.src  = "IAX2 JB interpolation";
02595          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02596          af.offset = AST_FRIENDLY_OFFSET;
02597          
02598          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02599           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02600          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
02601             iax2_queue_frame(callno, &af);
02602             /* iax2_queue_frame() could cause the call to disappear */
02603             pvt = iaxs[callno];
02604          }
02605       }
02606          break;
02607       case JB_DROP:
02608          iax2_frame_free(frame.data);
02609          break;
02610       case JB_NOFRAME:
02611       case JB_EMPTY:
02612          /* do nothing */
02613          break;
02614       default:
02615          /* shouldn't happen */
02616          break;
02617       }
02618    }
02619    if (pvt)
02620       update_jbsched(pvt);
02621    ast_mutex_unlock(&iaxsl[callno]);
02622 }

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

Definition at line 5765 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05766 {
05767    struct iax2_registry *reg = (struct iax2_registry *)data;
05768    reg->expire = -1;
05769    iax2_do_register(reg);
05770 }

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

Definition at line 8876 of file chan_iax2.c.

References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, iax2_registry::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, and iax2_peer::pokefreqnotok.

Referenced by iax2_poke_noanswer().

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

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

Definition at line 6505 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06506 {
06507    struct iax2_peer *peer = (struct iax2_peer *)data;
06508    iax2_poke_peer(peer, 0);
06509    peer_unref(peer);
06510 }

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

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

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04521 {
04522    regex_t regexbuf;
04523    int havepattern = 0;
04524    int total_peers = 0;
04525    int online_peers = 0;
04526    int offline_peers = 0;
04527    int unmonitored_peers = 0;
04528    struct ao2_iterator i;
04529 
04530 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04531 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04532 
04533    struct iax2_peer *peer = NULL;
04534    char name[256];
04535    int registeredonly=0;
04536    char *term = manager ? "\r\n" : "\n";
04537 
04538    switch (argc) {
04539    case 6:
04540       if (!strcasecmp(argv[3], "registered"))
04541          registeredonly = 1;
04542       else
04543          return RESULT_SHOWUSAGE;
04544       if (!strcasecmp(argv[4], "like")) {
04545          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04546             return RESULT_SHOWUSAGE;
04547          havepattern = 1;
04548       } else
04549          return RESULT_SHOWUSAGE;
04550       break;
04551    case 5:
04552       if (!strcasecmp(argv[3], "like")) {
04553          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04554             return RESULT_SHOWUSAGE;
04555          havepattern = 1;
04556       } else
04557          return RESULT_SHOWUSAGE;
04558       break;
04559    case 4:
04560       if (!strcasecmp(argv[3], "registered"))
04561          registeredonly = 1;
04562       else
04563          return RESULT_SHOWUSAGE;
04564       break;
04565    case 3:
04566       break;
04567    default:
04568       return RESULT_SHOWUSAGE;
04569    }
04570 
04571 
04572    if (s)
04573       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04574    else
04575       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04576 
04577    i = ao2_iterator_init(peers, 0);
04578    for (peer = ao2_iterator_next(&i); peer; 
04579       peer_unref(peer), peer = ao2_iterator_next(&i)) {
04580       char nm[20];
04581       char status[20];
04582       char srch[2000];
04583       int retstatus;
04584 
04585       if (registeredonly && !peer->addr.sin_addr.s_addr)
04586          continue;
04587       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04588          continue;
04589 
04590       if (!ast_strlen_zero(peer->username))
04591          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04592       else
04593          ast_copy_string(name, peer->name, sizeof(name));
04594       
04595       retstatus = peer_status(peer, status, sizeof(status));
04596       if (retstatus > 0)
04597          online_peers++;
04598       else if (!retstatus)
04599          offline_peers++;
04600       else
04601          unmonitored_peers++;
04602       
04603       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04604       
04605       snprintf(srch, sizeof(srch), FORMAT, name, 
04606           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04607           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04608           nm,
04609           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04610           peer->encmethods ? "(E)" : "   ", status, term);
04611       
04612       if (s)
04613          astman_append(s, FORMAT, name, 
04614                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04615                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04616                   nm,
04617                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04618                   peer->encmethods ? "(E)" : "   ", status, term);
04619       else
04620          ast_cli(fd, FORMAT, name, 
04621             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04622             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04623             nm,
04624             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04625             peer->encmethods ? "(E)" : "   ", status, term);
04626       total_peers++;
04627    }
04628 
04629    if (s)
04630       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04631    else
04632       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04633 
04634    if (havepattern)
04635       regfree(&regexbuf);
04636 
04637    return RESULT_SUCCESS;
04638 #undef FORMAT
04639 #undef FORMAT2
04640 }

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

Definition at line 959 of file chan_iax2.c.

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

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

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

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

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

05023 {
05024    struct ast_frame f = { 0, };
05025 
05026    f.frametype = type;
05027    f.subclass = command;
05028    f.datalen = datalen;
05029    f.src = __FUNCTION__;
05030    f.data = (void *) data;
05031 
05032    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05033 }

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

Definition at line 1039 of file chan_iax2.c.

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

Referenced by send_lagrq().

01040 {
01041    int callno = (long) data;
01042 
01043    ast_mutex_lock(&iaxsl[callno]);
01044 
01045    while (iaxs[callno] && iaxs[callno]->lagid > -1) {
01046       if (iaxs[callno]->peercallno) {
01047          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01048       }
01049       iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01050       break;
01051    }
01052 
01053    ast_mutex_unlock(&iaxsl[callno]);
01054 }

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

Definition at line 999 of file chan_iax2.c.

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

Referenced by send_ping().

01000 {
01001    int callno = (long) data;
01002 
01003    ast_mutex_lock(&iaxsl[callno]);
01004 
01005    while (iaxs[callno] && iaxs[callno]->pingid != -1) {
01006       if (iaxs[callno]->peercallno) {
01007          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
01008       }
01009       iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
01010       break;
01011    }
01012 
01013    ast_mutex_unlock(&iaxsl[callno]);
01014 }

static int __unload_module ( void   )  [static]

Definition at line 11003 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, papp, peers, reload_firmware(), sched_context_destroy(), thread, users, and waresl.

Referenced by load_module(), and unload_module().

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

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

Definition at line 5074 of file chan_iax2.c.

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

Referenced by check_access().

05075 {
05076    while(con) {
05077       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05078          return -1;
05079       con = con->next;
05080    }
05081    return 0;
05082 }

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

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

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04849 {
04850    int x;
04851    int numchans = 0;
04852    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04853       ast_mutex_lock(&iaxsl[x]);
04854       if (iaxs[x]) {
04855          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04856          char *fmt;
04857          jb_info jbinfo;
04858          
04859          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04860             jb_getinfo(iaxs[x]->jb, &jbinfo);
04861             localjitter = jbinfo.jitter;
04862             localdelay = jbinfo.current - jbinfo.min;
04863             locallost = jbinfo.frames_lost;
04864             locallosspct = jbinfo.losspct/1000;
04865             localdropped = jbinfo.frames_dropped;
04866             localooo = jbinfo.frames_ooo;
04867          } else {
04868             localjitter = -1;
04869             localdelay = 0;
04870             locallost = -1;
04871             locallosspct = -1;
04872             localdropped = 0;
04873             localooo = -1;
04874          }
04875          if (limit_fmt)
04876             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04877          else
04878             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04879          if (s)
04880             
04881             astman_append(s, fmt,
04882                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04883                      iaxs[x]->pingtime,
04884                      localjitter, 
04885                      localdelay,
04886                      locallost,
04887                      locallosspct,
04888                      localdropped,
04889                      localooo,
04890                      iaxs[x]->frames_received/1000,
04891                      iaxs[x]->remote_rr.jitter,
04892                      iaxs[x]->remote_rr.delay,
04893                      iaxs[x]->remote_rr.losscnt,
04894                      iaxs[x]->remote_rr.losspct,
04895                      iaxs[x]->remote_rr.dropped,
04896                      iaxs[x]->remote_rr.ooo,
04897                      iaxs[x]->remote_rr.packets/1000);
04898          else
04899             ast_cli(fd, fmt,
04900                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04901                iaxs[x]->pingtime,
04902                localjitter, 
04903                localdelay,
04904                locallost,
04905                locallosspct,
04906                localdropped,
04907                localooo,
04908                iaxs[x]->frames_received/1000,
04909                iaxs[x]->remote_rr.jitter,
04910                iaxs[x]->remote_rr.delay,
04911                iaxs[x]->remote_rr.losscnt,
04912                iaxs[x]->remote_rr.losspct,
04913                iaxs[x]->remote_rr.dropped,
04914                iaxs[x]->remote_rr.ooo,
04915                iaxs[x]->remote_rr.packets/1000
04916                );
04917          numchans++;
04918       }
04919       ast_mutex_unlock(&iaxsl[x]);
04920    }
04921    return numchans;
04922 }

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

Create new call, interface with the PBX core.

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

03727 {
03728    struct ast_channel *tmp;
03729    struct chan_iax2_pvt *i;
03730    struct ast_variable *v = NULL;
03731 
03732    if (!(i = iaxs[callno])) {
03733       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03734       return NULL;
03735    }
03736 
03737    /* Don't hold call lock */
03738    ast_mutex_unlock(&iaxsl[callno]);
03739    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);
03740    ast_mutex_lock(&iaxsl[callno]);
03741    if (!iaxs[callno]) {
03742       if (tmp) {
03743          ast_channel_free(tmp);
03744       }
03745       ast_mutex_unlock(&iaxsl[callno]);
03746       return NULL;
03747    }
03748 
03749    if (!tmp)
03750       return NULL;
03751    tmp->tech = &iax2_tech;
03752    /* We can support any format by default, until we get restricted */
03753    tmp->nativeformats = capability;
03754    tmp->readformat = ast_best_codec(capability);
03755    tmp->writeformat = ast_best_codec(capability);
03756    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03757 
03758    /* Don't use ast_set_callerid() here because it will
03759     * generate a NewCallerID event before the NewChannel event */
03760    if (!ast_strlen_zero(i->ani))
03761       tmp->cid.cid_ani = ast_strdup(i->ani);
03762    else
03763       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03764    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03765    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03766    tmp->cid.cid_pres = i->calling_pres;
03767    tmp->cid.cid_ton = i->calling_ton;
03768    tmp->cid.cid_tns = i->calling_tns;
03769    if (!ast_strlen_zero(i->language))
03770       ast_string_field_set(tmp, language, i->language);
03771    if (!ast_strlen_zero(i->accountcode))
03772       ast_string_field_set(tmp, accountcode, i->accountcode);
03773    if (i->amaflags)
03774       tmp->amaflags = i->amaflags;
03775    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03776    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03777    if (i->adsi)
03778       tmp->adsicpe = i->peeradsicpe;
03779    else
03780       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03781    i->owner = tmp;
03782    i->capability = capability;
03783 
03784    for (v = i->vars ; v ; v = v->next)
03785       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03786 
03787    if (state != AST_STATE_DOWN) {
03788       if (ast_pbx_start(tmp)) {
03789          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03790          ast_hangup(tmp);
03791          i->owner = NULL;
03792          return NULL;
03793       }
03794    }
03795 
03796    ast_module_ref(ast_module_info->self);
03797    
03798    return tmp;
03799 }

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02232 {
02233 #ifdef SCHED_MULTITHREADED
02234    if (schedule_action(__attempt_transmit, data))
02235 #endif      
02236       __attempt_transmit(data);
02237    return 0;
02238 }

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

Definition at line 6427 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 6413 of file chan_iax2.c.

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

Referenced by auth_fail().

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

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

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

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 5691 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(), iax_ies::authmethods, iax2_peer::authmethods, iax_ie_data::buf, chan_iax2_pvt::callno, iax2_registry::callno, iax_ies::challenge, chan_iax2_pvt::dcx, chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, iax2_peer::mask, merge_encryption(), peer_unref(), peers, iax_ie_data::pos, realtime_peer(), send_command(), and iax_ies::username.

Referenced by socket_process().

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

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 5346 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, iax_ie_data::buf, iax2_user::curauthreq, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, iaxs, iax2_user::maxauthreq, iax_ie_data::pos, send_command(), send_command_final(), user_unref(), and users.

Referenced by socket_process().

05347 {
05348    struct iax_ie_data ied;
05349    int res = -1, authreq_restrict = 0;
05350    char challenge[10];
05351    struct chan_iax2_pvt *p = iaxs[call_num];
05352 
05353    memset(&ied, 0, sizeof(ied));
05354 
05355    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05356    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05357       struct iax2_user *user, tmp_user = {
05358          .name = p->username, 
05359       };
05360 
05361       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05362       if (user) {
05363          if (user->curauthreq == user->maxauthreq)
05364             authreq_restrict = 1;
05365          else
05366             user->curauthreq++;
05367          user = user_unref(user);
05368       }
05369    }
05370 
05371    /* If the AUTHREQ limit test failed, send back an error */
05372    if (authreq_restrict) {
05373       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05374       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05375       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05376       return 0;
05377    }
05378 
05379    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05380    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05381       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05382       ast_string_field_set(p, challenge, challenge);
05383       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05384       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05385    }
05386    if (p->encmethods)
05387       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05388 
05389    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05390 
05391    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05392 
05393    if (p->encmethods)
05394       ast_set_flag(p, IAX_ENCRYPTED);
05395 
05396    return res;
05397 }

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

Definition at line 5399 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, chan_iax2_pvt::authrej, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::rsa_result, iax2_registry::secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.

Referenced by socket_process().

05400 {
05401    char requeststr[256];
05402    char md5secret[256] = "";
05403    char secret[256] = "";
05404    char rsasecret[256] = "";
05405    int res = -1; 
05406    int x;
05407    struct iax2_user *user, tmp_user = {
05408       .name = p->username, 
05409    };
05410 
05411    if (p->authrej) {
05412       return res;
05413    }
05414    user = ao2_find(users, &tmp_user, OBJ_POINTER);
05415    if (user) {
05416       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05417          ast_atomic_fetchadd_int(&user->curauthreq, -1);
05418          ast_clear_flag(p, IAX_MAXAUTHREQ);
05419       }
05420       ast_string_field_set(p, host, user->name);
05421       user = user_unref(user);
05422    }
05423 
05424    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
05425       return res;
05426    if (ies->password)
05427       ast_copy_string(secret, ies->password, sizeof(secret));
05428    if (ies->md5_result)
05429       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05430    if (ies->rsa_result)
05431       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05432    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
05433       struct ast_key *key;
05434       char *keyn;
05435       char tmpkey[256];
05436       char *stringp=NULL;
05437       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
05438       stringp=tmpkey;
05439       keyn = strsep(&stringp, ":");
05440       while(keyn) {
05441          key = ast_key_get(keyn, AST_KEY_PUBLIC);
05442          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
05443             res = 0;
05444             break;
05445          } else if (!key)
05446             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
05447          keyn = strsep(&stringp, ":");
05448       }
05449    } else if (p->authmethods & IAX_AUTH_MD5) {
05450       struct MD5Context md5;
05451       unsigned char digest[16];
05452       char *tmppw, *stringp;
05453       
05454       tmppw = ast_strdupa(p->secret);
05455       stringp = tmppw;
05456       while((tmppw = strsep(&stringp, ";"))) {
05457          MD5Init(&md5);
05458          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05459          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05460          MD5Final(digest, &md5);
05461          /* If they support md5, authenticate with it.  */
05462          for (x=0;x<16;x++)
05463             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05464          if (!strcasecmp(requeststr, md5secret)) {
05465             res = 0;
05466             break;
05467          }
05468       }
05469    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05470       if (!strcmp(secret, p->secret))
05471          res = 0;
05472    }
05473    return res;
05474 }

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

Definition at line 3118 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03119 {
03120 #ifdef SCHED_MULTITHREADED
03121    if (schedule_action(__auto_congest, data))
03122 #endif      
03123       __auto_congest(data);
03124    return 0;
03125 }

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

Definition at line 6457 of file chan_iax2.c.

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

Referenced by iax2_dprequest(), and iax2_provision().

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

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

Definition at line 9197 of file chan_iax2.c.

References ast_calloc, and iax2_context::context.

Referenced by build_user().

09198 {
09199    struct iax2_context *con;
09200 
09201    if ((con = ast_calloc(1, sizeof(*con))))
09202       ast_copy_string(con->context, context, sizeof(con->context));
09203    
09204    return con;
09205 }

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

Definition at line 4106 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

04107 {
04108    aes_encrypt_key128(digest, ecx);
04109    aes_decrypt_key128(digest, dcx);
04110 }

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

Create peer structure based on configuration.

Definition at line 9343 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, 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(), iax2_peer::authmethods, iax2_peer::capability, cid_name, cid_num, iax2_peer::defaddr, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, iax2_peer::dnsmgr, iax2_peer::encmethods, iax2_peer::expire, iax2_peer::expiry, get_auth_methods(), get_encrypt_methods(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, prefs, iax2_peer::prefs, iax2_registry::secret, iax2_peer::smoothing, iax2_peer::sockfd, unlink_peer(), and ast_variable::value.

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

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

Create in-memory user structure from configuration.

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

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

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

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

Referenced by find_cache().

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

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

Definition at line 3974 of file chan_iax2.c.

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

03975 {
03976    /* Returns where in "receive time" we are.  That is, how many ms
03977       since we received (or would have received) the frame with timestamp 0 */
03978    int ms;
03979 #ifdef IAXTESTS
03980    int jit;
03981 #endif /* IAXTESTS */
03982    /* Setup rxcore if necessary */
03983    if (ast_tvzero(p->rxcore)) {
03984       p->rxcore = ast_tvnow();
03985       if (option_debug && iaxdebug)
03986          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
03987                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
03988       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
03989 #if 1
03990       if (option_debug && iaxdebug)
03991          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
03992                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
03993 #endif
03994    }
03995 
03996    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
03997 #ifdef IAXTESTS
03998    if (test_jit) {
03999       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
04000          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
04001          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
04002             jit = -jit;
04003          ms += jit;
04004       }
04005    }
04006    if (test_late) {
04007       ms += test_late;
04008       test_late = 0;
04009    }
04010 #endif /* IAXTESTS */
04011    return ms;
04012 }

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

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

Referenced by iax2_send(), and socket_process().

03846 {
03847    int ms;
03848    int voice = 0;
03849    int genuine = 0;
03850    int adjust;
03851    struct timeval *delivery = NULL;
03852 
03853 
03854    /* What sort of frame do we have?: voice is self-explanatory
03855       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
03856       non-genuine frames are CONTROL frames [ringing etc], DTMF
03857       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
03858       the others need a timestamp slaved to the voice frames so that they go in sequence
03859    */
03860    if (f) {
03861       if (f->frametype == AST_FRAME_VOICE) {
03862          voice = 1;
03863          delivery = &f->delivery;
03864       } else if (f->frametype == AST_FRAME_IAX) {
03865          genuine = 1;
03866       } else if (f->frametype == AST_FRAME_CNG) {
03867          p->notsilenttx = 0;  
03868       }
03869    }
03870    if (ast_tvzero(p->offset)) {
03871       gettimeofday(&p->offset, NULL);
03872       /* Round to nearest 20ms for nice looking traces */
03873       p->offset.tv_usec -= p->offset.tv_usec % 20000;
03874    }
03875    /* If the timestamp is specified, just send it as is */
03876    if (ts)
03877       return ts;
03878    /* If we have a time that the frame arrived, always use it to make our timestamp */
03879    if (delivery && !ast_tvzero(*delivery)) {
03880       ms = ast_tvdiff_ms(*delivery, p->offset);
03881       if (option_debug > 2 && iaxdebug)
03882          ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
03883    } else {
03884       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
03885       if (ms < 0)
03886          ms = 0;
03887       if (voice) {
03888          /* On a voice frame, use predicted values if appropriate */
03889          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
03890             /* Adjust our txcore, keeping voice and non-voice synchronized */
03891             /* AN EXPLANATION:
03892                When we send voice, we usually send "calculated" timestamps worked out
03893                on the basis of the number of samples sent. When we send other frames,
03894                we usually send timestamps worked out from the real clock.
03895                The problem is that they can tend to drift out of step because the 
03896                   source channel's clock and our clock may not be exactly at the same rate.
03897                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
03898                for this call.  Moving it adjusts timestamps for non-voice frames.
03899                We make the adjustment in the style of a moving average.  Each time we
03900                adjust p->offset by 10% of the difference between our clock-derived
03901                timestamp and the predicted timestamp.  That's why you see "10000"
03902                below even though IAX2 timestamps are in milliseconds.
03903                The use of a moving average avoids offset moving too radically.
03904                Generally, "adjust" roams back and forth around 0, with offset hardly
03905                changing at all.  But if a consistent different starts to develop it
03906                will be eliminated over the course of 10 frames (200-300msecs) 
03907             */
03908             adjust = (ms - p->nextpred);
03909             if (adjust < 0)
03910                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
03911             else if (adjust > 0)
03912                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
03913 
03914             if (!p->nextpred) {
03915                p->nextpred = ms; /*f->samples / 8;*/
03916                if (p->nextpred <= p->lastsent)
03917                   p->nextpred = p->lastsent + 3;
03918             }
03919             ms = p->nextpred;
03920          } else {
03921                 /* in this case, just use the actual
03922             * time, since we're either way off
03923             * (shouldn't happen), or we're  ending a
03924             * silent period -- and seed the next
03925             * predicted time.  Also, round ms to the
03926             * next multiple of frame size (so our
03927             * silent periods are multiples of
03928             * frame size too) */
03929 
03930             if (option_debug && iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
03931                ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
03932                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
03933 
03934             if (f->samples >= 8) /* check to make sure we dont core dump */
03935             {
03936                int diff = ms % (f->samples / 8);
03937                if (diff)
03938                    ms += f->samples/8 - diff;
03939             }
03940 
03941             p->nextpred = ms;
03942             p->notsilenttx = 1;
03943          }
03944       } else if ( f->frametype == AST_FRAME_VIDEO ) {
03945          /*
03946          * IAX2 draft 03 says that timestamps MUST be in order.
03947          * It does not say anything about several frames having the same timestamp
03948          * When transporting video, we can have a frame that spans multiple iax packets
03949          * (so called slices), so it would make sense to use the same timestamp for all of
03950          * them
03951          * We do want to make sure that frames don't go backwards though
03952          */
03953          if ( (unsigned int)ms < p->lastsent )
03954             ms = p->lastsent;
03955       } else {
03956          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
03957             it's a genuine frame */
03958          if (genuine) {
03959             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
03960             if (ms <= p->lastsent)
03961                ms = p->lastsent + 3;
03962          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
03963             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
03964             ms = p->lastsent + 3;
03965          }
03966       }
03967    }
03968    p->lastsent = ms;
03969    if (voice)
03970       p->nextpred = p->nextpred + f->samples / 8;
03971    return ms;
03972 }

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

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

03802 {
03803    unsigned long int mssincetx; /* unsigned to handle overflows */
03804    long int ms, pred;
03805 
03806    tpeer->trunkact = *tv;
03807    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03808    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03809       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03810       tpeer->txtrunktime = *tv;
03811       tpeer->lastsent = 999999;
03812    }
03813    /* Update last transmit time now */
03814    tpeer->lasttxtime = *tv;
03815    
03816    /* Calculate ms offset */
03817    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03818    /* Predict from last value */
03819    pred = tpeer->lastsent + sampms;
03820    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03821       ms = pred;
03822    
03823    /* We never send the same timestamp twice, so fudge a little if we must */
03824    if (ms == tpeer->lastsent)
03825       ms = tpeer->lastsent + 1;
03826    tpeer->lastsent = ms;
03827    return ms;
03828 }

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

Definition at line 5085 of file chan_iax2.c.

References iax2_user::adsi, chan_iax2_pvt::adsi, iax_ies::adsicpe, 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::authrej, iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, chan_iax2_pvt::calling_pres, iax_ies::calling_pres, chan_iax2_pvt::calling_tns, iax_ies::calling_tns, chan_iax2_pvt::calling_ton, iax_ies::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, iax_ies::capability, cid_name, cid_num, iax_ies::codec_prefs, iax2_context::context, iax2_user::contexts, iax_ies::dnid, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax_ies::format, iax2_user::ha, iax2_getpeertrunk(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, 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, iax_ies::language, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, chan_iax2_pvt::peeradsicpe, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_user::prefs, chan_iax2_pvt::prefs, prefs, iax_ies::rdnis, realtime_user(), iax2_registry::secret, user_unref(), iax_ies::username, users, ast_variable::value, chan_iax2_pvt::vars, iax2_user::vars, and iax_ies::version.

Referenced by socket_process().

05086 {
05087    /* Start pessimistic */
05088    int res = -1;
05089    int version = 2;
05090    struct iax2_user *user = NULL, *best = NULL;
05091    int bestscore = 0;
05092    int gotcapability = 0;
05093    struct ast_variable *v = NULL, *tmpvar = NULL;
05094    struct ao2_iterator i;
05095 
05096    if (!iaxs[callno])
05097       return res;
05098    if (ies->called_number)
05099       ast_string_field_set(iaxs[callno], exten, ies->called_number);
05100    if (ies->calling_number) {
05101       ast_shrink_phone_number(ies->calling_number);
05102       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
05103    }
05104    if (ies->calling_name)
05105       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
05106    if (ies->calling_ani)
05107       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
05108    if (ies->dnid)
05109       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
05110    if (ies->rdnis)
05111       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
05112    if (ies->called_context)
05113       ast_string_field_set(iaxs[callno], context, ies->called_context);
05114    if (ies->language)
05115       ast_string_field_set(iaxs[callno], language, ies->language);
05116    if (ies->username)
05117       ast_string_field_set(iaxs[callno], username, ies->username);
05118    if (ies->calling_ton > -1)
05119       iaxs[callno]->calling_ton = ies->calling_ton;
05120    if (ies->calling_tns > -1)
05121       iaxs[callno]->calling_tns = ies->calling_tns;
05122    if (ies->calling_pres > -1)
05123       iaxs[callno]->calling_pres = ies->calling_pres;
05124    if (ies->format)
05125       iaxs[callno]->peerformat = ies->format;
05126    if (ies->adsicpe)
05127       iaxs[callno]->peeradsicpe = ies->adsicpe;
05128    if (ies->capability) {
05129       gotcapability = 1;
05130       iaxs[callno]->peercapability = ies->capability;
05131    } 
05132    if (ies->version)
05133       version = ies->version;
05134 
05135    /* Use provided preferences until told otherwise for actual preferences */
05136    if(ies->codec_prefs) {
05137       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
05138       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
05139    }
05140 
05141    if (!gotcapability) 
05142       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
05143    if (version > IAX_PROTO_VERSION) {
05144       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
05145          ast_inet_ntoa(sin->sin_addr), version);
05146       return res;
05147    }
05148    /* Search the userlist for a compatible entry, and fill in the rest */
05149    i = ao2_iterator_init(users, 0);
05150    while ((user = ao2_iterator_next(&i))) {
05151       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
05152          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
05153          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
05154          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
05155               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
05156          if (!ast_strlen_zero(iaxs[callno]->username)) {
05157             /* Exact match, stop right now. */
05158             if (best)
05159                user_unref(best);
05160             best = user;
05161             break;
05162          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) {
05163             /* No required authentication */
05164             if (user->ha) {
05165                /* There was host authentication and we passed, bonus! */
05166                if (bestscore < 4) {
05167                   bestscore = 4;
05168                   if (best)
05169                      user_unref(best);
05170                   best = user;
05171                   continue;
05172                }
05173             } else {
05174                /* No host access, but no secret, either, not bad */
05175                if (bestscore < 3) {
05176                   bestscore = 3;
05177                   if (best)
05178                      user_unref(best);
05179                   best = user;
05180                   continue;
05181                }
05182             }
05183          } else {
05184             if (user->ha) {
05185                /* Authentication, but host access too, eh, it's something.. */
05186                if (bestscore < 2) {
05187                   bestscore = 2;
05188                   if (best)
05189                      user_unref(best);
05190                   best = user;
05191                   continue;
05192                }
05193             } else {
05194                /* Authentication and no host access...  This is our baseline */
05195                if (bestscore < 1) {
05196                   bestscore = 1;
05197                   if (best)
05198                      user_unref(best);
05199                   best = user;
05200                   continue;
05201                }
05202             }
05203          }
05204       }
05205       user_unref(user);
05206    }
05207    user = best;
05208    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
05209       user = realtime_user(iaxs[callno]->username, sin);
05210       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
05211           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
05212          user = user_unref(user);
05213       }
05214    }
05215    if (user) {
05216       /* We found our match (use the first) */
05217       /* copy vars */
05218       for (v = user->vars ; v ; v = v->next) {
05219          if((tmpvar = ast_variable_new(v->name, v->value))) {
05220             tmpvar->next = iaxs[callno]->vars; 
05221             iaxs[callno]->vars = tmpvar;
05222          }
05223       }
05224       /* If a max AUTHREQ restriction is in place, activate it */
05225       if (user->maxauthreq > 0)
05226          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
05227       iaxs[callno]->prefs = user->prefs;
05228       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
05229       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
05230       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
05231       iaxs[callno]->encmethods = user->encmethods;
05232       /* Store the requested username if not specified */
05233       if (ast_strlen_zero(iaxs[callno]->username))
05234          ast_string_field_set(iaxs[callno], username, user->name);
05235       /* Store whether this is a trunked call, too, of course, and move if appropriate */
05236       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
05237       iaxs[callno]->capability = user->capability;
05238       /* And use the default context */
05239       if (ast_strlen_zero(iaxs[callno]->context)) {
05240          if (user->contexts)
05241             ast_string_field_set(iaxs[callno], context, user->contexts->context);
05242          else
05243             ast_string_field_set(iaxs[callno], context, context);
05244       }
05245       /* And any input keys */
05246       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
05247       /* And the permitted authentication methods */
05248       iaxs[callno]->authmethods = user->authmethods;
05249       iaxs[callno]->adsi = user->adsi;
05250       /* If they have callerid, override the given caller id.  Always store the ANI */
05251       if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) {
05252          if (ast_test_flag(user, IAX_HASCALLERID)) {
05253             iaxs[callno]->calling_tns = 0;
05254             iaxs[callno]->calling_ton = 0;
05255             ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
05256             ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
05257             iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
05258          }
05259          if (ast_strlen_zero(iaxs[callno]->ani))
05260             ast_string_field_set(iaxs[callno], ani, user->cid_num);
05261       } else {
05262          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
05263       }
05264       if (!ast_strlen_zero(user->accountcode))
05265          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
05266       if (!ast_strlen_zero(user->mohinterpret))
05267          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
05268       if (!ast_strlen_zero(user->mohsuggest))
05269          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
05270       if (user->amaflags)
05271          iaxs[callno]->amaflags = user->amaflags;
05272       if (!ast_strlen_zero(user->language))
05273          ast_string_field_set(iaxs[callno], language, user->language);
05274       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
05275       /* Keep this check last */
05276       if (!ast_strlen_zero(user->dbsecret)) {
05277          char *family, *key=NULL;
05278          char buf[80];
05279          family = ast_strdupa(user->dbsecret);
05280          key = strchr(family, '/');
05281          if (key) {
05282             *key = '\0';
05283             key++;
05284          }
05285          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
05286             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
05287          else
05288             ast_string_field_set(iaxs[callno], secret, buf);
05289       } else
05290          ast_string_field_set(iaxs[callno], secret, user->secret);
05291       res = 0;
05292       user = user_unref(user);
05293    } else {
05294        /* user was not found, but we should still fake an AUTHREQ.
05295         * Set authmethods to the last known authmethod used by the system
05296         * Set a fake secret, it's not looked at, just required to attempt authentication.
05297         * Set authrej so the AUTHREP is rejected without even looking at its contents */
05298       iaxs[callno]->authmethods = last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
05299       ast_string_field_set(iaxs[callno], secret, "badsecret");
05300       iaxs[callno]->authrej = 1;
05301       if (!ast_strlen_zero(iaxs[callno]->username)) {
05302          /* only send the AUTHREQ if a username was specified. */
05303          res = 0;
05304       }
05305    }
05306    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
05307    return res;
05308 }

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

Definition at line 6815 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

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

Referenced by peer_set_srcaddr().

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

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

Definition at line 5810 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 2393 of file chan_iax2.c.

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

02394 {
02395    int which = 0;
02396    struct iax2_peer *peer;
02397    char *res = NULL;
02398    int wordlen = strlen(word);
02399    struct ao2_iterator i;
02400 
02401    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02402    if (pos != 3)
02403       return NULL;
02404 
02405    i = ao2_iterator_init(peers, 0);
02406    while ((peer = ao2_iterator_next(&i))) {
02407       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02408          res = ast_strdup(peer->name);
02409          peer_unref(peer);
02410          break;
02411       }
02412       peer_unref(peer);
02413    }
02414 
02415    return res;
02416 }

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

Definition at line 5866 of file chan_iax2.c.

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

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

static unsigned char compress_subclass ( int  subclass  )  [static]

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

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

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

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

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

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

Definition at line 3010 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, 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_DEBUG, 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.

03011 {
03012    struct ast_hostent ahp;
03013    struct hostent *hp;
03014    struct iax2_peer *peer;
03015    int res = -1;
03016    struct ast_codec_pref ourprefs;
03017 
03018    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
03019    cai->sockfd = defaultsockfd;
03020    cai->maxtime = 0;
03021    sin->sin_family = AF_INET;
03022 
03023    if (!(peer = find_peer(peername, 1))) {
03024       cai->found = 0;
03025 
03026       hp = ast_gethostbyname(peername, &ahp);
03027       if (hp) {
03028          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
03029          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
03030          /* use global iax prefs for unknown peer/user */
03031          /* But move the calling channel's native codec to the top of the preference list */
03032          memcpy(&ourprefs, &prefs, sizeof(ourprefs));
03033          if (c)
03034             ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03035          ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03036          return 0;
03037       } else {
03038          ast_log(LOG_WARNING, "No such host: %s\n", peername);
03039          return -1;
03040       }
03041    }
03042 
03043    cai->found = 1;
03044    
03045    /* if the peer has no address (current or default), return failure */
03046    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr))
03047       goto return_unref;
03048 
03049    /* if the peer is being monitored and is currently unreachable, return failure */
03050    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
03051       goto return_unref;
03052 
03053    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
03054    cai->maxtime = peer->maxms;
03055    cai->capability = peer->capability;
03056    cai->encmethods = peer->encmethods;
03057    cai->sockfd = peer->sockfd;
03058    cai->adsi = peer->adsi;
03059    memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
03060    /* Move the calling channel's native codec to the top of the preference list */
03061    if (c) {
03062       ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
03063       ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03064    }
03065    ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03066    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
03067    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
03068    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
03069    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
03070    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
03071    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
03072    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
03073    if (ast_strlen_zero(peer->dbsecret)) {
03074       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
03075    } else {
03076       char *family;
03077       char *key = NULL;
03078 
03079       family = ast_strdupa(peer->dbsecret);
03080       key = strchr(family, '/');
03081       if (key)
03082          *key++ = '\0';
03083       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
03084          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
03085          goto return_unref;
03086       }
03087    }
03088 
03089    if (peer->addr.sin_addr.s_addr) {
03090       sin->sin_addr = peer->addr.sin_addr;
03091       sin->sin_port = peer->addr.sin_port;
03092    } else {
03093       sin->sin_addr = peer->defaddr.sin_addr;
03094       sin->sin_port = peer->defaddr.sin_port;
03095    }
03096 
03097    res = 0;
03098 
03099 return_unref:
03100    peer_unref(peer);
03101 
03102    return res;
03103 }

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

Definition at line 4160 of file chan_iax2.c.

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

Referenced by decrypt_frame().

04161 {
04162    int padding;
04163    unsigned char *workspace;
04164 
04165    workspace = alloca(*datalen);
04166    memset(f, 0, sizeof(*f));
04167    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04168       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04169       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04170          return -1;
04171       /* Decrypt */
04172       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04173 
04174       padding = 16 + (workspace[15] & 0xf);
04175       if (option_debug && iaxdebug)
04176          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04177       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04178          return -1;
04179 
04180       *datalen -= padding;
04181       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04182       f->frametype = fh->type;
04183       if (f->frametype == AST_FRAME_VIDEO) {
04184          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04185       } else {
04186          f->subclass = uncompress_subclass(fh->csub);
04187       }
04188    } else {
04189       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04190       if (option_debug && iaxdebug)
04191          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04192       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04193          return -1;
04194       /* Decrypt */
04195       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04196       padding = 16 + (workspace[15] & 0x0f);
04197       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04198          return -1;
04199       *datalen -= padding;
04200       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04201    }
04202    return 0;
04203 }

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

Definition at line 4246 of file chan_iax2.c.

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

Referenced by socket_process().

04247 {
04248    int res=-1;
04249    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04250       /* Search for possible keys, given secrets */
04251       struct MD5Context md5;
04252       unsigned char digest[16];
04253       char *tmppw, *stringp;
04254       
04255       tmppw = ast_strdupa(iaxs[callno]->secret);
04256       stringp = tmppw;
04257       while ((tmppw = strsep(&stringp, ";"))) {
04258          MD5Init(&md5);
04259          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04260          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04261          MD5Final(digest, &md5);
04262          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04263          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04264          if (!res) {
04265             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04266             break;
04267          }
04268       }
04269    } else 
04270       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04271    return res;
04272 }

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

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

static void delete_users ( void   )  [static]

Definition at line 9815 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, user_delme_cb(), and users.

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

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1744 of file chan_iax2.c.

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

Referenced by reload_firmware().

01745 {
01746    /* Close firmware */
01747    if (cur->fwh) {
01748       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01749    }
01750    close(cur->fd);
01751    free(cur);
01752 }

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

Definition at line 6663 of file chan_iax2.c.

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

Referenced by dp_lookup_thread(), and socket_process().

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

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

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

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

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

Definition at line 4205 of file chan_iax2.c.

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

Referenced by iax2_send().

04206 {
04207    int padding;
04208    unsigned char *workspace;
04209    workspace = alloca(*datalen + 32);
04210    if (!workspace)
04211       return -1;
04212    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04213       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04214       if (option_debug && iaxdebug)
04215          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04216       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04217       padding = 16 + (padding & 0xf);
04218       memcpy(workspace, poo, padding);
04219       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04220       workspace[15] &= 0xf0;
04221       workspace[15] |= (padding & 0xf);
04222       if (option_debug && iaxdebug)
04223          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]);
04224       *datalen += padding;
04225       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04226       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04227          memcpy(poo, workspace + *datalen - 32, 32);
04228    } else {
04229       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04230       if (option_debug && iaxdebug)
04231          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04232       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04233       padding = 16 + (padding & 0xf);
04234       memcpy(workspace, poo, padding);
04235       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04236       workspace[15] &= 0xf0;
04237       workspace[15] |= (padding & 0x0f);
04238       *datalen += padding;
04239       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04240       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04241          memcpy(poo, workspace + *datalen - 32, 32);
04242    }
04243    return 0;
04244 }

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

Definition at line 6103 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

06104 {
06105 #ifdef SCHED_MULTITHREADED
06106    if (schedule_action(__expire_registry, data))
06107 #endif      
06108       __expire_registry(data);
06109    return 0;
06110 }

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

Definition at line 10373 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, iax2_registry::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().

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

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

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

01644                                                                                                                                     {
01645 
01646    return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame);
01647 }

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

References __find_callno().

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

01649                                                                                                                                            {
01650 
01651    return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
01652 }

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

Definition at line 910 of file chan_iax2.c.

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

Referenced by __schedule_action(), and socket_read().

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

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

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

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

01144 {
01145    struct iax2_peer *peer = NULL;
01146    struct iax2_peer tmp_peer = {
01147       .name = name,
01148    };
01149 
01150    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
01151 
01152    /* Now go for realtime if applicable */
01153    if(!peer && realtime)
01154       peer = realtime_peer(name, NULL);
01155 
01156    return peer;
01157 }

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

Definition at line 4014 of file chan_iax2.c.

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

Referenced by iax2_trunk_queue(), and socket_process().

04015 {
04016    struct iax2_trunk_peer *tpeer;
04017    
04018    /* Finds and locks trunk peer */
04019    ast_mutex_lock(&tpeerlock);
04020    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
04021       /* We don't lock here because tpeer->addr *never* changes */
04022       if (!inaddrcmp(&tpeer->addr, sin)) {
04023          ast_mutex_lock(&tpeer->lock);
04024          break;
04025       }
04026    }
04027    if (!tpeer) {
04028       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
04029          ast_mutex_init(&tpeer->lock);
04030          tpeer->lastsent = 9999;
04031          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
04032          tpeer->trunkact = ast_tvnow();
04033          ast_mutex_lock(&tpeer->lock);
04034          tpeer->next = tpeers;
04035          tpeer->sockfd = fd;
04036          tpeers = tpeer;
04037 #ifdef SO_NO_CHECK
04038          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
04039 #endif
04040          if (option_debug)
04041             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
04042       }
04043    }
04044    ast_mutex_unlock(&tpeerlock);
04045    return tpeer;
04046 }

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

Definition at line 3830 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03831 {
03832    long ms; /* NOT unsigned */
03833    if (ast_tvzero(iaxs[callno]->rxcore)) {
03834       /* Initialize rxcore time if appropriate */
03835       gettimeofday(&iaxs[callno]->rxcore, NULL);
03836       /* Round to nearest 20ms so traces look pretty */
03837       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03838    }
03839    /* Calculate difference between trunk and channel */
03840    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03841    /* Return as the sum of trunk time and the difference between trunk and real time */
03842    return ms + ts;
03843 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8982 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08983 {
08984    struct iax2_context *conl;
08985    while(con) {
08986       conl = con;
08987       con = con->next;
08988       free(conl);
08989    }
08990 }

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

Todo:
: will be removed after the 1.4 relese

Definition at line 10642 of file chan_iax2.c.

References iax2_peer::addr, iax2_registry::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_registry::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.

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

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9207 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09208 {
09209    int methods = 0;
09210    if (strstr(value, "rsa"))
09211       methods |= IAX_AUTH_RSA;
09212    if (strstr(value, "md5"))
09213       methods |= IAX_AUTH_MD5;
09214    if (strstr(value, "plaintext"))
09215       methods |= IAX_AUTH_PLAINTEXT;
09216    return methods;
09217 }

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

Definition at line 1025 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

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

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

Definition at line 2624 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02625 {
02626 #ifdef SCHED_MULTITHREADED
02627    if (schedule_action(__get_from_jb, data))
02628 #endif      
02629       __get_from_jb(data);
02630    return 0;
02631 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6861 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

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

static int handle_error ( void   )  [static]

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

02033 {
02034    /* XXX Ideally we should figure out why an error occured and then abort those
02035       rather than continuing to try.  Unfortunately, the published interface does
02036       not seem to work XXX */
02037 #if 0
02038    struct sockaddr_in *sin;
02039    int res;
02040    struct msghdr m;
02041    struct sock_extended_err e;
02042    m.msg_name = NULL;
02043    m.msg_namelen = 0;
02044    m.msg_iov = NULL;
02045    m.msg_control = &e;
02046    m.msg_controllen = sizeof(e);
02047    m.msg_flags = 0;
02048    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
02049    if (res < 0)
02050       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
02051    else {
02052       if (m.msg_controllen) {
02053          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
02054          if (sin) 
02055             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
02056          else
02057             ast_log(LOG_WARNING, "No address detected??\n");
02058       } else {
02059          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
02060       }
02061    }
02062 #endif
02063    return 0;
02064 }

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

Acknowledgment received for OUR registration.

Definition at line 5924 of file chan_iax2.c.

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

Referenced by socket_process().

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

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3630 of file chan_iax2.c.

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

03631 {
03632    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03633    if (option_debug)
03634       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03635    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03636 }

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

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

03481 {
03482    struct ast_channel *cs[3];
03483    struct ast_channel *who, *other;
03484    int to = -1;
03485    int res = -1;
03486    int transferstarted=0;
03487    struct ast_frame *f;
03488    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03489    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03490    struct timeval waittimer = {0, 0}, tv;
03491 
03492    lock_both(callno0, callno1);
03493    if (!iaxs[callno0] || !iaxs[callno1]) {
03494       unlock_both(callno0, callno1);
03495       return AST_BRIDGE_FAILED;
03496    }
03497    /* Put them in native bridge mode */
03498    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
03499       iaxs[callno0]->bridgecallno = callno1;
03500       iaxs[callno1]->bridgecallno = callno0;
03501    }
03502    unlock_both(callno0, callno1);
03503 
03504    /* If not, try to bridge until we can execute a transfer, if we can */
03505    cs[0] = c0;
03506    cs[1] = c1;
03507    for (/* ever */;;) {
03508       /* Check in case we got masqueraded into */
03509       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
03510          if (option_verbose > 2)
03511             ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
03512          /* Remove from native mode */
03513          if (c0->tech == &iax2_tech) {
03514             ast_mutex_lock(&iaxsl[callno0]);
03515             iaxs[callno0]->bridgecallno = 0;
03516             ast_mutex_unlock(&iaxsl[callno0]);
03517          }
03518          if (c1->tech == &iax2_tech) {
03519             ast_mutex_lock(&iaxsl[callno1]);
03520             iaxs[callno1]->bridgecallno = 0;
03521             ast_mutex_unlock(&iaxsl[callno1]);
03522          }
03523          return AST_BRIDGE_FAILED_NOWARN;
03524       }
03525       if (c0->nativeformats != c1->nativeformats) {
03526          if (option_verbose > 2) {
03527             char buf0[255];
03528             char buf1[255];
03529             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
03530             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
03531             ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
03532          }
03533          /* Remove from native mode */
03534          lock_both(callno0, callno1);
03535          if (iaxs[callno0])
03536             iaxs[callno0]->bridgecallno = 0;
03537          if (iaxs[callno1])
03538             iaxs[callno1]->bridgecallno = 0;
03539          unlock_both(callno0, callno1);
03540          return AST_BRIDGE_FAILED_NOWARN;
03541       }
03542       /* check if transfered and if we really want native bridging */
03543       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
03544          /* Try the transfer */
03545          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
03546                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
03547             ast_log(LOG_WARNING, "Unable to start the transfer\n");
03548          transferstarted = 1;
03549       }
03550       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
03551          /* Call has been transferred.  We're no longer involved */
03552          gettimeofday(&tv, NULL);
03553          if (ast_tvzero(waittimer)) {
03554             waittimer = tv;
03555          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
03556             c0->_softhangup |= AST_SOFTHANGUP_DEV;
03557             c1->_softhangup |= AST_SOFTHANGUP_DEV;
03558             *fo = NULL;
03559             *rc = c0;
03560             res = AST_BRIDGE_COMPLETE;
03561             break;
03562          }
03563       }
03564       to = 1000;
03565       who = ast_waitfor_n(cs, 2, &to);
03566       if (timeoutms > -1) {
03567          timeoutms -= (1000 - to);
03568          if (timeoutms < 0)
03569             timeoutms = 0;
03570       }
03571       if (!who) {
03572          if (!timeoutms) {
03573             res = AST_BRIDGE_RETRY;
03574             break;
03575          }
03576          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03577             res = AST_BRIDGE_FAILED;
03578             break;
03579          }
03580          continue;
03581       }
03582       f = ast_read(who);
03583       if (!f) {
03584          *fo = NULL;
03585          *rc = who;
03586          res = AST_BRIDGE_COMPLETE;
03587          break;
03588       }
03589       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03590          *fo = f;
03591          *rc = who;
03592          res =  AST_BRIDGE_COMPLETE;
03593          break;
03594       }
03595       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
03596       if ((f->frametype == AST_FRAME_VOICE) ||
03597           (f->frametype == AST_FRAME_TEXT) ||
03598           (f->frametype == AST_FRAME_VIDEO) || 
03599           (f->frametype == AST_FRAME_IMAGE) ||
03600           (f->frametype == AST_FRAME_DTMF)) {
03601          /* monitored dtmf take out of the bridge.
03602           * check if we monitor the specific source.
03603           */
03604          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
03605          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
03606             *rc = who;
03607             *fo = f;
03608             res = AST_BRIDGE_COMPLETE;
03609             /* Remove from native mode */
03610             break;
03611          }
03612          /* everything else goes to the other side */
03613          ast_write(other, f);
03614       }
03615       ast_frfree(f);
03616       /* Swap who gets priority */
03617       cs[2] = cs[0];
03618       cs[0] = cs[1];
03619       cs[1] = cs[2];
03620    }
03621    lock_both(callno0, callno1);
03622    if(iaxs[callno0])
03623       iaxs[callno0]->bridgecallno = 0;
03624    if(iaxs[callno1])
03625       iaxs[callno1]->bridgecallno = 0;
03626    unlock_both(callno0, callno1);
03627    return res;
03628 }

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

Definition at line 3224 of file chan_iax2.c.

References ast_channel::_state, create_addr_info::adsi, chan_iax2_pvt::adsi, ast_channel::adsicpe, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PRES_NUMBER_NOT_AVAILABLE, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, auto_congest(), iax_ie_data::buf, iax2_registry::callno, 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, create_addr_info::context, ast_channel::context, parsed_dial_string::context, create_addr(), chan_iax2_pvt::encmethods, create_addr_info::encmethods, parsed_dial_string::exten, iax2_datetime(), 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, parsed_dial_string::key, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, parsed_dial_string::options, create_addr_info::outkey, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, create_addr_info::peercontext, chan_iax2_pvt::pingtime, parsed_dial_string::port, iax_ie_data::pos, create_addr_info::prefs, PTR_TO_CALLNO, iax2_registry::secret, create_addr_info::secret, send_command(), create_addr_info::sockfd, chan_iax2_pvt::sockfd, ast_channel::tech_pvt, create_addr_info::timezone, create_addr_info::username, and parsed_dial_string::username.

03225 {
03226    struct sockaddr_in sin;
03227    char *l=NULL, *n=NULL, *tmpstr;
03228    struct iax_ie_data ied;
03229    char *defaultrdest = "s";
03230    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03231    struct parsed_dial_string pds;
03232    struct create_addr_info cai;
03233 
03234    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
03235       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
03236       return -1;
03237    }
03238 
03239    memset(&cai, 0, sizeof(cai));
03240    cai.encmethods = iax2_encryption;
03241 
03242    memset(&pds, 0, sizeof(pds));
03243    tmpstr = ast_strdupa(dest);
03244    parse_dial_string(tmpstr, &pds);
03245 
03246    if (ast_strlen_zero(pds.peer)) {
03247       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest);
03248       return -1;
03249    }
03250 
03251    if (!pds.exten) {
03252       pds.exten = defaultrdest;
03253    }
03254 
03255    if (create_addr(pds.peer, c, &sin, &cai)) {
03256       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
03257       return -1;
03258    }
03259 
03260    if (!pds.username && !ast_strlen_zero(cai.username))
03261       pds.username = cai.username;
03262    if (!pds.password && !ast_strlen_zero(cai.secret))
03263       pds.password = cai.secret;
03264    if (!pds.key && !ast_strlen_zero(cai.outkey))
03265       pds.key = cai.outkey;
03266    if (!pds.context && !ast_strlen_zero(cai.peercontext))
03267       pds.context = cai.peercontext;
03268 
03269    /* Keep track of the context for outgoing calls too */
03270    ast_copy_string(c->context, cai.context, sizeof(c->context));
03271 
03272    if (pds.port)
03273       sin.sin_port = htons(atoi(pds.port));
03274 
03275    l = c->cid.cid_num;
03276    n = c->cid.cid_name;
03277 
03278    /* Now build request */ 
03279    memset(&ied, 0, sizeof(ied));
03280 
03281    /* On new call, first IE MUST be IAX version of caller */
03282    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
03283    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
03284    if (pds.options && strchr(pds.options, 'a')) {
03285       /* Request auto answer */
03286       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
03287    }
03288 
03289    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
03290 
03291    if (l) {
03292       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
03293       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03294    } else {
03295       if (n)
03296          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03297       else
03298          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
03299    }
03300 
03301    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
03302    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
03303 
03304    if (n)
03305       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
03306    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
03307       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
03308 
03309    if (!ast_strlen_zero(c->language))
03310       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
03311    if (!ast_strlen_zero(c->cid.cid_dnid))
03312       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
03313    if (!ast_strlen_zero(c->cid.cid_rdnis))
03314       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
03315 
03316    if (pds.context)
03317       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
03318 
03319    if (pds.username)
03320       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
03321 
03322    if (cai.encmethods)
03323       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
03324 
03325    ast_mutex_lock(&iaxsl[callno]);
03326 
03327    if (!ast_strlen_zero(c->context))
03328       ast_string_field_set(iaxs[callno], context, c->context);
03329 
03330    if (pds.username)
03331       ast_string_field_set(iaxs[callno], username, pds.username);
03332 
03333    iaxs[callno]->encmethods = cai.encmethods;
03334 
03335    iaxs[callno]->adsi = cai.adsi;
03336    
03337    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
03338    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
03339 
03340    if (pds.key)
03341       ast_string_field_set(iaxs[callno], outkey, pds.key);
03342    if (pds.password)
03343       ast_string_field_set(iaxs[callno], secret, pds.password);
03344 
03345    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
03346    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
03347    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
03348    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
03349 
03350    if (iaxs[callno]->maxtime) {
03351       /* Initialize pingtime and auto-congest time */
03352       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
03353       iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
03354    } else if (autokill) {
03355       iaxs[callno]->pingtime = autokill / 2;
03356       iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
03357    }
03358 
03359    /* send the command using the appropriate socket for this peer */
03360    iaxs[callno]->sockfd = cai.sockfd;
03361 
03362    /* Transmit the string in a "NEW" request */
03363    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
03364 
03365    ast_mutex_unlock(&iaxsl[callno]);
03366    ast_setstate(c, AST_STATE_RINGING);
03367    
03368    return 0;
03369 }

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

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

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

Definition at line 3127 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03128 {
03129    time_t t;
03130    struct tm tm;
03131    unsigned int tmp;
03132    time(&t);
03133    if (!ast_strlen_zero(tz))
03134       ast_localtime(&t, &tm, tz);
03135    else
03136       ast_localtime(&t, &tm, NULL);
03137    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03138    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03139    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03140    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03141    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03142    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03143    return tmp;
03144 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1283 of file chan_iax2.c.

References ao2_ref(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, lastused, ast_channel::lock, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), 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().

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1213 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, user_unref(), and users.

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

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

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 10731 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_DEBUG, LOG_WARNING, iax2_peer::maxms, option_debug, parse_dial_string(), parsed_dial_string::peer, and peer_unref().

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

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

Definition at line 2743 of file chan_iax2.c.

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

02744 {
02745    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02746 }

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

Definition at line 2748 of file chan_iax2.c.

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

02749 {
02750    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02751 }

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

Definition at line 4936 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04937 {
04938    if (argc < 2 || argc > 3)
04939       return RESULT_SHOWUSAGE;
04940    iaxdebug = 1;
04941    ast_cli(fd, "IAX2 Debugging Enabled\n");
04942    return RESULT_SUCCESS;
04943 }

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

Definition at line 4954 of file chan_iax2.c.

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

04955 {
04956    if (argc < 3 || argc > 4)
04957       return RESULT_SHOWUSAGE;
04958    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04959    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04960    return RESULT_SUCCESS;
04961 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

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

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

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

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

Definition at line 5772 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05773 {
05774 #ifdef SCHED_MULTITHREADED
05775    if (schedule_action(__iax2_do_register_s, data))
05776 #endif      
05777       __iax2_do_register_s(data);
05778    return 0;
05779 }

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

Definition at line 4945 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04946 {
04947    if (argc < 3 || argc > 4)
04948       return RESULT_SHOWUSAGE;
04949    iaxtrunkdebug = 1;
04950    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04951    return RESULT_SUCCESS;
04952 }

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

Definition at line 6472 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

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

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

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

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

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

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

Definition at line 2770 of file chan_iax2.c.

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

02771 {
02772    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02773    ast_mutex_lock(&iaxsl[callno]);
02774    if (iaxs[callno])
02775       iaxs[callno]->owner = newchan;
02776    else
02777       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02778    ast_mutex_unlock(&iaxsl[callno]);
02779    return 0;
02780 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

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

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

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

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03706 {
03707    struct iax2_peer *peer;
03708    int res = 0;
03709    struct ao2_iterator i;
03710 
03711    i = ao2_iterator_init(peers, 0);
03712    while ((peer = ao2_iterator_next(&i))) {
03713       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03714           (peer->addr.sin_port == sin.sin_port)) {
03715          res = ast_test_flag(peer, IAX_TRUNK);
03716          peer_unref(peer);
03717          break;
03718       }
03719       peer_unref(peer);
03720    }
03721 
03722    return res;
03723 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3371 of file chan_iax2.c.

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

03372 {
03373    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03374    int alreadygone;
03375    struct iax_ie_data ied;
03376    memset(&ied, 0, sizeof(ied));
03377    ast_mutex_lock(&iaxsl[callno]);
03378    if (callno && iaxs[callno]) {
03379       if (option_debug)
03380          ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
03381       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03382       /* Send the hangup unless we have had a transmission error or are already gone */
03383       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03384       if (!iaxs[callno]->error && !alreadygone) {
03385          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03386          if (!iaxs[callno]) {
03387             ast_mutex_unlock(&iaxsl[callno]);
03388             return 0;
03389          }
03390       }
03391       /* Explicitly predestroy it */
03392       iax2_predestroy(callno);
03393       /* If we were already gone to begin with, destroy us now */
03394       if (alreadygone && iaxs[callno]) {
03395          if (option_debug)
03396             ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03397          iax2_destroy(callno);
03398       }
03399    }
03400    ast_mutex_unlock(&iaxsl[callno]);
03401    if (option_verbose > 2) 
03402       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03403    return 0;
03404 }

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

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

03639 {
03640    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03641    struct chan_iax2_pvt *pvt;
03642    int res = 0;
03643 
03644    if (option_debug && iaxdebug)
03645       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03646 
03647    ast_mutex_lock(&iaxsl[callno]);
03648    pvt = iaxs[callno];
03649 
03650    if (!pvt->peercallno) {
03651       /* We don't know the remote side's call number, yet.  :( */
03652       int count = 10;
03653       while (count-- && pvt && !pvt->peercallno) {
03654          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
03655          pvt = iaxs[callno];
03656       }
03657       if (!pvt->peercallno) {
03658          res = -1;
03659          goto done;
03660       }
03661    }
03662 
03663    switch (condition) {
03664    case AST_CONTROL_HOLD:
03665       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03666          ast_moh_start(c, data, pvt->mohinterpret);
03667          goto done;
03668       }
03669       break;
03670    case AST_CONTROL_UNHOLD:
03671       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03672          ast_moh_stop(c);
03673          goto done;
03674       }
03675    }
03676 
03677    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03678 
03679 done:
03680    ast_mutex_unlock(&iaxsl[callno]);
03681 
03682    return res;
03683 }

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

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

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

Definition at line 4963 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04964 {
04965    if (argc < 3 || argc > 4)
04966       return RESULT_SHOWUSAGE;
04967    iaxdebug = 0;
04968    ast_cli(fd, "IAX2 Debugging Disabled\n");
04969    return RESULT_SUCCESS;
04970 }

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

Definition at line 4981 of file chan_iax2.c.

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

04982 {
04983    if (argc < 4 || argc > 5)
04984       return RESULT_SHOWUSAGE;
04985    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04986    jb_debug_output("\n");
04987    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04988    return RESULT_SUCCESS;
04989 }

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

Definition at line 4972 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04973 {
04974    if (argc < 4 || argc > 5)
04975       return RESULT_SHOWUSAGE;
04976    iaxtrunkdebug = 0;
04977    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
04978    return RESULT_SUCCESS;
04979 }

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

Definition at line 8899 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08900 {
08901    struct iax2_peer *peer = (struct iax2_peer *)data;
08902    peer->pokeexpire = -1;
08903 #ifdef SCHED_MULTITHREADED
08904    if (schedule_action(__iax2_poke_noanswer, data))
08905 #endif      
08906       __iax2_poke_noanswer(data);
08907    peer_unref(peer);
08908    return 0;
08909 }

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

Definition at line 8920 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, iax2_registry::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, 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().

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

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

Definition at line 8911 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08912 {
08913    struct iax2_peer *peer = obj;
08914 
08915    iax2_poke_peer(peer, 0);
08916 
08917    return 0;
08918 }

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

Definition at line 6512 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

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

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

02117 {
02118    struct ast_channel *c;
02119    struct chan_iax2_pvt *pvt = iaxs[callno];
02120 
02121    if (!pvt)
02122       return -1;
02123    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
02124       iax2_destroy_helper(pvt);
02125       ast_set_flag(pvt, IAX_ALREADYGONE); 
02126    }
02127    c = pvt->owner;
02128    if (c) {
02129       c->tech_pvt = NULL;
02130       iax2_queue_hangup(callno);
02131       pvt->owner = NULL;
02132       ast_module_unref(ast_module_info->self);
02133    }
02134    return 0;
02135 }

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

Note:
For some reason, idle threads are exiting without being removed from an idle list, which is causing memory corruption. Forcibly remove it from the list, if it's there.

Definition at line 8576 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

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

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8567 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08568 {
08569    struct iax2_thread *thread = data;
08570    ast_mutex_destroy(&thread->lock);
08571    ast_cond_destroy(&thread->cond);
08572    free(thread);
08573    ast_atomic_dec_and_test(&iaxactivethreadcount);
08574 }

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

Definition at line 8854 of file chan_iax2.c.

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

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

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

Definition at line 8757 of file chan_iax2.c.

References iax_prov_complete_template().

08758 {
08759    if (pos != 3)
08760       return NULL;
08761    return iax_prov_complete_template(line, word, pos, state);
08762 }

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

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

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

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

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

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

02241 {
02242    struct iax2_peer *peer;
02243 
02244    if (argc != 4)
02245         return RESULT_SHOWUSAGE;
02246    if (!strcmp(argv[3],"all")) {
02247       reload_config();
02248       ast_cli(fd, "OK cache is flushed.\n");
02249    } else if ((peer = find_peer(argv[3], 0))) {
02250       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02251          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02252          expire_registry(peer_ref(peer));
02253          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02254       } else {
02255          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02256       }
02257       peer_unref(peer);
02258    } else {
02259       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02260    }
02261    
02262    return RESULT_SUCCESS;
02263 }

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

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

Referenced by socket_process().

01728 {
01729    for (;;) {
01730       if (iaxs[callno] && iaxs[callno]->owner) {
01731          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01732             /* Avoid deadlock by pausing and trying again */
01733             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01734          } else {
01735             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01736             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01737             break;
01738          }
01739       } else
01740          break;
01741    }
01742    return 0;
01743 }

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

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

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

01665 {
01666    for (;;) {
01667       if (iaxs[callno] && iaxs[callno]->owner) {
01668          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01669             /* Avoid deadlock by pausing and trying again */
01670             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01671          } else {
01672             ast_queue_frame(iaxs[callno]->owner, f);
01673             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01674             break;
01675          }
01676       } else
01677          break;
01678    }
01679    return 0;
01680 }

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

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

Referenced by iax2_predestroy().

01696 {
01697    for (;;) {
01698       if (iaxs[callno] && iaxs[callno]->owner) {
01699          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01700             /* Avoid deadlock by pausing and trying again */
01701             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01702          } else {
01703             ast_queue_hangup(iaxs[callno]->owner);
01704             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01705             break;
01706          }
01707       } else
01708          break;
01709    }
01710    return 0;
01711 }

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

Definition at line 3432 of file chan_iax2.c.

References ast_log(), ast_null_frame, LOG_NOTICE, and option_verbose.

03433 {
03434    if (option_verbose > 3)
03435        ast_log(LOG_NOTICE, "I should never be called!\n");
03436    return &ast_null_frame;
03437 }

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

Definition at line 5985 of file chan_iax2.c.

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

Referenced by set_config().

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

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

Definition at line 10290 of file chan_iax2.c.

References reload_config().

10291 {
10292    return reload_config();
10293 }

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

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

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

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

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

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

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

04275 {
04276    /* Queue a packet for delivery on a given private structure.  Use "ts" for
04277       timestamp, or calculate if ts is 0.  Send immediately without retransmission
04278       or delayed, with retransmission */
04279    struct ast_iax2_full_hdr *fh;
04280    struct ast_iax2_mini_hdr *mh;
04281    struct ast_iax2_video_hdr *vh;
04282    struct {
04283       struct iax_frame fr2;
04284       unsigned char buffer[4096];
04285    } frb;
04286    struct iax_frame *fr;
04287    int res;
04288    int sendmini=0;
04289    unsigned int lastsent;
04290    unsigned int fts;
04291 
04292    frb.fr2.afdatalen = sizeof(frb.buffer);
04293 
04294    if (!pvt) {
04295       ast_log(LOG_WARNING, "No private structure for packet?\n");
04296       return -1;
04297    }
04298    
04299    lastsent = pvt->lastsent;
04300 
04301    /* Calculate actual timestamp */
04302    fts = calc_timestamp(pvt, ts, f);
04303 
04304    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
04305     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
04306     * increment the "predicted timestamps" for voice, if we're predecting */
04307    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
04308        return 0;
04309 
04310 
04311    if ((ast_test_flag(pvt, IAX_TRUNK) || 
04312          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
04313          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
04314       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
04315        (f->frametype == AST_FRAME_VOICE) 
04316       /* is a voice frame */ &&
04317       (f->subclass == pvt->svoiceformat) 
04318       /* is the same type */ ) {
04319          /* Force immediate rather than delayed transmission */
04320          now = 1;
04321          /* Mark that mini-style frame is appropriate */
04322          sendmini = 1;
04323    }
04324    if ( f->frametype == AST_FRAME_VIDEO ) {
04325       /*
04326        * If the lower 15 bits of the timestamp roll over, or if
04327        * the video format changed then send a full frame.
04328        * Otherwise send a mini video frame
04329        */
04330       if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
04331           ((f->subclass & ~0x1) == pvt->svideoformat)
04332          ) {
04333          now = 1;
04334          sendmini = 1;
04335       } else {
04336          now = 0;
04337          sendmini = 0;
04338       }
04339       pvt->lastvsent = fts;
04340    }
04341    /* Allocate an iax_frame */
04342    if (now) {
04343       fr = &frb.fr2;
04344    } else
04345       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));
04346    if (!fr) {
04347       ast_log(LOG_WARNING, "Out of memory\n");
04348       return -1;
04349    }
04350    /* Copy our prospective frame into our immediate or retransmitted wrapper */
04351    iax_frame_wrap(fr, f);
04352 
04353    fr->ts = fts;
04354    fr->callno = pvt->callno;
04355    fr->transfer = transfer;
04356    fr->final = final;
04357    if (!sendmini) {
04358       /* We need a full frame */
04359       if (seqno > -1)
04360          fr->oseqno = seqno;
04361       else
04362          fr->oseqno = pvt->oseqno++;
04363       fr->iseqno = pvt->iseqno;
04364       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
04365       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
04366       fh->ts = htonl(fr->ts);
04367       fh->oseqno = fr->oseqno;
04368       if (transfer) {
04369          fh->iseqno = 0;
04370       } else
04371          fh->iseqno = fr->iseqno;
04372       /* Keep track of the last thing we've acknowledged */
04373       if (!transfer)
04374          pvt->aseqno = fr->iseqno;
04375       fh->type = fr->af.frametype & 0xFF;
04376       if (fr->af.frametype == AST_FRAME_VIDEO)
04377          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
04378       else
04379          fh->csub = compress_subclass(fr->af.subclass);
04380       if (transfer) {
04381          fr->dcallno = pvt->transfercallno;
04382       } else
04383          fr->dcallno = pvt->peercallno;
04384       fh->dcallno = htons(fr->dcallno);
04385       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
04386       fr->data = fh;
04387       fr->retries = 0;
04388       /* Retry after 2x the ping time has passed */
04389       fr->retrytime = pvt->pingtime * 2;
04390       if (fr->retrytime < MIN_RETRY_TIME)
04391          fr->retrytime = MIN_RETRY_TIME;
04392       if (fr->retrytime > MAX_RETRY_TIME)
04393          fr->retrytime = MAX_RETRY_TIME;
04394       /* Acks' don't get retried */
04395       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
04396          fr->retries = -1;
04397       else if (f->frametype == AST_FRAME_VOICE)
04398          pvt->svoiceformat = f->subclass;
04399       else if (f->frametype == AST_FRAME_VIDEO)
04400          pvt->svideoformat = f->subclass & ~0x1;
04401       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04402          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04403             if (iaxdebug) {
04404                if (fr->transfer)
04405                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04406                else
04407                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04408             }
04409             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
04410          } else
04411             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04412       }
04413    
04414       if (now) {
04415          res = send_packet(fr);
04416       } else
04417          res = iax2_transmit(fr);
04418    } else {
04419       if (ast_test_flag(pvt, IAX_TRUNK)) {
04420          iax2_trunk_queue(pvt, fr);
04421          res = 0;
04422       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
04423          /* Video frame have no sequence number */
04424          fr->oseqno = -1;
04425          fr->iseqno = -1;
04426          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
04427          vh->zeros = 0;
04428          vh->callno = htons(0x8000 | fr->callno);
04429          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
04430          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
04431          fr->data = vh;
04432          fr->retries = -1;
04433          res = send_packet(fr);        
04434       } else {
04435          /* Mini-frames have no sequence number */
04436          fr->oseqno = -1;
04437          fr->iseqno = -1;
04438          /* Mini frame will do */
04439          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
04440          mh->callno = htons(fr->callno);
04441          mh->ts = htons(fr->ts & 0xFFFF);
04442          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
04443          fr->data = mh;
04444          fr->retries = -1;
04445          if (pvt->transferring == TRANSFER_MEDIAPASS)
04446             fr->transfer = 1;
04447          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04448             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04449                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
04450             } else
04451                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04452          }
04453          res = send_packet(fr);
04454       }
04455    }
04456    return res;
04457 }

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

Definition at line 2765 of file chan_iax2.c.

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

02766 {
02767    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02768 }

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

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

Definition at line 2753 of file chan_iax2.c.

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

02754 {
02755    
02756    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02757       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02758 }

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

Definition at line 3406 of file chan_iax2.c.

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

03407 {
03408    struct ast_option_header *h;
03409    int res;
03410 
03411    switch (option) {
03412    case AST_OPTION_TXGAIN:
03413    case AST_OPTION_RXGAIN:
03414       /* these two cannot be sent, because they require a result */
03415       errno = ENOSYS;
03416       return -1;
03417    default:
03418       if (!(h = ast_malloc(datalen + sizeof(*h))))
03419          return -1;
03420 
03421       h->flag = AST_OPTION_FLAG_REQUEST;
03422       h->option = htons(option);
03423       memcpy(h->data, data, datalen);
03424       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03425                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03426                  datalen + sizeof(*h), -1);
03427       free(h);
03428       return res;
03429    }
03430 }

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

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

02445 {
02446    struct iax2_dpcache *dp;
02447    char tmp[1024], *pc;
02448    int s;
02449    int x,y;
02450    struct timeval tv;
02451    gettimeofday(&tv, NULL);
02452    ast_mutex_lock(&dpcache_lock);
02453    dp = dpcache;
02454    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02455    while(dp) {
02456       s = dp->expiry.tv_sec - tv.tv_sec;
02457       tmp[0] = '\0';
02458       if (dp->flags & CACHE_FLAG_EXISTS)
02459          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02460       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02461          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02462       if (dp->flags & CACHE_FLAG_CANEXIST)
02463          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02464       if (dp->flags & CACHE_FLAG_PENDING)
02465          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02466       if (dp->flags & CACHE_FLAG_TIMEOUT)
02467          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02468       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02469          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02470       if (dp->flags & CACHE_FLAG_MATCHMORE)
02471          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02472       if (dp->flags & CACHE_FLAG_UNKNOWN)
02473          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02474       /* Trim trailing pipe */
02475       if (!ast_strlen_zero(tmp))
02476          tmp[strlen(tmp) - 1] = '\0';
02477       else
02478          ast_copy_string(tmp, "(none)", sizeof(tmp));
02479       y=0;
02480       pc = strchr(dp->peercontext, '@');
02481       if (!pc)
02482          pc = dp->peercontext;
02483       else
02484          pc++;
02485       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02486          if (dp->waiters[x] > -1)
02487             y++;
02488       if (s > 0)
02489          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02490       else
02491          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02492       dp = dp->next;
02493    }
02494    ast_mutex_unlock(&dpcache_lock);
02495    return RESULT_SUCCESS;
02496 }

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

Definition at line 4801 of file chan_iax2.c.

References iax2_registry::addr, 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.

04802 {
04803 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04804 #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"
04805 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04806    int x;
04807    int numchans = 0;
04808 
04809    if (argc != 3)
04810       return RESULT_SHOWUSAGE;
04811    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04812    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04813       ast_mutex_lock(&iaxsl[x]);
04814       if (iaxs[x]) {
04815          int lag, jitter, localdelay;
04816          jb_info jbinfo;
04817          
04818          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04819             jb_getinfo(iaxs[x]->jb, &jbinfo);
04820             jitter = jbinfo.jitter;
04821             localdelay = jbinfo.current - jbinfo.min;
04822          } else {
04823             jitter = -1;
04824             localdelay = 0;
04825          }
04826          lag = iaxs[x]->remote_rr.delay;
04827          ast_cli(fd, FORMAT,
04828             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04829             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04830             S_OR(iaxs[x]->username, "(None)"),
04831             iaxs[x]->callno, iaxs[x]->peercallno,
04832             iaxs[x]->oseqno, iaxs[x]->iseqno,
04833             lag,
04834             jitter,
04835             localdelay,
04836             ast_getformatname(iaxs[x]->voiceformat) );
04837          numchans++;
04838       }
04839       ast_mutex_unlock(&iaxsl[x]);
04840    }
04841    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04842    return RESULT_SUCCESS;
04843 #undef FORMAT
04844 #undef FORMAT2
04845 #undef FORMATB
04846 }

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

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

04713 {
04714 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04715 #if !defined(__FreeBSD__)
04716 #define FORMAT "%-15.15s  %-15d %-15d\n"
04717 #else /* __FreeBSD__ */
04718 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04719 #endif /* __FreeBSD__ */
04720    struct iax_firmware *cur;
04721    if ((argc != 3) && (argc != 4))
04722       return RESULT_SHOWUSAGE;
04723    ast_mutex_lock(&waresl.lock);
04724    
04725    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04726    for (cur = waresl.wares;cur;cur = cur->next) {
04727       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04728          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04729             (int)ntohl(cur->fwh->datalen));
04730    }
04731    ast_mutex_unlock(&waresl.lock);
04732    return RESULT_SUCCESS;
04733 #undef FORMAT
04734 #undef FORMAT2
04735 }

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

Definition at line 4924 of file chan_iax2.c.

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

04925 {
04926    int numchans = 0;
04927    if (argc != 3)
04928       return RESULT_SHOWUSAGE;
04929    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04930    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04931    numchans = ast_cli_netstats(NULL, fd, 1);
04932    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04933    return RESULT_SUCCESS;
04934 }

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

Show one peer in detail.

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

02335 {
02336    char status[30];
02337    char cbuf[256];
02338    struct iax2_peer *peer;
02339    char codec_buf[512];
02340    int x = 0, codec = 0, load_realtime = 0;
02341 
02342    if (argc < 4)
02343       return RESULT_SHOWUSAGE;
02344 
02345    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02346 
02347    peer = find_peer(argv[3], load_realtime);
02348    if (peer) {
02349       ast_cli(fd,"\n\n");
02350       ast_cli(fd, "  * Name       : %s\n", peer->name);
02351       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02352       ast_cli(fd, "  Context      : %s\n", peer->context);
02353       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02354       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02355       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02356       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02357       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02358       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));
02359       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02360       ast_cli(fd, "  Username     : %s\n", peer->username);
02361       ast_cli(fd, "  Codecs       : ");
02362       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02363       ast_cli(fd, "%s\n", codec_buf);
02364 
02365       ast_cli(fd, "  Codec Order  : (");
02366       for(x = 0; x < 32 ; x++) {
02367          codec = ast_codec_pref_index(&peer->prefs,x);
02368          if(!codec)
02369             break;
02370          ast_cli(fd, "%s", ast_getformatname(codec));
02371          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02372             ast_cli(fd, "|");
02373       }
02374 
02375       if (!x)
02376          ast_cli(fd, "none");
02377       ast_cli(fd, ")\n");
02378 
02379       ast_cli(fd, "  Status       : ");
02380       peer_status(peer, status, sizeof(status));   
02381       ast_cli(fd, "%s\n",status);
02382       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02383       ast_cli(fd,"\n");
02384       peer_unref(peer);
02385    } else {
02386       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02387       ast_cli(fd,"\n");
02388    }
02389 
02390    return RESULT_SUCCESS;
02391 }

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

Definition at line 4701 of file chan_iax2.c.

References __iax2_show_peers().

04702 {
04703    return __iax2_show_peers(0, fd, NULL, argc, argv);
04704 }

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

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

04774 {
04775 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04776 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04777    struct iax2_registry *reg = NULL;
04778 
04779    char host[80];
04780    char perceived[80];
04781    if (argc != 3)
04782       return RESULT_SHOWUSAGE;
04783    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04784    AST_LIST_LOCK(&registrations);
04785    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04786       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04787       if (reg->us.sin_addr.s_addr) 
04788          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04789       else
04790          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04791       ast_cli(fd, FORMAT, host, 
04792                (reg->dnsmgr) ? "Y" : "N", 
04793                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04794    }
04795    AST_LIST_UNLOCK(&registrations);
04796    return RESULT_SUCCESS;
04797 #undef FORMAT
04798 #undef FORMAT2
04799 }

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

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

02419 {
02420    struct iax_frame *cur;
02421    int cnt = 0, dead=0, final=0;
02422 
02423    if (argc != 3)
02424       return RESULT_SHOWUSAGE;
02425 
02426    AST_LIST_LOCK(&iaxq.queue);
02427    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02428       if (cur->retries < 0)
02429          dead++;
02430       if (cur->final)
02431          final++;
02432       cnt++;
02433    }
02434    AST_LIST_UNLOCK(&iaxq.queue);
02435 
02436    ast_cli(fd, "    IAX Statistics\n");
02437    ast_cli(fd, "---------------------\n");
02438    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02439    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02440    
02441    return RESULT_SUCCESS;
02442 }

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

Definition at line 4642 of file chan_iax2.c.

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

04643 {
04644    struct iax2_thread *thread = NULL;
04645    time_t t;
04646    int threadcount = 0, dynamiccount = 0;
04647    char type;
04648 
04649    if (argc != 3)
04650       return RESULT_SHOWUSAGE;
04651       
04652    ast_cli(fd, "IAX2 Thread Information\n");
04653    time(&t);
04654    ast_cli(fd, "Idle Threads:\n");
04655    AST_LIST_LOCK(&idle_list);
04656    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04657 #ifdef DEBUG_SCHED_MULTITHREAD
04658       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04659          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04660 #else
04661       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04662          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04663 #endif
04664       threadcount++;
04665    }
04666    AST_LIST_UNLOCK(&idle_list);
04667    ast_cli(fd, "Active Threads:\n");
04668    AST_LIST_LOCK(&active_list);
04669    AST_LIST_TRAVERSE(&active_list, thread, list) {
04670       if (thread->type == IAX_TYPE_DYNAMIC)
04671          type = 'D';
04672       else
04673          type = 'P';
04674 #ifdef DEBUG_SCHED_MULTITHREAD
04675       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04676          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04677 #else
04678       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04679          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04680 #endif
04681       threadcount++;
04682    }
04683    AST_LIST_UNLOCK(&active_list);
04684    ast_cli(fd, "Dynamic Threads:\n");
04685         AST_LIST_LOCK(&dynamic_list);
04686         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04687 #ifdef DEBUG_SCHED_MULTITHREAD
04688                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04689                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04690 #else
04691                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04692                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04693 #endif
04694       dynamiccount++;
04695         }
04696         AST_LIST_UNLOCK(&dynamic_list);
04697    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04698    return RESULT_SUCCESS;
04699 }

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

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

04460 {
04461    regex_t regexbuf;
04462    int havepattern = 0;
04463 
04464 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04465 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04466 
04467    struct iax2_user *user = NULL;
04468    char auth[90];
04469    char *pstr = "";
04470    struct ao2_iterator i;
04471 
04472    switch (argc) {
04473    case 5:
04474       if (!strcasecmp(argv[3], "like")) {
04475          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04476             return RESULT_SHOWUSAGE;
04477          havepattern = 1;
04478       } else
04479          return RESULT_SHOWUSAGE;
04480    case 3:
04481       break;
04482    default:
04483       return RESULT_SHOWUSAGE;
04484    }
04485 
04486    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04487    i = ao2_iterator_init(users, 0);
04488    for (user = ao2_iterator_next(&i); user; 
04489       user_unref(user), user = ao2_iterator_next(&i)) {
04490       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04491          continue;
04492       
04493       if (!ast_strlen_zero(user->secret)) {
04494          ast_copy_string(auth,user->secret,sizeof(auth));
04495       } else if (!ast_strlen_zero(user->inkeys)) {
04496          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04497       } else
04498          ast_copy_string(auth, "-no secret-", sizeof(auth));
04499       
04500       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04501          pstr = "REQ Only";
04502       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04503          pstr = "Disabled";
04504       else
04505          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04506       
04507       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04508          user->contexts ? user->contexts->context : context,
04509          user->ha ? "Yes" : "No", pstr);
04510    }
04511 
04512    if (havepattern)
04513       regfree(&regexbuf);
04514 
04515    return RESULT_SUCCESS;
04516 #undef FORMAT
04517 #undef FORMAT2
04518 }

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

Definition at line 3439 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03440 {
03441    int res;
03442    struct iax_ie_data ied0;
03443    struct iax_ie_data ied1;
03444    unsigned int transferid = (unsigned int)ast_random();
03445    memset(&ied0, 0, sizeof(ied0));
03446    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03447    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03448    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03449 
03450    memset(&ied1, 0, sizeof(ied1));
03451    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03452    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03453    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03454    
03455    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03456    if (res)
03457       return -1;
03458    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03459    if (res)
03460       return -1;
03461    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03462    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03463    return 0;
03464 }

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

Definition at line 2265 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02266 {
02267        if (argc != 4)
02268                return RESULT_SHOWUSAGE;
02269 
02270        test_losspct = atoi(argv[3]);
02271 
02272        return RESULT_SUCCESS;
02273 }

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

Definition at line 3685 of file chan_iax2.c.

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

03686 {
03687    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03688    struct iax_ie_data ied;
03689    char tmp[256], *context;
03690    ast_copy_string(tmp, dest, sizeof(tmp));
03691    context = strchr(tmp, '@');
03692    if (context) {
03693       *context = '\0';
03694       context++;
03695    }
03696    memset(&ied, 0, sizeof(ied));
03697    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03698    if (context)
03699       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03700    if (option_debug)
03701       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03702    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03703 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

02725 {
02726    /* Lock the queue and place this packet at the end */
02727    /* By setting this to 0, the network thread will send it for us, and
02728       queue retransmission if necessary */
02729    fr->sentyet = 0;
02730    AST_LIST_LOCK(&iaxq.queue);
02731    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02732    iaxq.count++;
02733    AST_LIST_UNLOCK(&iaxq.queue);
02734    /* Wake up the network and scheduler thread */
02735    if (netthreadid != AST_PTHREADT_NULL)
02736       pthread_kill(netthreadid, SIGURG);
02737    signal_condition(&sched_lock, &sched_cond);
02738    return 0;
02739 }

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

Definition at line 6567 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

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

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

Definition at line 4048 of file chan_iax2.c.

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

04049 {
04050    struct ast_frame *f;
04051    struct iax2_trunk_peer *tpeer;
04052    void *tmp, *ptr;
04053    struct ast_iax2_meta_trunk_entry *met;
04054    struct ast_iax2_meta_trunk_mini *mtm;
04055 
04056    f = &fr->af;
04057    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
04058    if (tpeer) {
04059       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
04060          /* Need to reallocate space */
04061          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
04062             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
04063                ast_mutex_unlock(&tpeer->lock);
04064                return -1;
04065             }
04066             
04067             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
04068             tpeer->trunkdata = tmp;
04069             if (option_debug)
04070                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);
04071          } else {
04072             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));
04073             ast_mutex_unlock(&tpeer->lock);
04074             return -1;
04075          }
04076       }
04077 
04078       /* Append to meta frame */
04079       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
04080       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
04081          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
04082          mtm->len = htons(f->datalen);
04083          mtm->mini.callno = htons(pvt->callno);
04084          mtm->mini.ts = htons(0xffff & fr->ts);
04085          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
04086          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
04087       } else {
04088          met = (struct ast_iax2_meta_trunk_entry *)ptr;
04089          /* Store call number and length in meta header */
04090          met->callno = htons(pvt->callno);
04091          met->len = htons(f->datalen);
04092          /* Advance pointers/decrease length past trunk entry header */
04093          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
04094          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
04095       }
04096       /* Copy actual trunk data */
04097       memcpy(ptr, f->data, f->datalen);
04098       tpeer->trunkdatalen += f->datalen;
04099 
04100       tpeer->calls++;
04101       ast_mutex_unlock(&tpeer->lock);
04102    }
04103    return 0;
04104 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6484 of file chan_iax2.c.

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

Referenced by socket_process().

06485 {
06486    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06487 }

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

Definition at line 4991 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, error(), ast_frame::frametype, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, LOG_DEBUG, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.

04992 {
04993    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04994    int res = -1;
04995    ast_mutex_lock(&iaxsl[callno]);
04996    if (iaxs[callno]) {
04997    /* If there's an outstanding error, return failure now */
04998       if (!iaxs[callno]->error) {
04999          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
05000             res = 0;
05001             /* Don't waste bandwidth sending null frames */
05002          else if (f->frametype == AST_FRAME_NULL)
05003             res = 0;
05004          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
05005             res = 0;
05006          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
05007             res = 0;
05008          else
05009          /* Simple, just queue for transmission */
05010             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
05011       } else {
05012          if (option_debug)
05013             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
05014       }
05015    }
05016    /* If it's already gone, just return */
05017    ast_mutex_unlock(&iaxsl[callno]);
05018    return res;
05019 }

static int iax_check_version ( char *  dev  )  [static]

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

01900 {
01901    int res = 0;
01902    struct iax_firmware *cur;
01903    if (!ast_strlen_zero(dev)) {
01904       ast_mutex_lock(&waresl.lock);
01905       cur = waresl.wares;
01906       while(cur) {
01907          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01908             res = ntohs(cur->fwh->version);
01909             break;
01910          }
01911          cur = cur->next;
01912       }
01913       ast_mutex_unlock(&waresl.lock);
01914    }
01915    return res;
01916 }

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

Definition at line 765 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

00766 {
00767    if (iaxdebug)
00768       ast_verbose("%s", data);
00769 }

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

Definition at line 771 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00772 {
00773    ast_log(LOG_WARNING, "%s", data);
00774 }

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

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

01919 {
01920    int res = -1;
01921    unsigned int bs = desc & 0xff;
01922    unsigned int start = (desc >> 8) & 0xffffff;
01923    unsigned int bytes;
01924    struct iax_firmware *cur;
01925    if (!ast_strlen_zero((char *)dev) && bs) {
01926       start *= bs;
01927       ast_mutex_lock(&waresl.lock);
01928       cur = waresl.wares;
01929       while(cur) {
01930          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01931             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01932             if (start < ntohl(cur->fwh->datalen)) {
01933                bytes = ntohl(cur->fwh->datalen) - start;
01934                if (bytes > bs)
01935                   bytes = bs;
01936                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01937             } else {
01938                bytes = 0;
01939                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01940             }
01941             if (bytes == bs)
01942                res = 0;
01943             else
01944                res = 1;
01945             break;
01946          }
01947          cur = cur->next;
01948       }
01949       ast_mutex_unlock(&waresl.lock);
01950    }
01951    return res;
01952 }

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

Definition at line 6755 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

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

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

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

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

01414 {
01415    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01416    if (new) {
01417       size_t afdatalen = new->afdatalen;
01418       memcpy(new, fr, sizeof(*new));
01419       iax_frame_wrap(new, &fr->af);
01420       new->afdatalen = afdatalen;
01421       new->data = NULL;
01422       new->datalen = 0;
01423       new->direction = DIRECTION_INGRESS;
01424       new->retrans = -1;
01425    }
01426    return new;
01427 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 895 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, and IAX_TYPE_DYNAMIC.

Referenced by iax2_process_thread().

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

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

Definition at line 800 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 776 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 788 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 11126 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_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, option_verbose, papp, pdescrip, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, psyn, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.

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

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

Definition at line 3466 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03467 {
03468    ast_mutex_lock(&iaxsl[callno0]);
03469    while (ast_mutex_trylock(&iaxsl[callno1])) {
03470       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03471    }
03472 }

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

Definition at line 1467 of file chan_iax2.c.

References ARRAY_LEN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, chan_iax2_pvt::callno, iax2_sched_add(), iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, option_debug, chan_iax2_pvt::pingid, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().

Referenced by iax2_request(), and socket_process().

01468 {
01469    int x;
01470    int res= 0;
01471    struct timeval now;
01472    if (iaxs[callno]->oseqno) {
01473       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01474       return -1;
01475    }
01476    if (callno & TRUNK_CALL_START) {
01477       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01478       return -1;
01479    }
01480    gettimeofday(&now, NULL);
01481    for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
01482       ast_mutex_lock(&iaxsl[x]);
01483       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01484          iaxs[x] = iaxs[callno];
01485          iaxs[x]->callno = x;
01486          iaxs[callno] = NULL;
01487          /* Update the two timers that should have been started */
01488          AST_SCHED_DEL(sched, iaxs[x]->pingid);
01489          AST_SCHED_DEL(sched, iaxs[x]->lagid);
01490          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01491          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01492          if (locked)
01493             ast_mutex_unlock(&iaxsl[callno]);
01494          res = x;
01495          if (!locked)
01496             ast_mutex_unlock(&iaxsl[x]);
01497          break;
01498       }
01499       ast_mutex_unlock(&iaxsl[x]);
01500    }
01501    if (x >= ARRAY_LEN(iaxs) - 1) {
01502       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01503       return -1;
01504    }
01505    if (option_debug)
01506       ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
01507    /* We move this call from a non-trunked to a trunked call */
01508    update_max_trunk();
01509    update_max_nontrunk();
01510    return res;
01511 }

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

Definition at line 4705 of file chan_iax2.c.

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

Referenced by load_module().

04706 {
04707    ast_cli_netstats(s, -1, 0);
04708    astman_append(s, "\r\n");
04709    return RESULT_SUCCESS;
04710 }

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

Definition at line 4738 of file chan_iax2.c.

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

Referenced by load_module().

04739 {
04740    char *a[] = { "iax2", "show", "users" };
04741    int ret;
04742    const char *id = astman_get_header(m,"ActionID");
04743 
04744    if (!ast_strlen_zero(id))
04745       astman_append(s, "ActionID: %s\r\n",id);
04746    ret = __iax2_show_peers(1, -1, s, 3, a );
04747    astman_append(s, "\r\n\r\n" );
04748    return ret;
04749 } /* /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 1433 of file chan_iax2.c.

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

Referenced by __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().

01434 {
01435    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01436       (cur->addr.sin_port == sin->sin_port)) {
01437       /* This is the main host */
01438       if ( (cur->peercallno == 0 || cur->peercallno == callno) &&
01439           (check_dcallno ? dcallno == cur->callno : 1) ) {
01440          /* That's us.  Be sure we keep track of the peer call number */
01441          return 1;
01442       }
01443    }
01444    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01445        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01446       /* We're transferring */
01447       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01448          return 1;
01449    }
01450    return 0;
01451 }

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

Definition at line 4112 of file chan_iax2.c.

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

Referenced by decode_frame().

04113 {
04114 #if 0
04115    /* Debug with "fake encryption" */
04116    int x;
04117    if (len % 16)
04118       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04119    for (x=0;x<len;x++)
04120       dst[x] = src[x] ^ 0xff;
04121 #else 
04122    unsigned char lastblock[16] = { 0 };
04123    int x;
04124    while(len > 0) {
04125       aes_decrypt(src, dst, dcx);
04126       for (x=0;x<16;x++)
04127          dst[x] ^= lastblock[x];
04128       memcpy(lastblock, src, sizeof(lastblock));
04129       dst += 16;
04130       src += 16;
04131       len -= 16;
04132    }
04133 #endif
04134 }

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

Definition at line 4136 of file chan_iax2.c.

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

Referenced by encrypt_frame().

04137 {
04138 #if 0
04139    /* Debug with "fake encryption" */
04140    int x;
04141    if (len % 16)
04142       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04143    for (x=0;x<len;x++)
04144       dst[x] = src[x] ^ 0xff;
04145 #else
04146    unsigned char curblock[16] = { 0 };
04147    int x;
04148    while(len > 0) {
04149       for (x=0;x<16;x++)
04150          curblock[x] ^= src[x];
04151       aes_encrypt(curblock, dst, ecx);
04152       memcpy(curblock, dst, sizeof(curblock)); 
04153       dst += 16;
04154       src += 16;
04155       len -= 16;
04156    }
04157 #endif
04158 }

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

Definition at line 5328 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05329 {
05330    /* Select exactly one common encryption if there are any */
05331    p->encmethods &= enc;
05332    if (p->encmethods) {
05333       if (p->encmethods & IAX_ENCRYPT_AES128)
05334          p->encmethods = IAX_ENCRYPT_AES128;
05335       else
05336          p->encmethods = 0;
05337    }
05338 }

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

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

Referenced by start_network_thread().

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

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

Definition at line 1374 of file chan_iax2.c.

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

Referenced by __find_callno().

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

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

03185 {
03186    if (ast_strlen_zero(data))
03187       return;
03188 
03189    pds->peer = strsep(&data, "/");
03190    pds->exten = strsep(&data, "/");
03191    pds->options = data;
03192 
03193    if (pds->exten) {
03194       data = pds->exten;
03195       pds->exten = strsep(&data, "@");
03196       pds->context = data;
03197    }
03198 
03199    if (strchr(pds->peer, '@')) {
03200       data = pds->peer;
03201       pds->username = strsep(&data, "@");
03202       pds->peer = data;
03203    }
03204 
03205    if (pds->username) {
03206       data = pds->username;
03207       pds->username = strsep(&data, ":");
03208       pds->password = data;
03209    }
03210 
03211    data = pds->peer;
03212    pds->peer = strsep(&data, ":");
03213    pds->port = data;
03214 
03215    /* check for a key name wrapped in [] in the secret position, if found,
03216       move it to the key field instead
03217    */
03218    if (pds->password && (pds->password[0] == '[')) {
03219       pds->key = ast_strip_quoted(pds->password, "[", "]");
03220       pds->password = NULL;
03221    }
03222 }

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

Referenced by load_module().

01113 {
01114    struct iax2_peer *peer = obj, *peer2 = arg;
01115 
01116    return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
01117 }

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

Definition at line 9797 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09798 {
09799    struct iax2_peer *peer = obj;
09800 
09801    ast_set_flag(peer, IAX_DELME);
09802 
09803    return 0;
09804 }

static void peer_destructor ( void *  obj  )  [static]

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

09323 {
09324    struct iax2_peer *peer = obj;
09325 
09326    ast_free_ha(peer->ha);
09327 
09328    if (peer->callno > 0) {
09329       ast_mutex_lock(&iaxsl[peer->callno]);
09330       iax2_destroy(peer->callno);
09331       ast_mutex_unlock(&iaxsl[peer->callno]);
09332    }
09333 
09334    register_peer_exten(peer, 0);
09335 
09336    if (peer->dnsmgr)
09337       ast_dnsmgr_release(peer->dnsmgr);
09338 
09339    ast_string_field_free_memory(peer);
09340 }

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

References ast_str_hash().

Referenced by load_module().

01103 {
01104    const struct iax2_peer *peer = obj;
01105 
01106    return ast_str_hash(peer->name);
01107 }

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

Definition at line 1159 of file chan_iax2.c.

References ao2_ref().

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

01160 {
01161    ao2_ref(peer, +1);
01162    return peer;
01163 }

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

Definition at line 11097 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

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

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

References iax2_registry::addr, ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, LOG_DEBUG, LOG_WARNING, option_debug, socket_read(), iax2_peer::sockfd, and strsep().

Referenced by build_peer().

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

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

peer_status: Report Peer status in character string

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

02312 {
02313    int res = 0;
02314    if (peer->maxms) {
02315       if (peer->lastms < 0) {
02316          ast_copy_string(status, "UNREACHABLE", statuslen);
02317       } else if (peer->lastms > peer->maxms) {
02318          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02319          res = 1;
02320       } else if (peer->lastms) {
02321          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02322          res = 1;
02323       } else {
02324          ast_copy_string(status, "UNKNOWN", statuslen);
02325       }
02326    } else { 
02327       ast_copy_string(status, "Unmonitored", statuslen);
02328       res = -1;
02329    }
02330    return res;
02331 }

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

static void poke_all_peers ( void   )  [static]

Definition at line 10258 of file chan_iax2.c.

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

Referenced by reload_config().

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

static void prune_peers ( void   )  [static]

Definition at line 9855 of file chan_iax2.c.

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

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

static void prune_users ( void   )  [static]

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

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

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

Definition at line 11114 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

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

static void pvt_destructor ( void *  obj  )  [static]

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

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

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

Definition at line 11107 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

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

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

Definition at line 5310 of file chan_iax2.c.

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

Referenced by socket_process().

05311 {
05312    struct ast_iax2_full_hdr fh;
05313    fh.scallno = htons(src | IAX_FLAG_FULL);
05314    fh.dcallno = htons(dst);
05315    fh.ts = 0;
05316    fh.oseqno = 0;
05317    fh.iseqno = 0;
05318    fh.type = AST_FRAME_IAX;
05319    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05320    if (iaxdebug)
05321        iax_showframe(NULL, &fh, 0, sin, 0);
05322    if (option_debug)
05323       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05324          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05325    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05326 }

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

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

References iax2_peer::addr, ast_copy_flags, ast_get_time_t(), ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_log(), ast_sched_del(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_peer(), iax2_peer::expire, expire_registry(), hp, iax2_sched_add(), IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_TEMPONLY, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, peer_ref(), peer_unref(), peers, realtime_update_peer(), reg_source_db(), ast_variable::value, and var.

02787 {
02788    struct ast_variable *var = NULL;
02789    struct ast_variable *tmp;
02790    struct iax2_peer *peer=NULL;
02791    time_t regseconds = 0, nowtime;
02792    int dynamic=0;
02793 
02794    if (peername) {
02795       var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL);
02796       if (!var && sin)
02797          var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02798    } else if (sin) {
02799       char porta[25];
02800       sprintf(porta, "%d", ntohs(sin->sin_port));
02801       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02802       if (var) {
02803          /* We'll need the peer name in order to build the structure! */
02804          for (tmp = var; tmp; tmp = tmp->next) {
02805             if (!strcasecmp(tmp->name, "name"))
02806                peername = tmp->value;
02807          }
02808       }
02809    }
02810    if (!var && peername) { /* Last ditch effort */
02811       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
02812       /*!\note
02813        * If this one loaded something, then we need to ensure that the host
02814        * field matched.  The only reason why we can't have this as a criteria
02815        * is because we only have the IP address and the host field might be
02816        * set as a name (and the reverse PTR might not match).
02817        */
02818       if (var && sin) {
02819          for (tmp = var; tmp; tmp = tmp->next) {
02820             if (!strcasecmp(tmp->name, "host")) {
02821                struct ast_hostent ahp;
02822                struct hostent *hp;
02823                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02824                   /* No match */
02825                   ast_variables_destroy(var);
02826                   var = NULL;
02827                }
02828                break;
02829             }
02830          }
02831       }
02832    }
02833    if (!var)
02834       return NULL;
02835 
02836    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
02837    
02838    if (!peer) {
02839       ast_variables_destroy(var);
02840       return NULL;
02841    }
02842 
02843    for (tmp = var; tmp; tmp = tmp->next) {
02844       /* Make sure it's not a user only... */
02845       if (!strcasecmp(tmp->name, "type")) {
02846          if (strcasecmp(tmp->value, "friend") &&
02847              strcasecmp(tmp->value, "peer")) {
02848             /* Whoops, we weren't supposed to exist! */
02849             peer = peer_unref(peer);
02850             break;
02851          } 
02852       } else if (!strcasecmp(tmp->name, "regseconds")) {
02853          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
02854       } else if (!strcasecmp(tmp->name, "ipaddr")) {
02855          inet_aton(tmp->value, &(peer->addr.sin_addr));
02856       } else if (!strcasecmp(tmp->name, "port")) {
02857          peer->addr.sin_port = htons(atoi(tmp->value));
02858       } else if (!strcasecmp(tmp->name, "host")) {
02859          if (!strcasecmp(tmp->value, "dynamic"))
02860             dynamic = 1;
02861       }
02862    }
02863 
02864    ast_variables_destroy(var);
02865 
02866    if (!peer)
02867       return NULL;
02868 
02869    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02870       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
02871       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
02872          if (peer->expire > -1) {
02873             if (!ast_sched_del(sched, peer->expire)) {
02874                peer->expire = -1;
02875                peer_unref(peer);
02876             }
02877          }
02878          peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
02879          if (peer->expire == -1)
02880             peer_unref(peer);
02881       }
02882       ao2_link(peers, peer);
02883       if (ast_test_flag(peer, IAX_DYNAMIC))
02884          reg_source_db(peer);
02885    } else {
02886       ast_set_flag(peer, IAX_TEMPONLY);   
02887    }
02888 
02889    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
02890       time(&nowtime);
02891       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
02892          memset(&peer->addr, 0, sizeof(peer->addr));
02893          realtime_update_peer(peer->name, &peer->addr, 0);
02894          if (option_debug)
02895             ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
02896                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02897       }
02898       else {
02899          if (option_debug)
02900             ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
02901                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02902       }
02903    }
02904 
02905    return peer;
02906 }

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

Definition at line 2979 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02980 {
02981    char port[10];
02982    char regseconds[20];
02983    
02984    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
02985    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
02986    ast_update_realtime("iaxpeers", "name", peername, 
02987       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
02988       "regseconds", regseconds, NULL);
02989 }

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

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

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

02909 {
02910    struct ast_variable *var;
02911    struct ast_variable *tmp;
02912    struct iax2_user *user=NULL;
02913 
02914    var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL);
02915    if (!var)
02916       var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02917    if (!var && sin) {
02918       char porta[6];
02919       snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port));
02920       var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02921       if (!var)
02922          var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02923    }
02924    if (!var) { /* Last ditch effort */
02925       var = ast_load_realtime("iaxusers", "name", username, NULL);
02926       /*!\note
02927        * If this one loaded something, then we need to ensure that the host
02928        * field matched.  The only reason why we can't have this as a criteria
02929        * is because we only have the IP address and the host field might be
02930        * set as a name (and the reverse PTR might not match).
02931        */
02932       if (var) {
02933          for (tmp = var; tmp; tmp = tmp->next) {
02934             if (!strcasecmp(tmp->name, "host")) {
02935                struct ast_hostent ahp;
02936                struct hostent *hp;
02937                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02938                   /* No match */
02939                   ast_variables_destroy(var);
02940                   var = NULL;
02941                }
02942                break;
02943             }
02944          }
02945       }
02946    }
02947    if (!var)
02948       return NULL;
02949 
02950    tmp = var;
02951    while(tmp) {
02952       /* Make sure it's not a peer only... */
02953       if (!strcasecmp(tmp->name, "type")) {
02954          if (strcasecmp(tmp->value, "friend") &&
02955              strcasecmp(tmp->value, "user")) {
02956             return NULL;
02957          } 
02958       }
02959       tmp = tmp->next;
02960    }
02961 
02962    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
02963 
02964    ast_variables_destroy(var);
02965 
02966    if (!user)
02967       return NULL;
02968 
02969    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02970       ast_set_flag(user, IAX_RTCACHEFRIENDS);
02971       ao2_link(users, user);
02972    } else {
02973       ast_set_flag(user, IAX_TEMPONLY);   
02974    }
02975 
02976    return user;
02977 }

static void reg_source_db ( struct iax2_peer p  )  [static]

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

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

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

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

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

06035 {
06036    char multi[256];
06037    char *stringp, *ext;
06038    if (!ast_strlen_zero(regcontext)) {
06039       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
06040       stringp = multi;
06041       while((ext = strsep(&stringp, "&"))) {
06042          if (onoff) {
06043             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
06044                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
06045                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
06046          } else
06047             ast_context_remove_extension(regcontext, ext, 1, NULL);
06048       }
06049    }
06050 }

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

Verify inbound registration.

Definition at line 5477 of file chan_iax2.c.

References ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_device_state_changed(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, iax2_registry::expire, chan_iax2_pvt::expiry, expiry, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, iaxs, iaxsl, LOG_NOTICE, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, peer_unref(), iax_ies::refresh, iax_ies::rsa_result, iax2_registry::secret, strsep(), and iax_ies::username.

Referenced by handle_request_register(), and socket_process().

05478 {
05479    char requeststr[256] = "";
05480    char peer[256] = "";
05481    char md5secret[256] = "";
05482    char rsasecret[256] = "";
05483    char secret[256] = "";
05484    struct iax2_peer *p = NULL;
05485    struct ast_key *key;
05486    char *keyn;
05487    int x;
05488    int expire = 0;
05489    int res = -1;
05490 
05491    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05492    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05493    if (ies->username)
05494       ast_copy_string(peer, ies->username, sizeof(peer));
05495    if (ies->password)
05496       ast_copy_string(secret, ies->password, sizeof(secret));
05497    if (ies->md5_result)
05498       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05499    if (ies->rsa_result)
05500       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05501    if (ies->refresh)
05502       expire = ies->refresh;
05503 
05504    if (ast_strlen_zero(peer)) {
05505       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05506       return -1;
05507    }
05508 
05509    /* SLD: first call to lookup peer during registration */
05510    ast_mutex_unlock(&iaxsl[callno]);
05511    p = find_peer(peer, 1);
05512    ast_mutex_lock(&iaxsl[callno]);
05513    if (!p || !iaxs[callno]) {
05514       if (iaxs[callno]) {
05515          int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT));
05516 
05517          ast_string_field_set(iaxs[callno], secret, "badsecret");
05518 
05519          /* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless
05520           * 1. A challenge already exists indicating a AUTHREQ was already sent out.
05521           * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it.
05522           * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened
05523           *    to be plaintext, indicating it is an authmethod used by other peers on the system. 
05524           *
05525           * If none of these cases exist, res will be returned as 0 without authentication indicating
05526           * an AUTHREQ needs to be sent out. */
05527 
05528          if (ast_strlen_zero(iaxs[callno]->challenge) &&
05529             !(!ast_strlen_zero(secret) && plaintext)) {
05530             /* by setting res to 0, an REGAUTH will be sent */
05531             res = 0;
05532          }
05533       }
05534       if (authdebug && !p)
05535          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05536 
05537       goto return_unref;
05538    }
05539 
05540    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05541       if (authdebug)
05542          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05543       goto return_unref;
05544    }
05545 
05546    if (!ast_apply_ha(p->ha, sin)) {
05547       if (authdebug)
05548          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05549       goto return_unref;
05550    }
05551    ast_string_field_set(iaxs[callno], secret, p->secret);
05552    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05553    /* Check secret against what we have on file */
05554    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05555       if (!ast_strlen_zero(p->inkeys)) {
05556          char tmpkeys[256];
05557          char *stringp=NULL;
05558          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05559          stringp=tmpkeys;
05560          keyn = strsep(&stringp, ":");
05561          while(keyn) {
05562             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05563             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05564                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05565                break;
05566             } else if (!key)
05567                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05568             keyn = strsep(&stringp, ":");
05569          }
05570          if (!keyn) {
05571             if (authdebug)
05572                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05573             goto return_unref;
05574          }
05575       } else {
05576          if (authdebug)
05577             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05578          goto return_unref;
05579       }
05580    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05581       struct MD5Context md5;
05582       unsigned char digest[16];
05583       char *tmppw, *stringp;
05584 
05585       tmppw = ast_strdupa(p->secret);
05586       stringp = tmppw;
05587       while((tmppw = strsep(&stringp, ";"))) {
05588          MD5Init(&md5);
05589          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05590          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05591          MD5Final(digest, &md5);
05592          for (x=0;x<16;x++)
05593             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05594          if (!strcasecmp(requeststr, md5secret))
05595             break;
05596       }
05597       if (tmppw) {
05598          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05599       } else {
05600          if (authdebug)
05601             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05602          goto return_unref;
05603       }
05604    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05605       /* They've provided a plain text password and we support that */
05606       if (strcmp(secret, p->secret)) {
05607          if (authdebug)
05608             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05609          goto return_unref;
05610       } else
05611          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05612    } else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) {
05613       /* if challenge has been sent, but no challenge response if given, reject. */
05614       goto return_unref;
05615    }
05616    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05617 
05618    /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */
05619    res = 0;
05620 return_unref:
05621    if (iaxs[callno]) {
05622       ast_string_field_set(iaxs[callno], peer, peer);
05623    }
05624    /* Choose lowest expiry number */
05625    if (expire && (expire < iaxs[callno]->expiry)) {
05626       iaxs[callno]->expiry = expire;
05627    }
05628 
05629    if (p)
05630       peer_unref(p);
05631    return res;
05632 }

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6293 of file chan_iax2.c.

References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strdupa, ast_string_field_set, chan_iax2_pvt::authmethods, iax2_peer::authmethods, iax_ie_data::buf, find_peer(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, 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, peer_unref(), iax_ie_data::pos, and send_command().

Referenced by socket_process().

06294 {
06295    struct iax_ie_data ied;
06296    struct iax2_peer *p;
06297    char challenge[10];
06298    const char *peer_name;
06299    int sentauthmethod;
06300 
06301    peer_name = ast_strdupa(iaxs[callno]->peer);
06302 
06303    /* SLD: third call to find_peer in registration */
06304    ast_mutex_unlock(&iaxsl[callno]);
06305    if ((p = find_peer(peer_name, 1))) {
06306       last_authmethod = p->authmethods;
06307    }
06308 
06309    ast_mutex_lock(&iaxsl[callno]);
06310    if (!iaxs[callno])
06311       goto return_unref;
06312 
06313    memset(&ied, 0, sizeof(ied));
06314    /* The selection of which delayed reject is sent may leak information,
06315     * if it sets a static response.  For example, if a host is known to only
06316     * use MD5 authentication, then an RSA response would indicate that the
06317     * peer does not exist, and vice-versa.
06318     * Therefore, we use whatever the last peer used (which may vary over the
06319     * course of a server, which should leak minimal information). */
06320    sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
06321    if (!p) {
06322       iaxs[callno]->authmethods = sentauthmethod;
06323    }
06324    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
06325    if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06326       /* Build the challenge */
06327       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06328       ast_string_field_set(iaxs[callno], challenge, challenge);
06329       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06330    }
06331    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06332 
06333 return_unref:
06334    if (p) {
06335       peer_unref(p);
06336    }
06337 
06338    return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1;
06339 }

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

Definition at line 6341 of file chan_iax2.c.

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

Referenced by socket_process().

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

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4751 of file chan_iax2.c.

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

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

04752 {
04753    switch(regstate) {
04754    case REG_STATE_UNREGISTERED:
04755       return "Unregistered";
04756    case REG_STATE_REGSENT:
04757       return "Request Sent";
04758    case REG_STATE_AUTHSENT:
04759       return "Auth. Sent";
04760    case REG_STATE_REGISTERED:
04761       return "Registered";
04762    case REG_STATE_REJECTED:
04763       return "Rejected";
04764    case REG_STATE_TIMEOUT:
04765       return "Timeout";
04766    case REG_STATE_NOAUTH:
04767       return "No Authentication";
04768    default:
04769       return "Unknown";
04770    }
04771 }

static int reload ( void   )  [static]

Definition at line 10295 of file chan_iax2.c.

References reload_config().

10296 {
10297    return reload_config();
10298 }

static int reload_config ( void   )  [static]

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

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

static void reload_firmware ( int  unload  )  [static]

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

01956 {
01957    struct iax_firmware *cur, *curl, *curp;
01958    DIR *fwd;
01959    struct dirent *de;
01960    char dir[256];
01961    char fn[256];
01962    /* Mark all as dead */
01963    ast_mutex_lock(&waresl.lock);
01964    cur = waresl.wares;
01965    while(cur) {
01966       cur->dead = 1;
01967       cur = cur->next;
01968    }
01969 
01970    /* Now that we've freed them, load the new ones */
01971    if (!unload) {
01972       snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
01973       fwd = opendir(dir);
01974       if (fwd) {
01975          while((de = readdir(fwd))) {
01976             if (de->d_name[0] != '.') {
01977                snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
01978                if (!try_firmware(fn)) {
01979                   if (option_verbose > 1)
01980                      ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
01981                }
01982             }
01983          }
01984          closedir(fwd);
01985       } else 
01986          ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
01987    }
01988 
01989    /* Clean up leftovers */
01990    cur = waresl.wares;
01991    curp = NULL;
01992    while(cur) {
01993       curl = cur;
01994       cur = cur->next;
01995       if (curl->dead) {
01996          if (curp) {
01997             curp->next = cur;
01998          } else {
01999             waresl.wares = cur;
02000          }
02001          destroy_firmware(curl);
02002       } else {
02003          curp = cur;
02004       }
02005    }
02006    ast_mutex_unlock(&waresl.lock);
02007 }

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

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

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

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

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

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

Referenced by start_network_thread().

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

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

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

Referenced by socket_process().

02640 {
02641    int type, len;
02642    int ret;
02643    int needfree = 0;
02644    struct ast_channel *owner = NULL;
02645    struct ast_channel *bridge = NULL;
02646    
02647    /* Attempt to recover wrapped timestamps */
02648    unwrap_timestamp(fr);
02649 
02650    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02651    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02652       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02653    else {
02654 #if 0
02655       if (option_debug)
02656          ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02657 #endif
02658       fr->af.delivery = ast_tv(0,0);
02659    }
02660 
02661    type = JB_TYPE_CONTROL;
02662    len = 0;
02663 
02664    if(fr->af.frametype == AST_FRAME_VOICE) {
02665       type = JB_TYPE_VOICE;
02666       len = ast_codec_get_samples(&fr->af) / 8;
02667    } else if(fr->af.frametype == AST_FRAME_CNG) {
02668       type = JB_TYPE_SILENCE;
02669    }
02670 
02671    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02672       if (tsout)
02673          *tsout = fr->ts;
02674       __do_deliver(fr);
02675       return -1;
02676    }
02677 
02678    if ((owner = iaxs[fr->callno]->owner))
02679       bridge = ast_bridged_channel(owner);
02680 
02681    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02682     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02683    if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
02684       jb_frame frame;
02685 
02686       /* deliver any frames in the jb */
02687       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
02688          __do_deliver(frame.data);
02689          /* __do_deliver() can make the call disappear */
02690          if (!iaxs[fr->callno])
02691             return -1;
02692       }
02693 
02694       jb_reset(iaxs[fr->callno]->jb);
02695 
02696       AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
02697 
02698       /* deliver this frame now */
02699       if (tsout)
02700          *tsout = fr->ts;
02701       __do_deliver(fr);
02702       return -1;
02703    }
02704 
02705    /* insert into jitterbuffer */
02706    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02707    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02708          calc_rxstamp(iaxs[fr->callno],fr->ts));
02709    if (ret == JB_DROP) {
02710       needfree++;
02711    } else if (ret == JB_SCHED) {
02712       update_jbsched(iaxs[fr->callno]);
02713    }
02714    if (tsout)
02715       *tsout = fr->ts;
02716    if (needfree) {
02717       /* Free our iax frame */
02718       iax2_frame_free(fr);
02719       return -1;
02720    }
02721    return 0;
02722 }

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

References AST_FRAME_IAX, compress_subclass(), and ast_iax2_full_hdr::scallno.

Referenced by socket_process().

03158 {
03159    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03160       .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX,
03161       .csub = compress_subclass(command) };
03162 
03163    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03164 }

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

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

05055 {
05056    int call_num = i->callno;
05057    /* It is assumed that the callno has already been locked */
05058    iax2_predestroy(i->callno);
05059    if (!iaxs[call_num])
05060       return -1;
05061    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05062 }

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

Definition at line 5064 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05065 {
05066    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05067 }

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

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

05041 {
05042    int res;
05043    ast_mutex_lock(&iaxsl[callno]);
05044    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05045    ast_mutex_unlock(&iaxsl[callno]);
05046    return res;
05047 }

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

Definition at line 5069 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

05070 {
05071    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05072 }

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

Definition at line 1056 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

01057 {
01058 #ifdef SCHED_MULTITHREADED
01059    if (schedule_action(__send_lagrq, data))
01060 #endif      
01061       __send_lagrq(data);
01062    return 0;
01063 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 2080 of file chan_iax2.c.

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

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

02081 {
02082    int res;
02083    int callno = f->callno;
02084 
02085    /* Don't send if there was an error, but return error instead */
02086    if (!callno || !iaxs[callno] || iaxs[callno]->error)
02087        return -1;
02088    
02089    /* Called with iaxsl held */
02090    if (option_debug > 2 && iaxdebug)
02091       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));
02092    if (f->transfer) {
02093       if (iaxdebug)
02094          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
02095       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
02096                sizeof(iaxs[callno]->transfer));
02097    } else {
02098       if (iaxdebug)
02099          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
02100       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
02101                sizeof(iaxs[callno]->addr));
02102    }
02103    if (res < 0) {
02104       if (option_debug && iaxdebug)
02105          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02106       handle_error();
02107    } else
02108       res = 0;
02109    return res;
02110 }

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

Definition at line 1016 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

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

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

Definition at line 6523 of file chan_iax2.c.

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

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

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

Load configuration.

Definition at line 9899 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(), 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, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_PEER_BUCKETS, ast_variable::name, ast_variable::next, option_verbose, peer_unref(), peers, portno, prefs, reg_source_db(), iax2_registry::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().

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

static void set_config_destroy ( void   )  [static]

Definition at line 9883 of file chan_iax2.c.

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

Referenced by set_config().

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

static void set_timing ( void   )  [static]

Definition at line 9868 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09869 {
09870 #ifdef HAVE_ZAPTEL
09871    int bs = trunkfreq * 8;
09872    if (timingfd > -1) {
09873       if (
09874 #ifdef ZT_TIMERACK
09875          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09876 #endif         
09877          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09878          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09879    }
09880 #endif
09881 }

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

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

00759 {
00760    ast_mutex_lock(lock);
00761    ast_cond_signal(cond);
00762    ast_mutex_unlock(lock);
00763 }

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6997 of file chan_iax2.c.

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

Referenced by handle_deferred_full_frames(), and iax2_process_thread().

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

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

Definition at line 6919 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_registry::callno, 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_DEBUG, 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().

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

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

Definition at line 6706 of file chan_iax2.c.

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

Referenced by socket_process().

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

static int start_network_thread ( void   )  [static]

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

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

static void stop_stuff ( int  callno  )  [static]

Definition at line 6388 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06389 {
06390    iax2_destroy_helper(iaxs[callno]);
06391 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

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

01241 {
01242    if (!pvt->peercallno) {
01243       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01244       return;
01245    }
01246 
01247    ao2_link(iax_peercallno_pvts, pvt);
01248 }

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

Definition at line 6575 of file chan_iax2.c.

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

Referenced by network_thread().

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

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

Definition at line 2066 of file chan_iax2.c.

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

Referenced by send_trunk().

02067 {
02068    int res;
02069    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
02070                sizeof(*sin));
02071    if (res < 0) {
02072       if (option_debug)
02073          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02074       handle_error();
02075    } else
02076       res = 0;
02077    return res;
02078 }

static int try_firmware ( char *  s  )  [static]

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

Referenced by reload_firmware().

01755 {
01756    struct stat stbuf;
01757    struct iax_firmware *cur;
01758    int ifd;
01759    int fd;
01760    int res;
01761    
01762    struct ast_iax2_firmware_header *fwh, fwh2;
01763    struct MD5Context md5;
01764    unsigned char sum[16];
01765    unsigned char buf[1024];
01766    int len, chunk;
01767    char *s2;
01768    char *last;
01769    s2 = alloca(strlen(s) + 100);
01770    if (!s2) {
01771       ast_log(LOG_WARNING, "Alloca failed!\n");
01772       return -1;
01773    }
01774    last = strrchr(s, '/');
01775    if (last)
01776       last++;
01777    else
01778       last = s;
01779    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01780    res = stat(s, &stbuf);
01781    if (res < 0) {
01782       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01783       return -1;
01784    }
01785    /* Make sure it's not a directory */
01786    if (S_ISDIR(stbuf.st_mode))
01787       return -1;
01788    ifd = open(s, O_RDONLY);
01789    if (ifd < 0) {
01790       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01791       return -1;
01792    }
01793    fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600);
01794    if (fd < 0) {
01795       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
01796       close(ifd);
01797       return -1;
01798    }
01799    /* Unlink our newly created file */
01800    unlink(s2);
01801    
01802    /* Now copy the firmware into it */
01803    len = stbuf.st_size;
01804    while(len) {
01805       chunk = len;
01806       if (chunk > sizeof(buf))
01807          chunk = sizeof(buf);
01808       res = read(ifd, buf, chunk);
01809       if (res != chunk) {
01810          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01811          close(ifd);
01812          close(fd);
01813          return -1;
01814       }
01815       res = write(fd, buf, chunk);
01816       if (res != chunk) {
01817          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01818          close(ifd);
01819          close(fd);
01820          return -1;
01821       }
01822       len -= chunk;
01823    }
01824    close(ifd);
01825    /* Return to the beginning */
01826    lseek(fd, 0, SEEK_SET);
01827    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
01828       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
01829       close(fd);
01830       return -1;
01831    }
01832    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
01833       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
01834       close(fd);
01835       return -1;
01836    }
01837    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
01838       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
01839       close(fd);
01840       return -1;
01841    }
01842    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
01843       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
01844       close(fd);
01845       return -1;
01846    }
01847    fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
01848    if (fwh == (void *) -1) {
01849       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
01850       close(fd);
01851       return -1;
01852    }
01853    MD5Init(&md5);
01854    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
01855    MD5Final(sum, &md5);
01856    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
01857       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
01858       munmap((void*)fwh, stbuf.st_size);
01859       close(fd);
01860       return -1;
01861    }
01862    cur = waresl.wares;
01863    while(cur) {
01864       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
01865          /* Found a candidate */
01866          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
01867             /* The version we have on loaded is older, load this one instead */
01868             break;
01869          /* This version is no newer than what we have.  Don't worry about it.
01870             We'll consider it a proper load anyhow though */
01871          munmap((void*)fwh, stbuf.st_size);
01872          close(fd);
01873          return 0;
01874       }
01875       cur = cur->next;
01876    }
01877    if (!cur) {
01878       /* Allocate a new one and link it */
01879       if ((cur = ast_calloc(1, sizeof(*cur)))) {
01880          cur->fd = -1;
01881          cur->next = waresl.wares;
01882          waresl.wares = cur;
01883       }
01884    }
01885    if (cur) {
01886       if (cur->fwh) {
01887          munmap((void*)cur->fwh, cur->mmaplen);
01888       }
01889       if (cur->fd > -1)
01890          close(cur->fd);
01891       cur->fwh = fwh;
01892       cur->fd = fd;
01893       cur->mmaplen = stbuf.st_size;
01894       cur->dead = 0;
01895    }
01896    return 0;
01897 }

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

Definition at line 5781 of file chan_iax2.c.

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

Referenced by socket_process().

05782 {
05783    int newcall = 0;
05784    char newip[256];
05785    struct iax_ie_data ied;
05786    struct sockaddr_in new;
05787    
05788    
05789    memset(&ied, 0, sizeof(ied));
05790    if (ies->apparent_addr)
05791       bcopy(ies->apparent_addr, &new, sizeof(new));
05792    if (ies->callno)
05793       newcall = ies->callno;
05794    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05795       ast_log(LOG_WARNING, "Invalid transfer request\n");
05796       return -1;
05797    }
05798    pvt->transfercallno = newcall;
05799    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05800    inet_aton(newip, &pvt->transfer.sin_addr);
05801    pvt->transfer.sin_family = AF_INET;
05802    pvt->transferring = TRANSFER_BEGIN;
05803    pvt->transferid = ies->transferid;
05804    if (ies->transferid)
05805       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05806    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05807    return 0; 
05808 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1085 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01086 {
01087    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01088    if (csub & IAX_FLAG_SC_LOG) {
01089       /* special case for 'compressed' -1 */
01090       if (csub == 0xff)
01091          return -1;
01092       else
01093          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01094    }
01095    else
01096       return csub;
01097 }

static void unlink_peer ( struct iax2_peer peer  )  [static]

Definition at line 6053 of file chan_iax2.c.

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

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

06054 {
06055    if (peer->expire > -1) {
06056       if (!ast_sched_del(sched, peer->expire)) {
06057          peer->expire = -1;
06058          peer_unref(peer);
06059       }
06060    }
06061 
06062    if (peer->pokeexpire > -1) {
06063       if (!ast_sched_del(sched, peer->pokeexpire)) {
06064          peer->pokeexpire = -1;
06065          peer_unref(peer);
06066       }
06067    }
06068 
06069    ao2_unlink(peers, peer);
06070 }

static int unload_module ( void   )  [static]

Definition at line 11091 of file chan_iax2.c.

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

11092 {
11093    ast_custom_function_unregister(&iaxpeer_function);
11094    return __unload_module();
11095 }

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

Definition at line 3474 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03475 {
03476    ast_mutex_unlock(&iaxsl[callno1]);
03477    ast_mutex_unlock(&iaxsl[callno0]);
03478 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

Definition at line 2500 of file chan_iax2.c.

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

Referenced by schedule_delivery().

02501 {
02502    int x;
02503 
02504    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02505       x = fr->ts - iaxs[fr->callno]->last;
02506       if (x < -50000) {
02507          /* Sudden big jump backwards in timestamp:
02508             What likely happened here is that miniframe timestamp has circled but we haven't
02509             gotten the update from the main packet.  We'll just pretend that we did, and
02510             update the timestamp appropriately. */
02511          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02512          if (option_debug && iaxdebug)
02513             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02514       }
02515       if (x > 50000) {
02516          /* Sudden apparent big jump forwards in timestamp:
02517             What's likely happened is this is an old miniframe belonging to the previous
02518             top-16-bit timestamp that has turned up out of order.
02519             Adjust the timestamp appropriately. */
02520          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02521          if (option_debug && iaxdebug)
02522             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02523       }
02524    }
02525 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

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

Referenced by __get_from_jb(), and schedule_delivery().

02530 {
02531    int when;
02532    
02533    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02534    
02535    when = jb_next(pvt->jb) - when;
02536 
02537    AST_SCHED_DEL(sched, pvt->jbid);
02538 
02539    if(when <= 0) {
02540       /* XXX should really just empty until when > 0.. */
02541       when = 1;
02542    }
02543    
02544    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02545 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1453 of file chan_iax2.c.

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

Referenced by __find_callno(), and make_trunk().

01454 {
01455    int max = 1;
01456    int x;
01457    /* XXX Prolly don't need locks here XXX */
01458    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01459       if (iaxs[x])
01460          max = x + 1;
01461    }
01462    maxnontrunkcall = max;
01463    if (option_debug && iaxdebug)
01464       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01465 }

static void update_max_trunk ( void   )  [static]

Definition at line 1260 of file chan_iax2.c.

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

Referenced by iax2_destroy(), and make_trunk().

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

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2137 of file chan_iax2.c.

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

Referenced by __attempt_transmit().

02138 {
02139    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02140    struct ast_iax2_full_hdr *fh = f->data;
02141    /* Mark this as a retransmission */
02142    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02143    /* Update iseqno */
02144    f->iseqno = iaxs[f->callno]->iseqno;
02145    fh->iseqno = f->iseqno;
02146    return 0;
02147 }

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 6164 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(), iax_ie_data::buf, EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), 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(), iax_ie_data::pos, realtime_update_peer(), register_peer_exten(), send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.

Referenced by socket_process().

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

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

Referenced by load_module().

01133 {
01134    struct iax2_user *user = obj, *user2 = arg;
01135 
01136    return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
01137 }

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

Definition at line 9806 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09807 {
09808    struct iax2_user *user = obj;
09809 
09810    ast_set_flag(user, IAX_DELME);
09811 
09812    return 0;
09813 }

static void user_destructor ( void *  obj  )  [static]

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

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

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

References ast_str_hash().

Referenced by load_module().

01123 {
01124    const struct iax2_user *user = obj;
01125 
01126    return ast_str_hash(user->name);
01127 }

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

Definition at line 1171 of file chan_iax2.c.

References ao2_ref().

01172 {
01173    ao2_ref(user, +1);
01174    return user;
01175 }

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

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

01178 {
01179    ao2_ref(user, -1);
01180    return NULL;
01181 }

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

Definition at line 6489 of file chan_iax2.c.

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

Referenced by socket_process().

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


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

int adsi = 0 [static]

Definition at line 223 of file chan_iax2.c.

int amaflags = 0 [static]

Definition at line 222 of file chan_iax2.c.

int authdebug = 1 [static]

Definition at line 158 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 159 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10907 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

Initial value:

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

Definition at line 10887 of file chan_iax2.c.

Initial value:

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

Definition at line 10892 of file chan_iax2.c.

Initial value:

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

Definition at line 10902 of file chan_iax2.c.

Initial value:

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

Definition at line 10897 of file chan_iax2.c.

Initial value:

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

Definition at line 10882 of file chan_iax2.c.

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

Definition at line 145 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 10856 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 10848 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 10840 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 176 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 224 of file chan_iax2.c.

struct iax2_dpcache * dpcache [static]

Referenced by find_cache(), and iax2_show_cache().

int global_rtautoclear = 120 [static]

Definition at line 277 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 205 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 225 of file chan_iax2.c.

enum { ... } iax2_flags

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

char iax2_reload_usage[] [static]

Initial value:

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

Definition at line 10798 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10772 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

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

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

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

int iaxcompat = 0 [static]

Definition at line 160 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 207 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 163 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 165 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 452 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 451 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

Definition at line 10708 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static]

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 450 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 209 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 202 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 153 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 147 of file chan_iax2.c.

int last_authmethod = 0 [static]

Definition at line 161 of file chan_iax2.c.

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

Definition at line 815 of file chan_iax2.c.

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

int max_reg_expire [static]

Definition at line 170 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 151 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 150 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 154 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 156 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 833 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_nontrunk().

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 832 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_trunk().

int min_reg_expire [static]

Definition at line 169 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 220 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 221 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 174 of file chan_iax2.c.

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 229 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 10860 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 10852 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 10844 of file chan_iax2.c.

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 175 of file chan_iax2.c.

char* papp = "IAX2Provision" [static]

Definition at line 8813 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

char* pdescrip [static]

Initial value:

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

Definition at line 8815 of file chan_iax2.c.

Referenced by load_module().

struct ao2_container* peers [static]

int ping_time = 21 [static]

Definition at line 152 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10794 of file chan_iax2.c.

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

Definition at line 8814 of file chan_iax2.c.

Referenced by load_module().

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 148 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 155 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 203 of file chan_iax2.c.

Definition at line 232 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 230 of file chan_iax2.c.

char show_cache_usage[] [static]

Initial value:

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

Definition at line 10786 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 10814 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 10832 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 10818 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 10790 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 10826 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10802 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 10836 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 10782 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 10822 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 10809 of file chan_iax2.c.

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

Definition at line 143 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 211 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 172 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 167 of file chan_iax2.c.

struct iax2_trunk_peer * tpeers [static]

Referenced by find_tpeer(), and timing_read().

int trunkfreq = 20 [static]

Definition at line 157 of file chan_iax2.c.

struct ao2_container* users [static]

struct ast_firmware_list waresl [static]


Generated on Thu Oct 8 21:56:15 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6