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

Functions

static void __attempt_transmit (const void *data)
static void __auth_reject (const void *nothing)
static void __auto_congest (const void *nothing)
static void __auto_hangup (const void *nothing)
static int __do_deliver (void *data)
static void __expire_registry (const void *data)
static int __find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int return_locked, int check_dcallno)
static void __get_from_jb (const void *p)
static void __iax2_do_register_s (const void *data)
static void __iax2_poke_noanswer (const void *data)
static void __iax2_poke_peer_s (const void *data)
static int __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[])
static int __schedule_action (void(*func)(const void *data), const void *data, const char *funcname)
static int __send_command (struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const unsigned char *data, int datalen, int seqno, int now, int transfer, int final)
static void __send_lagrq (const void *data)
static void __send_ping (const void *data)
static int __unload_module (void)
static int apply_context (struct iax2_context *con, const char *context)
static int ast_cli_netstats (struct mansession *s, int fd, int limit_fmt)
static struct ast_channel * ast_iax2_new (int callno, int state, int capability)
 Create new call, interface with the PBX core.
static AST_LIST_HEAD_STATIC (dynamic_list, iax2_thread)
static AST_LIST_HEAD_STATIC (active_list, iax2_thread)
static AST_LIST_HEAD_STATIC (idle_list, iax2_thread)
static AST_LIST_HEAD_STATIC (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, struct chan_iax2_pvt *pvt)
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_context * build_context (char *context)
static void build_ecx_key (const unsigned char *digest, struct chan_iax2_pvt *pvt)
static void build_encryption_keys (const unsigned char *digest, struct chan_iax2_pvt *pvt)
static struct iax2_peer * build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
 Create peer structure based on configuration.
static struct iax2_user * build_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_dpcache * find_cache (struct ast_channel *chan, const char *data, const char *context, const char *exten, int priority)
static int find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int 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_thread * find_idle_thread (void)
static struct iax2_peer * find_peer (const char *name, int realtime)
static struct iax2_trunk_peer * find_tpeer (struct sockaddr_in *sin, int fd)
static unsigned int fix_peerts (struct timeval *tv, int callno, unsigned int ts)
static void free_context (struct iax2_context *con)
static int function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int get_auth_methods (char *value)
static int get_encrypt_methods (const char *s)
static int get_from_jb (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_frame * iax2_read (struct ast_channel *c)
static int iax2_register (char *value, int lineno)
static int iax2_reload (int fd, int argc, char *argv[])
static struct ast_channel * iax2_request (const char *type, int format, void *data, int *cause)
static int iax2_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_frame * iaxfrdup2 (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_pvt * new_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_peer * peer_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_peer * peer_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_peer * realtime_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_user * realtime_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_user * user_ref (struct iax2_user *user)
static struct iax2_user * user_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_dpcache * dpcache
static int global_rtautoclear = 120
static struct ast_flags globalflags = { 0 }
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH
static int iax2_encryption = 0
enum { ... }  iax2_flags
int(* iax2_regfunk )(const char *username, int onoff) = NULL
static char iax2_reload_usage []
enum { ... }  iax2_state
static struct ast_switch iax2_switch
static struct ast_channel_tech iax2_tech
static char iax2_test_losspct_usage []
static struct ao2_container * iax_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_pvt * iaxs [IAX_MAX_CALLS]
static ast_mutex_t iaxsl [ARRAY_LEN(iaxs)]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct io_context * io
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static struct timeval lastused [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_list * netsock
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_jb_usage []
static char no_debug_trunk_usage []
static char no_debug_usage []
static struct ast_netsock_list * outsock
static char * papp = "IAX2Provision"
static char * pdescrip
static struct ao2_container * peers
static int ping_time = 21
static struct ast_codec_pref prefs
static char prune_realtime_usage []
static char * psyn = "Provision a calling IAXy with a given template"
static char regcontext [AST_MAX_CONTEXT] = ""
static int resyncthreshold = 1000
static struct sched_context * sched
static ast_cond_t sched_cond
static pthread_t schedthreadid = AST_PTHREADT_NULL
static char show_cache_usage []
static char show_channels_usage []
static char show_firmware_usage []
static char show_netstats_usage []
static char show_peer_usage []
static char show_peers_usage []
static char show_prov_usage []
static char show_reg_usage []
static char show_stats_usage []
static char show_threads_usage []
static char show_users_usage []
static const char tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)"
static int test_losspct = 0
static int timingfd = -1
static unsigned int tos = 0
static struct iax2_trunk_peer * tpeers
static int trunkfreq = 20
static struct ao2_container * users
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 667 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 663 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 677 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 665 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 669 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 671 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

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

Referenced by complete_dpreply(), and iax2_show_cache().

#define CALLNO_TO_PTR ( a   )     ((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 199 of file chan_iax2.c.

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

#define DEFAULT_FREQ_OK   60 * 1000

Definition at line 198 of file chan_iax2.c.

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 197 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

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

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 188 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 193 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 182 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 698 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 700 of file chan_iax2.c.

Referenced by iax2_process_thread().

#define IAX_IOSTATE_READY   1

Definition at line 699 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 701 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 703 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 649 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 654 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 1435 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

#define NEW_PREVENT   0

Definition at line 1434 of file chan_iax2.c.

Referenced by socket_process().

#define PTR_TO_CALLNO ( a   )     ((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 831 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 
IAX_STATE_UNCHANGED 

Definition at line 233 of file chan_iax2.c.

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

anonymous enum

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

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

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

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

06381 {
06382    /* Called from IAX thread only, without iaxs lock */
06383    int callno = (int)(long)(nothing);
06384    struct iax_ie_data ied;
06385    ast_mutex_lock(&iaxsl[callno]);
06386    if (iaxs[callno]) {
06387       memset(&ied, 0, sizeof(ied));
06388       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06389          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06390          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06391       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06392          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06393          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06394       }
06395       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06396    }
06397    ast_mutex_unlock(&iaxsl[callno]);
06398 }

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

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

03122 {
03123    int callno = PTR_TO_CALLNO(nothing);
03124    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03125    ast_mutex_lock(&iaxsl[callno]);
03126    if (iaxs[callno]) {
03127       iaxs[callno]->initid = -1;
03128       iax2_queue_frame(callno, &f);
03129       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03130    }
03131    ast_mutex_unlock(&iaxsl[callno]);
03132 }

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

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

06430 {
06431    /* Called from IAX thread only, without iaxs lock */
06432    int callno = (int)(long)(nothing);
06433    struct iax_ie_data ied;
06434    ast_mutex_lock(&iaxsl[callno]);
06435    if (iaxs[callno]) {
06436       memset(&ied, 0, sizeof(ied));
06437       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06438       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06439       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06440    }
06441    ast_mutex_unlock(&iaxsl[callno]);
06442 }

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

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

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

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

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

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

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

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

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

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

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

Definition at line 5761 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05762 {
05763    struct iax2_registry *reg = (struct iax2_registry *)data;
05764    reg->expire = -1;
05765    iax2_do_register(reg);
05766 }

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

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

08863 {
08864    struct iax2_peer *peer = (struct iax2_peer *)data;
08865    int callno;
08866 
08867    if (peer->lastms > -1) {
08868       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08869       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08870       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08871    }
08872    if ((callno = peer->callno) > 0) {
08873       ast_mutex_lock(&iaxsl[callno]);
08874       iax2_destroy(callno);
08875       ast_mutex_unlock(&iaxsl[callno]);
08876    }
08877    peer->callno = 0;
08878    peer->lastms = -1;
08879    /* Try again quickly */
08880    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08881    if (peer->pokeexpire == -1)
08882       peer_unref(peer);
08883 }

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

Definition at line 6492 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06493 {
06494    struct iax2_peer *peer = (struct iax2_peer *)data;
06495    iax2_poke_peer(peer, 0);
06496    peer_unref(peer);
06497 }

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

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

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

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

Definition at line 964 of file chan_iax2.c.

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

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

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

05053 {
05054    struct ast_frame f = { 0, };
05055 
05056    f.frametype = type;
05057    f.subclass = command;
05058    f.datalen = datalen;
05059    f.src = __FUNCTION__;
05060    f.data = (void *) data;
05061 
05062    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05063 }

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

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

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

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

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

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

static int __unload_module ( void   )  [static]

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

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

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

Definition at line 5104 of file chan_iax2.c.

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

Referenced by check_access().

05105 {
05106    while(con) {
05107       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05108          return -1;
05109       con = con->next;
05110    }
05111    return 0;
05112 }

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

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

04879 {
04880    int x;
04881    int numchans = 0;
04882    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04883       ast_mutex_lock(&iaxsl[x]);
04884       if (iaxs[x]) {
04885          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04886          char *fmt;
04887          jb_info jbinfo;
04888          
04889          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04890             jb_getinfo(iaxs[x]->jb, &jbinfo);
04891             localjitter = jbinfo.jitter;
04892             localdelay = jbinfo.current - jbinfo.min;
04893             locallost = jbinfo.frames_lost;
04894             locallosspct = jbinfo.losspct/1000;
04895             localdropped = jbinfo.frames_dropped;
04896             localooo = jbinfo.frames_ooo;
04897          } else {
04898             localjitter = -1;
04899             localdelay = 0;
04900             locallost = -1;
04901             locallosspct = -1;
04902             localdropped = 0;
04903             localooo = -1;
04904          }
04905          if (limit_fmt)
04906             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04907          else
04908             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04909          if (s)
04910             
04911             astman_append(s, fmt,
04912                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04913                      iaxs[x]->pingtime,
04914                      localjitter, 
04915                      localdelay,
04916                      locallost,
04917                      locallosspct,
04918                      localdropped,
04919                      localooo,
04920                      iaxs[x]->frames_received/1000,
04921                      iaxs[x]->remote_rr.jitter,
04922                      iaxs[x]->remote_rr.delay,
04923                      iaxs[x]->remote_rr.losscnt,
04924                      iaxs[x]->remote_rr.losspct,
04925                      iaxs[x]->remote_rr.dropped,
04926                      iaxs[x]->remote_rr.ooo,
04927                      iaxs[x]->remote_rr.packets/1000);
04928          else
04929             ast_cli(fd, fmt,
04930                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04931                iaxs[x]->pingtime,
04932                localjitter, 
04933                localdelay,
04934                locallost,
04935                locallosspct,
04936                localdropped,
04937                localooo,
04938                iaxs[x]->frames_received/1000,
04939                iaxs[x]->remote_rr.jitter,
04940                iaxs[x]->remote_rr.delay,
04941                iaxs[x]->remote_rr.losscnt,
04942                iaxs[x]->remote_rr.losspct,
04943                iaxs[x]->remote_rr.dropped,
04944                iaxs[x]->remote_rr.ooo,
04945                iaxs[x]->remote_rr.packets/1000
04946                );
04947          numchans++;
04948       }
04949       ast_mutex_unlock(&iaxsl[x]);
04950    }
04951    return numchans;
04952 }

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

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

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02248 {
02249 #ifdef SCHED_MULTITHREADED
02250    if (schedule_action(__attempt_transmit, data))
02251 #endif      
02252       __attempt_transmit(data);
02253    return 0;
02254 }

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

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

06415 {
06416    /* Schedule sending the authentication failure in one second, to prevent
06417       guessing */
06418    if (iaxs[callno]) {
06419       iaxs[callno]->authfail = failcode;
06420       if (delayreject) {
06421          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06422          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06423       } else
06424          auth_reject((void *)(long)callno);
06425    }
06426    return 0;
06427 }

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

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

06401 {
06402    int callno = (int)(long)(data);
06403    ast_mutex_lock(&iaxsl[callno]);
06404    if (iaxs[callno])
06405       iaxs[callno]->authid = -1;
06406    ast_mutex_unlock(&iaxsl[callno]);
06407 #ifdef SCHED_MULTITHREADED
06408    if (schedule_action(__auth_reject, data))
06409 #endif      
06410       __auth_reject(data);
06411    return 0;
06412 }

static int authenticate ( const char *  challenge,
const char *  secret,
const char *  keyn,
int  authmethods,
struct iax_ie_data *  ied,
struct sockaddr_in *  sin,
struct chan_iax2_pvt *  pvt 
) [static]

Definition at line 5629 of file chan_iax2.c.

References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_encryption_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().

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

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 5687 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::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().

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

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

05365 {
05366    struct iax_ie_data ied;
05367    int res = -1, authreq_restrict = 0;
05368    char challenge[10];
05369    struct chan_iax2_pvt *p = iaxs[call_num];
05370 
05371    memset(&ied, 0, sizeof(ied));
05372 
05373    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05374    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05375       struct iax2_user *user, tmp_user = {
05376          .name = p->username, 
05377       };
05378 
05379       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05380       if (user) {
05381          if (user->curauthreq == user->maxauthreq)
05382             authreq_restrict = 1;
05383          else
05384             user->curauthreq++;
05385          user = user_unref(user);
05386       }
05387    }
05388 
05389    /* If the AUTHREQ limit test failed, send back an error */
05390    if (authreq_restrict) {
05391       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05392       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05393       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05394       return 0;
05395    }
05396 
05397    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05398    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05399       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05400       ast_string_field_set(p, challenge, challenge);
05401       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05402       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05403    }
05404    if (p->encmethods)
05405       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05406 
05407    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05408 
05409    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05410 
05411    if (p->encmethods)
05412       ast_set_flag(p, IAX_ENCRYPTED);
05413 
05414    return res;
05415 }

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

Definition at line 5417 of file chan_iax2.c.

References ao2_find(), ast_check_signature, ast_clear_flag, ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, 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().

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

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

Definition at line 3134 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03135 {
03136 #ifdef SCHED_MULTITHREADED
03137    if (schedule_action(__auto_congest, data))
03138 #endif      
03139       __auto_congest(data);
03140    return 0;
03141 }

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

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

06445 {
06446    int callno = (int)(long)(data);
06447    ast_mutex_lock(&iaxsl[callno]);
06448    if (iaxs[callno]) {
06449       iaxs[callno]->autoid = -1;
06450    }
06451    ast_mutex_unlock(&iaxsl[callno]);
06452 #ifdef SCHED_MULTITHREADED
06453    if (schedule_action(__auto_hangup, data))
06454 #endif      
06455       __auto_hangup(data);
06456    return 0;
06457 }

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

Definition at line 9183 of file chan_iax2.c.

References ast_calloc, and iax2_context::context.

Referenced by build_user().

09184 {
09185    struct iax2_context *con;
09186 
09187    if ((con = ast_calloc(1, sizeof(*con))))
09188       ast_copy_string(con->context, context, sizeof(con->context));
09189    
09190    return con;
09191 }

static void build_ecx_key ( const unsigned char *  digest,
struct chan_iax2_pvt *  pvt 
) [static]

Definition at line 4128 of file chan_iax2.c.

References aes_decrypt_key128(), aes_encrypt_key128(), chan_iax2_pvt::ecx, and chan_iax2_pvt::mydcx.

Referenced by build_encryption_keys().

04129 {
04130    /* it is required to hold the corresponding decrypt key to our encrypt key
04131     * in the pvt struct because queued frames occasionally need to be decrypted and
04132     * re-encrypted when updated for a retransmission */
04133    aes_encrypt_key128(digest, &pvt->ecx);
04134    aes_decrypt_key128(digest, &pvt->mydcx);
04135 }

static void build_encryption_keys ( const unsigned char *  digest,
struct chan_iax2_pvt *  pvt 
) [static]

Definition at line 4122 of file chan_iax2.c.

References aes_decrypt_key128(), build_ecx_key(), and chan_iax2_pvt::dcx.

Referenced by authenticate(), and decrypt_frame().

04123 {
04124    build_ecx_key(digest, pvt);
04125    aes_decrypt_key128(digest, &pvt->dcx);
04126 }

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

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

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

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

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

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

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

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

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

03991 {
03992    /* Returns where in "receive time" we are.  That is, how many ms
03993       since we received (or would have received) the frame with timestamp 0 */
03994    int ms;
03995 #ifdef IAXTESTS
03996    int jit;
03997 #endif /* IAXTESTS */
03998    /* Setup rxcore if necessary */
03999    if (ast_tvzero(p->rxcore)) {
04000       p->rxcore = ast_tvnow();
04001       if (option_debug && iaxdebug)
04002          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
04003                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
04004       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
04005 #if 1
04006       if (option_debug && iaxdebug)
04007          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
04008                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
04009 #endif
04010    }
04011 
04012    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
04013 #ifdef IAXTESTS
04014    if (test_jit) {
04015       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
04016          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
04017          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
04018             jit = -jit;
04019          ms += jit;
04020       }
04021    }
04022    if (test_late) {
04023       ms += test_late;
04024       test_late = 0;
04025    }
04026 #endif /* IAXTESTS */
04027    return ms;
04028 }

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

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

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

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

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

03818 {
03819    unsigned long int mssincetx; /* unsigned to handle overflows */
03820    long int ms, pred;
03821 
03822    tpeer->trunkact = *tv;
03823    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03824    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03825       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03826       tpeer->txtrunktime = *tv;
03827       tpeer->lastsent = 999999;
03828    }
03829    /* Update last transmit time now */
03830    tpeer->lasttxtime = *tv;
03831    
03832    /* Calculate ms offset */
03833    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03834    /* Predict from last value */
03835    pred = tpeer->lastsent + sampms;
03836    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03837       ms = pred;
03838    
03839    /* We never send the same timestamp twice, so fudge a little if we must */
03840    if (ms == tpeer->lastsent)
03841       ms = tpeer->lastsent + 1;
03842    tpeer->lastsent = ms;
03843    return ms;
03844 }

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

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

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

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

Definition at line 6802 of file chan_iax2.c.

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

Referenced by socket_process().

06803 {
06804    unsigned int ourver;
06805    char rsi[80];
06806    snprintf(rsi, sizeof(rsi), "si-%s", si);
06807    if (iax_provision_version(&ourver, rsi, 1))
06808       return 0;
06809    if (option_debug)
06810       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06811    if (ourver != ver) 
06812       iax2_provision(sin, sockfd, NULL, rsi, 1);
06813    return 0;
06814 }

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

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

Referenced by peer_set_srcaddr().

09210 {
09211    int sd;
09212    int res;
09213    
09214    sd = socket(AF_INET, SOCK_DGRAM, 0);
09215    if (sd < 0) {
09216       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
09217       return -1;
09218    }
09219 
09220    res = bind(sd, sa, salen);
09221    if (res < 0) {
09222       if (option_debug)
09223          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09224       close(sd);
09225       return 1;
09226    }
09227 
09228    close(sd);
09229    return 0;
09230 }

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

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

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

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

Definition at line 2409 of file chan_iax2.c.

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

02410 {
02411    int which = 0;
02412    struct iax2_peer *peer;
02413    char *res = NULL;
02414    int wordlen = strlen(word);
02415    struct ao2_iterator i;
02416 
02417    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02418    if (pos != 3)
02419       return NULL;
02420 
02421    i = ao2_iterator_init(peers, 0);
02422    while ((peer = ao2_iterator_next(&i))) {
02423       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02424          res = ast_strdup(peer->name);
02425          peer_unref(peer);
02426          break;
02427       }
02428       peer_unref(peer);
02429    }
02430 
02431    return res;
02432 }

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

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

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

static unsigned char compress_subclass ( int  subclass  )  [static]

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

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

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

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

06817 {
06818    jb_info stats;
06819    jb_getinfo(pvt->jb, &stats);
06820    
06821    memset(iep, 0, sizeof(*iep));
06822 
06823    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06824    if(stats.frames_in == 0) stats.frames_in = 1;
06825    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06826    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06827    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06828    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06829    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06830 }

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

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

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

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

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

04186 {
04187    int padding;
04188    unsigned char *workspace;
04189 
04190    workspace = alloca(*datalen);
04191    memset(f, 0, sizeof(*f));
04192    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04193       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04194       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04195          return -1;
04196       /* Decrypt */
04197       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04198 
04199       padding = 16 + (workspace[15] & 0xf);
04200       if (option_debug && iaxdebug)
04201          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04202       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04203          return -1;
04204 
04205       *datalen -= padding;
04206       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04207       f->frametype = fh->type;
04208       if (f->frametype == AST_FRAME_VIDEO) {
04209          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04210       } else {
04211          f->subclass = uncompress_subclass(fh->csub);
04212       }
04213    } else {
04214       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04215       if (option_debug && iaxdebug)
04216          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04217       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04218          return -1;
04219       /* Decrypt */
04220       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04221       padding = 16 + (workspace[15] & 0x0f);
04222       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04223          return -1;
04224       *datalen -= padding;
04225       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04226    }
04227    return 0;
04228 }

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

Definition at line 4271 of file chan_iax2.c.

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

Referenced by socket_process().

04272 {
04273    int res=-1;
04274    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04275       /* Search for possible keys, given secrets */
04276       struct MD5Context md5;
04277       unsigned char digest[16];
04278       char *tmppw, *stringp;
04279       
04280       tmppw = ast_strdupa(iaxs[callno]->secret);
04281       stringp = tmppw;
04282       while ((tmppw = strsep(&stringp, ";"))) {
04283          MD5Init(&md5);
04284          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04285          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04286          MD5Final(digest, &md5);
04287          build_encryption_keys(digest, iaxs[callno]);
04288          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04289          if (!res) {
04290             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04291             break;
04292          }
04293       }
04294    } else 
04295       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04296    return res;
04297 }

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

06879 {
06880    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06881    struct ast_iax2_full_hdr *fh, *cur_fh;
06882 
06883    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06884       return;
06885 
06886    pkt_buf->len = from_here->buf_len;
06887    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06888 
06889    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06890    ast_mutex_lock(&to_here->lock);
06891    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06892       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06893       if (fh->oseqno < cur_fh->oseqno) {
06894          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06895          break;
06896       }
06897    }
06898    AST_LIST_TRAVERSE_SAFE_END
06899 
06900    if (!cur_pkt_buf)
06901       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06902    
06903    ast_mutex_unlock(&to_here->lock);
06904 }

static void delete_users ( void   )  [static]

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

09802 {
09803    struct iax2_registry *reg;
09804 
09805    ao2_callback(users, 0, user_delme_cb, NULL);
09806 
09807    AST_LIST_LOCK(&registrations);
09808    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09809       ast_sched_del(sched, reg->expire);
09810       if (reg->callno) {
09811          ast_mutex_lock(&iaxsl[reg->callno]);
09812          if (iaxs[reg->callno]) {
09813             iaxs[reg->callno]->reg = NULL;
09814             iax2_destroy(reg->callno);
09815          }
09816          ast_mutex_unlock(&iaxsl[reg->callno]);
09817       }
09818       if (reg->dnsmgr)
09819          ast_dnsmgr_release(reg->dnsmgr);
09820       free(reg);
09821    }
09822    AST_LIST_UNLOCK(&registrations);
09823 
09824    ao2_callback(peers, 0, peer_delme_cb, NULL);
09825 }

static void destroy_firmware ( struct iax_firmware *  cur  )  [static]

Definition at line 1749 of file chan_iax2.c.

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

Referenced by reload_firmware().

01750 {
01751    /* Close firmware */
01752    if (cur->fwh) {
01753       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01754    }
01755    close(cur->fd);
01756    free(cur);
01757 }

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

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

06651 {
06652    unsigned short dpstatus = 0;
06653    struct iax_ie_data ied1;
06654    int mm;
06655 
06656    memset(&ied1, 0, sizeof(ied1));
06657    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06658    /* Must be started */
06659    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06660       dpstatus = IAX_DPSTATUS_EXISTS;
06661    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06662       dpstatus = IAX_DPSTATUS_CANEXIST;
06663    } else {
06664       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06665    }
06666    if (ast_ignore_pattern(context, callednum))
06667       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06668    if (mm)
06669       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06670    if (!skiplock)
06671       ast_mutex_lock(&iaxsl[callno]);
06672    if (iaxs[callno]) {
06673       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06674       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06675       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06676       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06677    }
06678    if (!skiplock)
06679       ast_mutex_unlock(&iaxsl[callno]);
06680 }

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

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

06683 {
06684    /* Look up for dpreq */
06685    struct dpreq_data *dpr = data;
06686    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06687    if (dpr->callerid)
06688       free(dpr->callerid);
06689    free(dpr);
06690    return NULL;
06691 }

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

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

04231 {
04232    int padding;
04233    unsigned char *workspace;
04234    workspace = alloca(*datalen + 32);
04235    if (!workspace)
04236       return -1;
04237    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04238       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04239       if (option_debug && iaxdebug)
04240          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04241       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04242       padding = 16 + (padding & 0xf);
04243       memcpy(workspace, poo, padding);
04244       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04245       workspace[15] &= 0xf0;
04246       workspace[15] |= (padding & 0xf);
04247       if (option_debug && iaxdebug)
04248          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]);
04249       *datalen += padding;
04250       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04251       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04252          memcpy(poo, workspace + *datalen - 32, 32);
04253    } else {
04254       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04255       if (option_debug && iaxdebug)
04256          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04257       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04258       padding = 16 + (padding & 0xf);
04259       memcpy(workspace, poo, padding);
04260       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04261       workspace[15] &= 0xf0;
04262       workspace[15] |= (padding & 0x0f);
04263       *datalen += padding;
04264       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04265       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04266          memcpy(poo, workspace + *datalen - 32, 32);
04267    }
04268    return 0;
04269 }

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

Definition at line 6099 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

06100 {
06101 #ifdef SCHED_MULTITHREADED
06102    if (schedule_action(__expire_registry, data))
06103 #endif      
06104       __expire_registry(data);
06105    return 0;
06106 }

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

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

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

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

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

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

References __find_callno().

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

01654                                                                                                                                            {
01655 
01656    return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
01657 }

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

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

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

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

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

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

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

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

04031 {
04032    struct iax2_trunk_peer *tpeer;
04033    
04034    /* Finds and locks trunk peer */
04035    ast_mutex_lock(&tpeerlock);
04036    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
04037       /* We don't lock here because tpeer->addr *never* changes */
04038       if (!inaddrcmp(&tpeer->addr, sin)) {
04039          ast_mutex_lock(&tpeer->lock);
04040          break;
04041       }
04042    }
04043    if (!tpeer) {
04044       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
04045          ast_mutex_init(&tpeer->lock);
04046          tpeer->lastsent = 9999;
04047          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
04048          tpeer->trunkact = ast_tvnow();
04049          ast_mutex_lock(&tpeer->lock);
04050          tpeer->next = tpeers;
04051          tpeer->sockfd = fd;
04052          tpeers = tpeer;
04053 #ifdef SO_NO_CHECK
04054          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
04055 #endif
04056          if (option_debug)
04057             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
04058       }
04059    }
04060    ast_mutex_unlock(&tpeerlock);
04061    return tpeer;
04062 }

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

Definition at line 3846 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03847 {
03848    long ms; /* NOT unsigned */
03849    if (ast_tvzero(iaxs[callno]->rxcore)) {
03850       /* Initialize rxcore time if appropriate */
03851       gettimeofday(&iaxs[callno]->rxcore, NULL);
03852       /* Round to nearest 20ms so traces look pretty */
03853       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03854    }
03855    /* Calculate difference between trunk and channel */
03856    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03857    /* Return as the sum of trunk time and the difference between trunk and real time */
03858    return ms + ts;
03859 }

static void free_context ( struct iax2_context *  con  )  [static]

Definition at line 8968 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08969 {
08970    struct iax2_context *conl;
08971    while(con) {
08972       conl = con;
08973       con = con->next;
08974       free(conl);
08975    }
08976 }

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

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

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9193 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09194 {
09195    int methods = 0;
09196    if (strstr(value, "rsa"))
09197       methods |= IAX_AUTH_RSA;
09198    if (strstr(value, "md5"))
09199       methods |= IAX_AUTH_MD5;
09200    if (strstr(value, "plaintext"))
09201       methods |= IAX_AUTH_PLAINTEXT;
09202    return methods;
09203 }

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

Definition at line 1030 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

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

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

Definition at line 2640 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02641 {
02642 #ifdef SCHED_MULTITHREADED
02643    if (schedule_action(__get_from_jb, data))
02644 #endif      
02645       __get_from_jb(data);
02646    return 0;
02647 }

static void handle_deferred_full_frames ( struct iax2_thread *  thread  )  [static]

Handle any deferred full frames for this thread.

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

06849 {
06850    struct iax2_pkt_buf *pkt_buf;
06851 
06852    ast_mutex_lock(&thread->lock);
06853 
06854    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06855       ast_mutex_unlock(&thread->lock);
06856 
06857       thread->buf = pkt_buf->buf;
06858       thread->buf_len = pkt_buf->len;
06859       thread->buf_size = pkt_buf->len + 1;
06860       
06861       socket_process(thread);
06862 
06863       thread->buf = NULL;
06864       ast_free(pkt_buf);
06865 
06866       ast_mutex_lock(&thread->lock);
06867    }
06868 
06869    ast_mutex_unlock(&thread->lock);
06870 }

static int handle_error ( void   )  [static]

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

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

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

Acknowledgment received for OUR registration.

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

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

static int iax2_answer ( struct ast_channel *  c  )  [static]

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

03647 {
03648    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03649    if (option_debug)
03650       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03651    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03652 }

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

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

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

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

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

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

10531 {
10532    int res = 0;
10533    struct iax2_dpcache *dp;
10534 #if 0
10535    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10536 #endif
10537    if ((priority != 1) && (priority != 2))
10538       return 0;
10539    ast_mutex_lock(&dpcache_lock);
10540    dp = find_cache(chan, data, context, exten, priority);
10541    if (dp) {
10542       if (dp->flags & CACHE_FLAG_CANEXIST)
10543          res= 1;
10544    }
10545    ast_mutex_unlock(&dpcache_lock);
10546    if (!dp) {
10547       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10548    }
10549    return res;
10550 }

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

Definition at line 3143 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03144 {
03145    time_t t;
03146    struct tm tm;
03147    unsigned int tmp;
03148    time(&t);
03149    if (!ast_strlen_zero(tz))
03150       ast_localtime(&t, &tm, tz);
03151    else
03152       ast_localtime(&t, &tm, NULL);
03153    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03154    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03155    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03156    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03157    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03158    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03159    return tmp;
03160 }

static void iax2_destroy ( int  callno  )  [static]

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

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

static void iax2_destroy_helper ( struct chan_iax2_pvt *  pvt  )  [static]

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

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

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

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

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

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

Definition at line 2759 of file chan_iax2.c.

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

02760 {
02761    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02762 }

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

Definition at line 2764 of file chan_iax2.c.

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

02765 {
02766    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02767 }

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

Definition at line 4966 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04967 {
04968    if (argc < 2 || argc > 3)
04969       return RESULT_SHOWUSAGE;
04970    iaxdebug = 1;
04971    ast_cli(fd, "IAX2 Debugging Enabled\n");
04972    return RESULT_SUCCESS;
04973 }

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

Definition at line 4984 of file chan_iax2.c.

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

04985 {
04986    if (argc < 3 || argc > 4)
04987       return RESULT_SHOWUSAGE;
04988    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04989    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04990    return RESULT_SUCCESS;
04991 }

static int iax2_do_register ( struct iax2_registry *  reg  )  [static]

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

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

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

Definition at line 5768 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05769 {
05770 #ifdef SCHED_MULTITHREADED
05771    if (schedule_action(__iax2_do_register_s, data))
05772 #endif      
05773       __iax2_do_register_s(data);
05774    return 0;
05775 }

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

Definition at line 4975 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04976 {
04977    if (argc < 3 || argc > 4)
04978       return RESULT_SHOWUSAGE;
04979    iaxtrunkdebug = 1;
04980    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04981    return RESULT_SUCCESS;
04982 }

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

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

06460 {
06461    struct iax_ie_data ied;
06462    /* Auto-hangup with 30 seconds of inactivity */
06463    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06464    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06465    memset(&ied, 0, sizeof(ied));
06466    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06467    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06468    dp->flags |= CACHE_FLAG_TRANSMITTED;
06469 }

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

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

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

10508 {
10509    struct iax2_dpcache *dp;
10510    int res = 0;
10511 #if 0
10512    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10513 #endif
10514    if ((priority != 1) && (priority != 2))
10515       return 0;
10516    ast_mutex_lock(&dpcache_lock);
10517    dp = find_cache(chan, data, context, exten, priority);
10518    if (dp) {
10519       if (dp->flags & CACHE_FLAG_EXISTS)
10520          res= 1;
10521    }
10522    ast_mutex_unlock(&dpcache_lock);
10523    if (!dp) {
10524       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10525    }
10526    return res;
10527 }

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

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

02787 {
02788    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02789    ast_mutex_lock(&iaxsl[callno]);
02790    if (iaxs[callno])
02791       iaxs[callno]->owner = newchan;
02792    else
02793       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02794    ast_mutex_unlock(&iaxsl[callno]);
02795    return 0;
02796 }

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

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

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03722 {
03723    struct iax2_peer *peer;
03724    int res = 0;
03725    struct ao2_iterator i;
03726 
03727    i = ao2_iterator_init(peers, 0);
03728    while ((peer = ao2_iterator_next(&i))) {
03729       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03730           (peer->addr.sin_port == sin.sin_port)) {
03731          res = ast_test_flag(peer, IAX_TRUNK);
03732          peer_unref(peer);
03733          break;
03734       }
03735       peer_unref(peer);
03736    }
03737 
03738    return res;
03739 }

static int iax2_hangup ( struct ast_channel *  c  )  [static]

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

03388 {
03389    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03390    int alreadygone;
03391    struct iax_ie_data ied;
03392    memset(&ied, 0, sizeof(ied));
03393    ast_mutex_lock(&iaxsl[callno]);
03394    if (callno && iaxs[callno]) {
03395       if (option_debug)
03396          ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
03397       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03398       /* Send the hangup unless we have had a transmission error or are already gone */
03399       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03400       if (!iaxs[callno]->error && !alreadygone) {
03401          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03402          if (!iaxs[callno]) {
03403             ast_mutex_unlock(&iaxsl[callno]);
03404             return 0;
03405          }
03406       }
03407       /* Explicitly predestroy it */
03408       iax2_predestroy(callno);
03409       /* If we were already gone to begin with, destroy us now */
03410       if (alreadygone && iaxs[callno]) {
03411          if (option_debug)
03412             ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03413          iax2_destroy(callno);
03414       }
03415    }
03416    ast_mutex_unlock(&iaxsl[callno]);
03417    if (option_verbose > 2) 
03418       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03419    return 0;
03420 }

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

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

03655 {
03656    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03657    struct chan_iax2_pvt *pvt;
03658    int res = 0;
03659 
03660    if (option_debug && iaxdebug)
03661       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03662 
03663    ast_mutex_lock(&iaxsl[callno]);
03664    pvt = iaxs[callno];
03665 
03666    if (!pvt->peercallno) {
03667       /* We don't know the remote side's call number, yet.  :( */
03668       int count = 10;
03669       while (count-- && pvt && !pvt->peercallno) {
03670          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
03671          pvt = iaxs[callno];
03672       }
03673       if (!pvt->peercallno) {
03674          res = -1;
03675          goto done;
03676       }
03677    }
03678 
03679    switch (condition) {
03680    case AST_CONTROL_HOLD:
03681       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03682          ast_moh_start(c, data, pvt->mohinterpret);
03683          goto done;
03684       }
03685       break;
03686    case AST_CONTROL_UNHOLD:
03687       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03688          ast_moh_stop(c);
03689          goto done;
03690       }
03691    }
03692 
03693    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03694 
03695 done:
03696    ast_mutex_unlock(&iaxsl[callno]);
03697 
03698    return res;
03699 }

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

10554 {
10555    int res = 0;
10556    struct iax2_dpcache *dp;
10557 #if 0
10558    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10559 #endif
10560    if ((priority != 1) && (priority != 2))
10561       return 0;
10562    ast_mutex_lock(&dpcache_lock);
10563    dp = find_cache(chan, data, context, exten, priority);
10564    if (dp) {
10565       if (dp->flags & CACHE_FLAG_MATCHMORE)
10566          res= 1;
10567    }
10568    ast_mutex_unlock(&dpcache_lock);
10569    if (!dp) {
10570       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10571    }
10572    return res;
10573 }

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

Definition at line 4993 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04994 {
04995    if (argc < 3 || argc > 4)
04996       return RESULT_SHOWUSAGE;
04997    iaxdebug = 0;
04998    ast_cli(fd, "IAX2 Debugging Disabled\n");
04999    return RESULT_SUCCESS;
05000 }

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

Definition at line 5011 of file chan_iax2.c.

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

05012 {
05013    if (argc < 4 || argc > 5)
05014       return RESULT_SHOWUSAGE;
05015    jb_setoutput(jb_error_output, jb_warning_output, NULL);
05016    jb_debug_output("\n");
05017    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
05018    return RESULT_SUCCESS;
05019 }

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

Definition at line 5002 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05003 {
05004    if (argc < 4 || argc > 5)
05005       return RESULT_SHOWUSAGE;
05006    iaxtrunkdebug = 0;
05007    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
05008    return RESULT_SUCCESS;
05009 }

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

Definition at line 8885 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08886 {
08887    struct iax2_peer *peer = (struct iax2_peer *)data;
08888    peer->pokeexpire = -1;
08889 #ifdef SCHED_MULTITHREADED
08890    if (schedule_action(__iax2_poke_noanswer, data))
08891 #endif      
08892       __iax2_poke_noanswer(data);
08893    peer_unref(peer);
08894    return 0;
08895 }

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

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

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

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

Definition at line 8897 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08898 {
08899    struct iax2_peer *peer = obj;
08900 
08901    iax2_poke_peer(peer, 0);
08902 
08903    return 0;
08904 }

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

Definition at line 6499 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06500 {
06501    struct iax2_peer *peer = (struct iax2_peer *)data;
06502    peer->pokeexpire = -1;
06503 #ifdef SCHED_MULTITHREADED
06504    if (schedule_action(__iax2_poke_peer_s, data))
06505 #endif      
06506       __iax2_poke_peer_s(data);
06507    return 0;
06508 }

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

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

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

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

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8553 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08554 {
08555    struct iax2_thread *thread = data;
08556    ast_mutex_destroy(&thread->lock);
08557    ast_cond_destroy(&thread->cond);
08558    free(thread);
08559    ast_atomic_dec_and_test(&iaxactivethreadcount);
08560 }

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

Definition at line 8840 of file chan_iax2.c.

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

08841 {
08842    int force = 0;
08843    int res;
08844    if (argc < 4)
08845       return RESULT_SHOWUSAGE;
08846    if ((argc > 4)) {
08847       if (!strcasecmp(argv[4], "forced"))
08848          force = 1;
08849       else
08850          return RESULT_SHOWUSAGE;
08851    }
08852    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08853    if (res < 0)
08854       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08855    else if (res < 1)
08856       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08857    else
08858       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08859    return RESULT_SUCCESS;
08860 }

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

Definition at line 8743 of file chan_iax2.c.

References iax_prov_complete_template().

08744 {
08745    if (pos != 3)
08746       return NULL;
08747    return iax_prov_complete_template(line, word, pos, state);
08748 }

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

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

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

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

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

02257 {
02258    struct iax2_peer *peer;
02259 
02260    if (argc != 4)
02261         return RESULT_SHOWUSAGE;
02262    if (!strcmp(argv[3],"all")) {
02263       reload_config();
02264       ast_cli(fd, "OK cache is flushed.\n");
02265    } else if ((peer = find_peer(argv[3], 0))) {
02266       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02267          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02268          expire_registry(peer_ref(peer));
02269          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02270       } else {
02271          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02272       }
02273       peer_unref(peer);
02274    } else {
02275       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02276    }
02277    
02278    return RESULT_SUCCESS;
02279 }

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

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

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

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

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

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

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

Definition at line 3448 of file chan_iax2.c.

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

03449 {
03450    if (option_verbose > 3)
03451        ast_log(LOG_NOTICE, "I should never be called!\n");
03452    return &ast_null_frame;
03453 }

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

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

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

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

Definition at line 10276 of file chan_iax2.c.

References reload_config().

10277 {
10278    return reload_config();
10279 }

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

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

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

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 4299 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, iax_frame::ecx, chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_frame::encmethods, 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, chan_iax2_pvt::mydcx, iax_frame::mydcx, 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, iax_frame::semirand, 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().

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

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

Definition at line 2781 of file chan_iax2.c.

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

02782 {
02783    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02784 }

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

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

02770 {
02771    
02772    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02773       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02774 }

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

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

03423 {
03424    struct ast_option_header *h;
03425    int res;
03426 
03427    switch (option) {
03428    case AST_OPTION_TXGAIN:
03429    case AST_OPTION_RXGAIN:
03430       /* these two cannot be sent, because they require a result */
03431       errno = ENOSYS;
03432       return -1;
03433    default:
03434       if (!(h = ast_malloc(datalen + sizeof(*h))))
03435          return -1;
03436 
03437       h->flag = AST_OPTION_FLAG_REQUEST;
03438       h->option = htons(option);
03439       memcpy(h->data, data, datalen);
03440       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03441                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03442                  datalen + sizeof(*h), -1);
03443       free(h);
03444       return res;
03445    }
03446 }

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

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

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

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

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

04832 {
04833 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04834 #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"
04835 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04836    int x;
04837    int numchans = 0;
04838 
04839    if (argc != 3)
04840       return RESULT_SHOWUSAGE;
04841    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04842    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04843       ast_mutex_lock(&iaxsl[x]);
04844       if (iaxs[x]) {
04845          int lag, jitter, localdelay;
04846          jb_info jbinfo;
04847          
04848          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04849             jb_getinfo(iaxs[x]->jb, &jbinfo);
04850             jitter = jbinfo.jitter;
04851             localdelay = jbinfo.current - jbinfo.min;
04852          } else {
04853             jitter = -1;
04854             localdelay = 0;
04855          }
04856          lag = iaxs[x]->remote_rr.delay;
04857          ast_cli(fd, FORMAT,
04858             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04859             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04860             S_OR(iaxs[x]->username, "(None)"),
04861             iaxs[x]->callno, iaxs[x]->peercallno,
04862             iaxs[x]->oseqno, iaxs[x]->iseqno,
04863             lag,
04864             jitter,
04865             localdelay,
04866             ast_getformatname(iaxs[x]->voiceformat) );
04867          numchans++;
04868       }
04869       ast_mutex_unlock(&iaxsl[x]);
04870    }
04871    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04872    return RESULT_SUCCESS;
04873 #undef FORMAT
04874 #undef FORMAT2
04875 #undef FORMATB
04876 }

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

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

04743 {
04744 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04745 #if !defined(__FreeBSD__)
04746 #define FORMAT "%-15.15s  %-15d %-15d\n"
04747 #else /* __FreeBSD__ */
04748 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04749 #endif /* __FreeBSD__ */
04750    struct iax_firmware *cur;
04751    if ((argc != 3) && (argc != 4))
04752       return RESULT_SHOWUSAGE;
04753    ast_mutex_lock(&waresl.lock);
04754    
04755    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04756    for (cur = waresl.wares;cur;cur = cur->next) {
04757       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04758          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04759             (int)ntohl(cur->fwh->datalen));
04760    }
04761    ast_mutex_unlock(&waresl.lock);
04762    return RESULT_SUCCESS;
04763 #undef FORMAT
04764 #undef FORMAT2
04765 }

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

Definition at line 4954 of file chan_iax2.c.

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

04955 {
04956    int numchans = 0;
04957    if (argc != 3)
04958       return RESULT_SHOWUSAGE;
04959    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04960    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04961    numchans = ast_cli_netstats(NULL, fd, 1);
04962    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04963    return RESULT_SUCCESS;
04964 }

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

Show one peer in detail.

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

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

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

Definition at line 4731 of file chan_iax2.c.

References __iax2_show_peers().

04732 {
04733    return __iax2_show_peers(0, fd, NULL, argc, argv);
04734 }

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

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

04804 {
04805 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04806 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04807    struct iax2_registry *reg = NULL;
04808 
04809    char host[80];
04810    char perceived[80];
04811    if (argc != 3)
04812       return RESULT_SHOWUSAGE;
04813    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04814    AST_LIST_LOCK(&registrations);
04815    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04816       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04817       if (reg->us.sin_addr.s_addr) 
04818          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04819       else
04820          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04821       ast_cli(fd, FORMAT, host, 
04822                (reg->dnsmgr) ? "Y" : "N", 
04823                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04824    }
04825    AST_LIST_UNLOCK(&registrations);
04826    return RESULT_SUCCESS;
04827 #undef FORMAT
04828 #undef FORMAT2
04829 }

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

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

02435 {
02436    struct iax_frame *cur;
02437    int cnt = 0, dead=0, final=0;
02438 
02439    if (argc != 3)
02440       return RESULT_SHOWUSAGE;
02441 
02442    AST_LIST_LOCK(&iaxq.queue);
02443    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02444       if (cur->retries < 0)
02445          dead++;
02446       if (cur->final)
02447          final++;
02448       cnt++;
02449    }
02450    AST_LIST_UNLOCK(&iaxq.queue);
02451 
02452    ast_cli(fd, "    IAX Statistics\n");
02453    ast_cli(fd, "---------------------\n");
02454    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02455    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02456    
02457    return RESULT_SUCCESS;
02458 }

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

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

04673 {
04674    struct iax2_thread *thread = NULL;
04675    time_t t;
04676    int threadcount = 0, dynamiccount = 0;
04677    char type;
04678 
04679    if (argc != 3)
04680       return RESULT_SHOWUSAGE;
04681       
04682    ast_cli(fd, "IAX2 Thread Information\n");
04683    time(&t);
04684    ast_cli(fd, "Idle Threads:\n");
04685    AST_LIST_LOCK(&idle_list);
04686    AST_LIST_TRAVERSE(&idle_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       threadcount++;
04695    }
04696    AST_LIST_UNLOCK(&idle_list);
04697    ast_cli(fd, "Active Threads:\n");
04698    AST_LIST_LOCK(&active_list);
04699    AST_LIST_TRAVERSE(&active_list, thread, list) {
04700       if (thread->type == IAX_TYPE_DYNAMIC)
04701          type = 'D';
04702       else
04703          type = 'P';
04704 #ifdef DEBUG_SCHED_MULTITHREAD
04705       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04706          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04707 #else
04708       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04709          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04710 #endif
04711       threadcount++;
04712    }
04713    AST_LIST_UNLOCK(&active_list);
04714    ast_cli(fd, "Dynamic Threads:\n");
04715         AST_LIST_LOCK(&dynamic_list);
04716         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04717 #ifdef DEBUG_SCHED_MULTITHREAD
04718                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04719                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04720 #else
04721                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04722                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04723 #endif
04724       dynamiccount++;
04725         }
04726         AST_LIST_UNLOCK(&dynamic_list);
04727    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04728    return RESULT_SUCCESS;
04729 }

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

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

04490 {
04491    regex_t regexbuf;
04492    int havepattern = 0;
04493 
04494 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04495 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04496 
04497    struct iax2_user *user = NULL;
04498    char auth[90];
04499    char *pstr = "";
04500    struct ao2_iterator i;
04501 
04502    switch (argc) {
04503    case 5:
04504       if (!strcasecmp(argv[3], "like")) {
04505          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04506             return RESULT_SHOWUSAGE;
04507          havepattern = 1;
04508       } else
04509          return RESULT_SHOWUSAGE;
04510    case 3:
04511       break;
04512    default:
04513       return RESULT_SHOWUSAGE;
04514    }
04515 
04516    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04517    i = ao2_iterator_init(users, 0);
04518    for (user = ao2_iterator_next(&i); user; 
04519       user_unref(user), user = ao2_iterator_next(&i)) {
04520       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04521          continue;
04522       
04523       if (!ast_strlen_zero(user->secret)) {
04524          ast_copy_string(auth,user->secret,sizeof(auth));
04525       } else if (!ast_strlen_zero(user->inkeys)) {
04526          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04527       } else
04528          ast_copy_string(auth, "-no secret-", sizeof(auth));
04529       
04530       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04531          pstr = "REQ Only";
04532       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04533          pstr = "Disabled";
04534       else
04535          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04536       
04537       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04538          user->contexts ? user->contexts->context : context,
04539          user->ha ? "Yes" : "No", pstr);
04540    }
04541 
04542    if (havepattern)
04543       regfree(&regexbuf);
04544 
04545    return RESULT_SUCCESS;
04546 #undef FORMAT
04547 #undef FORMAT2
04548 }

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

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

03456 {
03457    int res;
03458    struct iax_ie_data ied0;
03459    struct iax_ie_data ied1;
03460    unsigned int transferid = (unsigned int)ast_random();
03461    memset(&ied0, 0, sizeof(ied0));
03462    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03463    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03464    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03465 
03466    memset(&ied1, 0, sizeof(ied1));
03467    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03468    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03469    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03470    
03471    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03472    if (res)
03473       return -1;
03474    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03475    if (res)
03476       return -1;
03477    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03478    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03479    return 0;
03480 }

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

Definition at line 2281 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02282 {
02283        if (argc != 4)
02284                return RESULT_SHOWUSAGE;
02285 
02286        test_losspct = atoi(argv[3]);
02287 
02288        return RESULT_SUCCESS;
02289 }

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

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

03702 {
03703    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03704    struct iax_ie_data ied;
03705    char tmp[256], *context;
03706    ast_copy_string(tmp, dest, sizeof(tmp));
03707    context = strchr(tmp, '@');
03708    if (context) {
03709       *context = '\0';
03710       context++;
03711    }
03712    memset(&ied, 0, sizeof(ied));
03713    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03714    if (context)
03715       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03716    if (option_debug)
03717       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03718    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03719 }

static int iax2_transmit ( struct iax_frame *  fr  )  [static]

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

02741 {
02742    /* Lock the queue and place this packet at the end */
02743    /* By setting this to 0, the network thread will send it for us, and
02744       queue retransmission if necessary */
02745    fr->sentyet = 0;
02746    AST_LIST_LOCK(&iaxq.queue);
02747    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02748    iaxq.count++;
02749    AST_LIST_UNLOCK(&iaxq.queue);
02750    /* Wake up the network and scheduler thread */
02751    if (netthreadid != AST_PTHREADT_NULL)
02752       pthread_kill(netthreadid, SIGURG);
02753    signal_condition(&sched_lock, &sched_cond);
02754    return 0;
02755 }

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

Definition at line 6554 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06555 {
06556    /* Drop when trunk is about 5 seconds idle */
06557    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06558       return 1;
06559    return 0;
06560 }

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

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

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

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6471 of file chan_iax2.c.

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

Referenced by socket_process().

06472 {
06473    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06474 }

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

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

05022 {
05023    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
05024    int res = -1;
05025    ast_mutex_lock(&iaxsl[callno]);
05026    if (iaxs[callno]) {
05027    /* If there's an outstanding error, return failure now */
05028       if (!iaxs[callno]->error) {
05029          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
05030             res = 0;
05031             /* Don't waste bandwidth sending null frames */
05032          else if (f->frametype == AST_FRAME_NULL)
05033             res = 0;
05034          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
05035             res = 0;
05036          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
05037             res = 0;
05038          else
05039          /* Simple, just queue for transmission */
05040             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
05041       } else {
05042          if (option_debug)
05043             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
05044       }
05045    }
05046    /* If it's already gone, just return */
05047    ast_mutex_unlock(&iaxsl[callno]);
05048    return res;
05049 }

static int iax_check_version ( char *  dev  )  [static]

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

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

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

Definition at line 766 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 772 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

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

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

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

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

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

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

06723 {
06724    struct ast_channel *chan1, *chan2;
06725    struct iax_dual *d;
06726    struct ast_frame *f;
06727    int ext;
06728    int res;
06729    d = stuff;
06730    chan1 = d->chan1;
06731    chan2 = d->chan2;
06732    free(d);
06733    f = ast_read(chan1);
06734    if (f)
06735       ast_frfree(f);
06736    res = ast_park_call(chan1, chan2, 0, &ext);
06737    ast_hangup(chan2);
06738    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06739    return NULL;
06740 }

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

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

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

static void insert_idle_thread ( struct iax2_thread *  thread  )  [static]

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

00901 {
00902    if (thread->type == IAX_TYPE_DYNAMIC) {
00903       AST_LIST_LOCK(&dynamic_list);
00904       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00905       AST_LIST_UNLOCK(&dynamic_list);
00906    } else {
00907       AST_LIST_LOCK(&idle_list);
00908       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00909       AST_LIST_UNLOCK(&idle_list);
00910    }
00911 
00912    return;
00913 }

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

Definition at line 801 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 777 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 789 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

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

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

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

Definition at line 3482 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03483 {
03484    ast_mutex_lock(&iaxsl[callno0]);
03485    while (ast_mutex_trylock(&iaxsl[callno1])) {
03486       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03487    }
03488 }

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

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

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

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

Definition at line 4735 of file chan_iax2.c.

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

Referenced by load_module().

04736 {
04737    ast_cli_netstats(s, -1, 0);
04738    astman_append(s, "\r\n");
04739    return RESULT_SUCCESS;
04740 }

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

Definition at line 4768 of file chan_iax2.c.

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

Referenced by load_module().

04769 {
04770    char *a[] = { "iax2", "show", "users" };
04771    int ret;
04772    const char *id = astman_get_header(m,"ActionID");
04773 
04774    if (!ast_strlen_zero(id))
04775       astman_append(s, "ActionID: %s\r\n",id);
04776    ret = __iax2_show_peers(1, -1, s, 3, a );
04777    astman_append(s, "\r\n\r\n" );
04778    return ret;
04779 } /* /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 1438 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().

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

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

Definition at line 4137 of file chan_iax2.c.

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

Referenced by decode_frame().

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

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

Definition at line 4161 of file chan_iax2.c.

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

Referenced by encrypt_frame().

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

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

Definition at line 5346 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05347 {
05348    /* Select exactly one common encryption if there are any */
05349    p->encmethods &= enc;
05350    if (p->encmethods) {
05351       if (p->encmethods & IAX_ENCRYPT_AES128)
05352          p->encmethods = IAX_ENCRYPT_AES128;
05353       else
05354          p->encmethods = 0;
05355    }
05356 }

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

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

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

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

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

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

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

03201 {
03202    if (ast_strlen_zero(data))
03203       return;
03204 
03205    pds->peer = strsep(&data, "/");
03206    pds->exten = strsep(&data, "/");
03207    pds->options = data;
03208 
03209    if (pds->exten) {
03210       data = pds->exten;
03211       pds->exten = strsep(&data, "@");
03212       pds->context = data;
03213    }
03214 
03215    if (strchr(pds->peer, '@')) {
03216       data = pds->peer;
03217       pds->username = strsep(&data, "@");
03218       pds->peer = data;
03219    }
03220 
03221    if (pds->username) {
03222       data = pds->username;
03223       pds->username = strsep(&data, ":");
03224       pds->password = data;
03225    }
03226 
03227    data = pds->peer;
03228    pds->peer = strsep(&data, ":");
03229    pds->port = data;
03230 
03231    /* check for a key name wrapped in [] in the secret position, if found,
03232       move it to the key field instead
03233    */
03234    if (pds->password && (pds->password[0] == '[')) {
03235       pds->key = ast_strip_quoted(pds->password, "[", "]");
03236       pds->password = NULL;
03237    }
03238 }

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

Referenced by load_module().

01118 {
01119    struct iax2_peer *peer = obj, *peer2 = arg;
01120 
01121    return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
01122 }

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

Definition at line 9783 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09784 {
09785    struct iax2_peer *peer = obj;
09786 
09787    ast_set_flag(peer, IAX_DELME);
09788 
09789    return 0;
09790 }

static void peer_destructor ( void *  obj  )  [static]

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

09309 {
09310    struct iax2_peer *peer = obj;
09311 
09312    ast_free_ha(peer->ha);
09313 
09314    if (peer->callno > 0) {
09315       ast_mutex_lock(&iaxsl[peer->callno]);
09316       iax2_destroy(peer->callno);
09317       ast_mutex_unlock(&iaxsl[peer->callno]);
09318    }
09319 
09320    register_peer_exten(peer, 0);
09321 
09322    if (peer->dnsmgr)
09323       ast_dnsmgr_release(peer->dnsmgr);
09324 
09325    ast_string_field_free_memory(peer);
09326 }

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

References ast_str_hash().

Referenced by load_module().

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

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

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

01165 {
01166    ao2_ref(peer, +1);
01167    return peer;
01168 }

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

Definition at line 11083 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

11084 {
11085    struct iax2_peer *peer = obj;
11086 
11087    if (peer->sockfd < 0)
11088       peer->sockfd = defaultsockfd;
11089 
11090    return 0;
11091 }

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

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

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

peer_status: Report Peer status in character string

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

02328 {
02329    int res = 0;
02330    if (peer->maxms) {
02331       if (peer->lastms < 0) {
02332          ast_copy_string(status, "UNREACHABLE", statuslen);
02333       } else if (peer->lastms > peer->maxms) {
02334          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02335          res = 1;
02336       } else if (peer->lastms) {
02337          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02338          res = 1;
02339       } else {
02340          ast_copy_string(status, "UNKNOWN", statuslen);
02341       }
02342    } else { 
02343       ast_copy_string(status, "Unmonitored", statuslen);
02344       res = -1;
02345    }
02346    return res;
02347 }

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

static void poke_all_peers ( void   )  [static]

Definition at line 10244 of file chan_iax2.c.

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

Referenced by reload_config().

10245 {
10246    struct ao2_iterator i;
10247    struct iax2_peer *peer;
10248 
10249    i = ao2_iterator_init(peers, 0);
10250    while ((peer = ao2_iterator_next(&i))) {
10251       iax2_poke_peer(peer, 0);
10252       peer_unref(peer);
10253    }
10254 }

static void prune_peers ( void   )  [static]

Definition at line 9841 of file chan_iax2.c.

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

09842 {
09843    struct iax2_peer *peer;
09844    struct ao2_iterator i;
09845 
09846    i = ao2_iterator_init(peers, 0);
09847    while ((peer = ao2_iterator_next(&i))) {
09848       if (ast_test_flag(peer, IAX_DELME))
09849          unlink_peer(peer);
09850       peer_unref(peer);
09851    }
09852 }

static void prune_users ( void   )  [static]

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

09828 {
09829    struct iax2_user *user;
09830    struct ao2_iterator i;
09831 
09832    i = ao2_iterator_init(users, 0);
09833    while ((user = ao2_iterator_next(&i))) {
09834       if (ast_test_flag(user, IAX_DELME))
09835          ao2_unlink(users, user);
09836       user_unref(user);
09837    }
09838 }

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

Definition at line 11100 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

11101 {
11102    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
11103 
11104    /* The frames_received field is used to hold whether we're matching
11105     * against a full frame or not ... */
11106 
11107    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
11108       pvt2->frames_received) ? CMP_MATCH : 0;
11109 }

static void pvt_destructor ( void *  obj  )  [static]

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

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

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

Definition at line 11093 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

11094 {
11095    const struct chan_iax2_pvt *pvt = obj;
11096 
11097    return pvt->peercallno;
11098 }

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

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

05329 {
05330    struct ast_iax2_full_hdr fh;
05331    fh.scallno = htons(src | IAX_FLAG_FULL);
05332    fh.dcallno = htons(dst);
05333    fh.ts = 0;
05334    fh.oseqno = 0;
05335    fh.iseqno = 0;
05336    fh.type = AST_FRAME_IAX;
05337    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05338    if (iaxdebug)
05339        iax_showframe(NULL, &fh, 0, sin, 0);
05340    if (option_debug)
05341       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05342          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05343    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05344 }

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

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

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

Definition at line 2995 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02996 {
02997    char port[10];
02998    char regseconds[20];
02999    
03000    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
03001    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
03002    ast_update_realtime("iaxpeers", "name", peername, 
03003       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
03004       "regseconds", regseconds, NULL);
03005 }

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

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

static void reg_source_db ( struct iax2_peer *  p  )  [static]

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

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

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

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

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

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

Verify inbound registration.

Definition at line 5492 of file chan_iax2.c.

References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_device_state_changed(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_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, IAX_STATE_UNCHANGED, iaxs, iaxsl, inaddrcmp(), 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().

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

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6289 of file chan_iax2.c.

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

Referenced by socket_process().

06290 {
06291    struct iax_ie_data ied;
06292    struct iax2_peer *p;
06293    char challenge[10];
06294    const char *peer_name;
06295    int res = -1;
06296 
06297    peer_name = ast_strdupa(iaxs[callno]->peer);
06298 
06299    /* SLD: third call to find_peer in registration */
06300    ast_mutex_unlock(&iaxsl[callno]);
06301    p = find_peer(peer_name, 1);
06302    ast_mutex_lock(&iaxsl[callno]);
06303    if (!iaxs[callno])
06304       goto return_unref;
06305    if (!p) {
06306       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06307       goto return_unref;
06308    }
06309    
06310    memset(&ied, 0, sizeof(ied));
06311    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06312    if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06313       /* Build the challenge */
06314       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06315       ast_string_field_set(iaxs[callno], challenge, challenge);
06316       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06317    }
06318    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06319 
06320    res = 0;
06321 
06322 return_unref:
06323    peer_unref(p);
06324 
06325    return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
06326 }

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

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

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

static char* regstate2str ( int  regstate  )  [static]

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

04782 {
04783    switch(regstate) {
04784    case REG_STATE_UNREGISTERED:
04785       return "Unregistered";
04786    case REG_STATE_REGSENT:
04787       return "Request Sent";
04788    case REG_STATE_AUTHSENT:
04789       return "Auth. Sent";
04790    case REG_STATE_REGISTERED:
04791       return "Registered";
04792    case REG_STATE_REJECTED:
04793       return "Rejected";
04794    case REG_STATE_TIMEOUT:
04795       return "Timeout";
04796    case REG_STATE_NOAUTH:
04797       return "No Authentication";
04798    default:
04799       return "Unknown";
04800    }
04801 }

static int reload ( void   )  [static]

Definition at line 10281 of file chan_iax2.c.

References reload_config().

10282 {
10283    return reload_config();
10284 }

static int reload_config ( void   )  [static]

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

10256 {
10257    char *config = "iax.conf";
10258    struct iax2_registry *reg;
10259 
10260    if (set_config(config, 1) > 0) {
10261       prune_peers();
10262       prune_users();
10263       AST_LIST_LOCK(&registrations);
10264       AST_LIST_TRAVERSE(&registrations, reg, entry)
10265          iax2_do_register(reg);
10266       AST_LIST_UNLOCK(&registrations);
10267       /* Qualify hosts, too */
10268       poke_all_peers();
10269    }
10270    reload_firmware(0);
10271    iax_provision_reload();
10272 
10273    return 0;
10274 }

static void reload_firmware ( int  unload  )  [static]

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

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

static void remove_by_peercallno ( struct chan_iax2_pvt *  pvt  )  [static]

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

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

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

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

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

09058 {
09059    int count;
09060    int res;
09061    struct timeval tv;
09062    struct timespec ts;
09063 
09064    for (;;) {
09065       res = ast_sched_wait(sched);
09066       if ((res > 1000) || (res < 0))
09067          res = 1000;
09068       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
09069       ts.tv_sec = tv.tv_sec;
09070       ts.tv_nsec = tv.tv_usec * 1000;
09071 
09072       pthread_testcancel();
09073       ast_mutex_lock(&sched_lock);
09074       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
09075       ast_mutex_unlock(&sched_lock);
09076       pthread_testcancel();
09077 
09078       count = ast_sched_runq(sched);
09079       if (option_debug && count >= 20)
09080          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
09081    }
09082    return NULL;
09083 }

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

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

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

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

Referenced by socket_process().

03174 {
03175    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03176       .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX,
03177       .csub = compress_subclass(command) };
03178 
03179    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03180 }

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

05085 {
05086    int call_num = i->callno;
05087    /* It is assumed that the callno has already been locked */
05088    iax2_predestroy(i->callno);
05089    if (!iaxs[call_num])
05090       return -1;
05091    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05092 }

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

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05095 {
05096    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05097 }

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

05071 {
05072    int res;
05073    ast_mutex_lock(&iaxsl[callno]);
05074    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05075    ast_mutex_unlock(&iaxsl[callno]);
05076    return res;
05077 }

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

References __send_command().

Referenced by socket_process(), and try_transfer().

05100 {
05101    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05102 }

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

Definition at line 1061 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

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

static int send_packet ( struct iax_frame *  f  )  [static]

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

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

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

Definition at line 1021 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

01022 {
01023 #ifdef SCHED_MULTITHREADED
01024    if (schedule_action(__send_ping, data))
01025 #endif      
01026       __send_ping(data);
01027    return 0;
01028 }

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

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

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

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

Load configuration.

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

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

static void set_config_destroy ( void   )  [static]

Definition at line 9869 of file chan_iax2.c.

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

Referenced by set_config().

09870 {
09871    strcpy(accountcode, "");
09872    strcpy(language, "");
09873    strcpy(mohinterpret, "default");
09874    strcpy(mohsuggest, "");
09875    amaflags = 0;
09876    delayreject = 0;
09877    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09878    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09879    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09880    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09881    delete_users();
09882 }

static void set_timing ( void   )  [static]

Definition at line 9854 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09855 {
09856 #ifdef HAVE_ZAPTEL
09857    int bs = trunkfreq * 8;
09858    if (timingfd > -1) {
09859       if (
09860 #ifdef ZT_TIMERACK
09861          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09862 #endif         
09863          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09864          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09865    }
09866 #endif
09867 }

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

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

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

static int socket_process ( struct iax2_thread *  thread  )  [static]

Definition at line 6984 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_STATE_UNCHANGED, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), iaxq, iaxs, iaxsl, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, ast_iax2_full_hdr::iseqno, iax_frame::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_frame::len, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), ast_frame::mallocd, manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, iax_ies::musiconhold, ast_channel::nativeformats, NEW_ALLOW, NEW_PREVENT, ast_frame::offset, option_debug, option_verbose, chan_iax2_pvt::oseqno, iax_frame::oseqno, ast_iax2_full_hdr::oseqno, iax_frame::outoforder, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, 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().

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

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

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

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

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

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

06694 {
06695    pthread_t newthread;
06696    struct dpreq_data *dpr;
06697    pthread_attr_t attr;
06698    
06699    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06700       return;
06701 
06702    pthread_attr_init(&attr);
06703    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06704 
06705    dpr->callno = callno;
06706    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06707    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06708    if (callerid)
06709       dpr->callerid = ast_strdup(callerid);
06710    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06711       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06712    }
06713 
06714    pthread_attr_destroy(&attr);
06715 }

static int start_network_thread ( void   )  [static]

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

09153 {
09154    pthread_attr_t attr;
09155    int threadcount = 0;
09156    int x;
09157    for (x = 0; x < iaxthreadcount; x++) {
09158       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
09159       if (thread) {
09160          thread->type = IAX_TYPE_POOL;
09161          thread->threadnum = ++threadcount;
09162          ast_mutex_init(&thread->lock);
09163          ast_cond_init(&thread->cond, NULL);
09164          pthread_attr_init(&attr);
09165          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
09166          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
09167             ast_log(LOG_WARNING, "Failed to create new thread!\n");
09168             free(thread);
09169             thread = NULL;
09170          }
09171          AST_LIST_LOCK(&idle_list);
09172          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
09173          AST_LIST_UNLOCK(&idle_list);
09174       }
09175    }
09176    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
09177    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
09178    if (option_verbose > 1)
09179       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
09180    return 0;
09181 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6375 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06376 {
06377    iax2_destroy_helper(iaxs[callno]);
06378 }

static void store_by_peercallno ( struct chan_iax2_pvt *  pvt  )  [static]

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

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

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

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

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

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

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

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

static int try_firmware ( char *  s  )  [static]

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

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

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

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

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

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1090 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

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

static void unlink_peer ( struct iax2_peer *  peer  )  [static]

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

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

static int unload_module ( void   )  [static]

Definition at line 11077 of file chan_iax2.c.

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

11078 {
11079    ast_custom_function_unregister(&iaxpeer_function);
11080    return __unload_module();
11081 }

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

Definition at line 3490 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03491 {
03492    ast_mutex_unlock(&iaxsl[callno1]);
03493    ast_mutex_unlock(&iaxsl[callno0]);
03494 }

static void unwrap_timestamp ( struct iax_frame *  fr  )  [static]

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

02517 {
02518    int x;
02519 
02520    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02521       x = fr->ts - iaxs[fr->callno]->last;
02522       if (x < -50000) {
02523          /* Sudden big jump backwards in timestamp:
02524             What likely happened here is that miniframe timestamp has circled but we haven't
02525             gotten the update from the main packet.  We'll just pretend that we did, and
02526             update the timestamp appropriately. */
02527          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02528          if (option_debug && iaxdebug)
02529             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02530       }
02531       if (x > 50000) {
02532          /* Sudden apparent big jump forwards in timestamp:
02533             What's likely happened is this is an old miniframe belonging to the previous
02534             top-16-bit timestamp that has turned up out of order.
02535             Adjust the timestamp appropriately. */
02536          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02537          if (option_debug && iaxdebug)
02538             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02539       }
02540    }
02541 }

static void update_jbsched ( struct chan_iax2_pvt *  pvt  )  [static]

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

02546 {
02547    int when;
02548    
02549    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02550    
02551    when = jb_next(pvt->jb) - when;
02552 
02553    AST_SCHED_DEL(sched, pvt->jbid);
02554 
02555    if(when <= 0) {
02556       /* XXX should really just empty until when > 0.. */
02557       when = 1;
02558    }
02559    
02560    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02561 }

static void update_max_nontrunk ( void   )  [static]

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

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

static void update_max_trunk ( void   )  [static]

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

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

static int update_packet ( struct iax_frame *  f  )  [static]

Definition at line 2142 of file chan_iax2.c.

References iax_frame::callno, iax_frame::data, iax_frame::datalen, iax_frame::dcallno, ast_iax2_full_hdr::dcallno, decode_frame(), iax_frame::ecx, iax_frame::encmethods, encrypt_frame(), IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, iax_frame::mydcx, and iax_frame::semirand.

Referenced by __attempt_transmit().

02143 {
02144    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02145    struct ast_iax2_full_hdr *fh = f->data;
02146    struct ast_frame af;
02147 
02148    /* if frame is encrypted. decrypt before updating it. */
02149    if (f->encmethods) {
02150       decode_frame(&f->mydcx, fh, &af, &f->datalen);
02151    }
02152    /* Mark this as a retransmission */
02153    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02154    /* Update iseqno */
02155    f->iseqno = iaxs[f->callno]->iseqno;
02156    fh->iseqno = f->iseqno;
02157 
02158    /* Now re-encrypt the frame */
02159    if (f->encmethods) {
02160       encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen);
02161    }
02162    return 0;
02163 }

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

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

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

Referenced by load_module().

01138 {
01139    struct iax2_user *user = obj, *user2 = arg;
01140 
01141    return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
01142 }

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

Definition at line 9792 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09793 {
09794    struct iax2_user *user = obj;
09795 
09796    ast_set_flag(user, IAX_DELME);
09797 
09798    return 0;
09799 }

static void user_destructor ( void *  obj  )  [static]

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

09557 {
09558    struct iax2_user *user = obj;
09559 
09560    ast_free_ha(user->ha);
09561    free_context(user->contexts);
09562    if(user->vars) {
09563       ast_variables_destroy(user->vars);
09564       user->vars = NULL;
09565    }
09566    ast_string_field_free_memory(user);
09567 }

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

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1176 of file chan_iax2.c.

References ao2_ref().

01177 {
01178    ao2_ref(user, +1);
01179    return user;
01180 }

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

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

01183 {
01184    ao2_ref(user, -1);
01185    return NULL;
01186 }

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

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

06477 {
06478    struct iax_frame *f;
06479 
06480    AST_LIST_LOCK(&iaxq.queue);
06481    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06482       /* Send a copy immediately */
06483       if ((f->callno == callno) && iaxs[f->callno] &&
06484          ((unsigned char ) (f->oseqno - last) < 128) &&
06485          (f->retries >= 0)) {
06486          send_packet(f);
06487       }
06488    }
06489    AST_LIST_UNLOCK(&iaxq.queue);
06490 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

int adsi = 0 [static]

Definition at line 222 of file chan_iax2.c.

int amaflags = 0 [static]

Definition at line 221 of file chan_iax2.c.

int authdebug = 1 [static]

Definition at line 158 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 159 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

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

Initial value:

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

Definition at line 10878 of file chan_iax2.c.

Initial value:

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

Definition at line 10888 of file chan_iax2.c.

Initial value:

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

Definition at line 10883 of file chan_iax2.c.

Initial value:

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

Definition at line 10868 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 10842 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 10834 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 10826 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 175 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 223 of file chan_iax2.c.

struct iax2_dpcache * dpcache [static]

Referenced by find_cache(), and iax2_show_cache().

int global_rtautoclear = 120 [static]

Definition at line 277 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 204 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 224 of file chan_iax2.c.

enum { ... } iax2_flags

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

char iax2_reload_usage[] [static]

Initial value:

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

Definition at line 10784 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10758 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 10850 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 827 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 206 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 162 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 164 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

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

struct io_context* io [static]

Definition at line 201 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 153 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 147 of file chan_iax2.c.

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

Definition at line 816 of file chan_iax2.c.

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

int max_reg_expire [static]

Definition at line 169 of file chan_iax2.c.

int max_retries = 4 [static]

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

Referenced by __find_callno(), and update_max_nontrunk().

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 833 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_trunk().

int min_reg_expire [static]

Definition at line 168 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 219 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 220 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 173 of file chan_iax2.c.

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 228 of file chan_iax2.c.

char no_debug_jb_usage[] [static]

Initial value:

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

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

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 174 of file chan_iax2.c.

char* papp = "IAX2Provision" [static]

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

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

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

Definition at line 231 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 229 of file chan_iax2.c.

char show_cache_usage[] [static]

Initial value:

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

Definition at line 10772 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 10800 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 10818 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 10804 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 10776 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 10812 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10788 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 10822 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 10768 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 10808 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 10795 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 210 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 171 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 166 of file chan_iax2.c.

struct iax2_trunk_peer * tpeers [static]

Referenced by find_tpeer(), and timing_read().

int trunkfreq = 20 [static]

Definition at line 157 of file chan_iax2.c.

struct ao2_container* users [static]

struct ast_firmware_list waresl [static]


Generated on Sat Apr 18 23:45:18 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.8