Tue Sep 30 01:19:47 2008

Asterisk developer's documentation


chan_iax2.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Functions

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

Variables

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


Detailed Description

Implementation of Inter-Asterisk eXchange Version 2.

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

Definition in file chan_iax2.c.


Define Documentation

#define CACHE_FLAG_CANEXIST   (1 << 2)

Extension can exist

Definition at line 665 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 661 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 675 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 663 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 667 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 669 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

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

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 126 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 114 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 134 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 132 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

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

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 698 of file chan_iax2.c.

Referenced by iax2_process_thread().

#define IAX_IOSTATE_READY   1

Definition at line 697 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 699 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 701 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 647 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 652 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 1429 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

#define NEW_PREVENT   0

Definition at line 1428 of file chan_iax2.c.

Referenced by socket_process().

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

#define SCHED_MULTITHREADED

Definition at line 110 of file chan_iax2.c.

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

#define TRUNK_CALL_START   ARRAY_LEN(iaxs) / 2

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

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

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

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

06349 {
06350    /* Called from IAX thread only, without iaxs lock */
06351    int callno = (int)(long)(nothing);
06352    struct iax_ie_data ied;
06353    ast_mutex_lock(&iaxsl[callno]);
06354    if (iaxs[callno]) {
06355       memset(&ied, 0, sizeof(ied));
06356       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06357          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06358          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06359       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06360          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06361          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06362       }
06363       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06364    }
06365    ast_mutex_unlock(&iaxsl[callno]);
06366 }

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

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

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

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

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

06398 {
06399    /* Called from IAX thread only, without iaxs lock */
06400    int callno = (int)(long)(nothing);
06401    struct iax_ie_data ied;
06402    ast_mutex_lock(&iaxsl[callno]);
06403    if (iaxs[callno]) {
06404       memset(&ied, 0, sizeof(ied));
06405       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06406       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06407       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06408    }
06409    ast_mutex_unlock(&iaxsl[callno]);
06410 }

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

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

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

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

06037 {
06038    struct iax2_peer *peer = (struct iax2_peer *) data;
06039 
06040    if (!peer)
06041       return;
06042 
06043    peer->expire = -1;
06044 
06045    if (option_debug)
06046       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
06047    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
06048       realtime_update_peer(peer->name, &peer->addr, 0);
06049    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
06050    /* Reset the address */
06051    memset(&peer->addr, 0, sizeof(peer->addr));
06052    /* Reset expiry value */
06053    peer->expiry = min_reg_expire;
06054    if (!ast_test_flag(peer, IAX_TEMPONLY))
06055       ast_db_del("IAX/Registry", peer->name);
06056    register_peer_exten(peer, 0);
06057    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
06058    if (iax2_regfunk)
06059       iax2_regfunk(peer->name, 0);
06060 
06061    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
06062       unlink_peer(peer);
06063 
06064    peer_unref(peer);
06065 }

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

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

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

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

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

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

Definition at line 5729 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05730 {
05731    struct iax2_registry *reg = (struct iax2_registry *)data;
05732    reg->expire = -1;
05733    iax2_do_register(reg);
05734 }

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

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

08831 {
08832    struct iax2_peer *peer = (struct iax2_peer *)data;
08833    int callno;
08834 
08835    if (peer->lastms > -1) {
08836       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08837       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08838       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08839    }
08840    if ((callno = peer->callno) > 0) {
08841       ast_mutex_lock(&iaxsl[callno]);
08842       iax2_destroy(callno);
08843       ast_mutex_unlock(&iaxsl[callno]);
08844    }
08845    peer->callno = 0;
08846    peer->lastms = -1;
08847    /* Try again quickly */
08848    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08849    if (peer->pokeexpire == -1)
08850       peer_unref(peer);
08851 }

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

Definition at line 6460 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06461 {
06462    struct iax2_peer *peer = (struct iax2_peer *)data;
06463    iax2_poke_peer(peer, 0);
06464    peer_unref(peer);
06465 }

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

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

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

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

Definition at line 958 of file chan_iax2.c.

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

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

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

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

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

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

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

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

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

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

static int __unload_module ( void   )  [static]

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

10958 {
10959    struct iax2_thread *thread = NULL;
10960    int x;
10961 
10962    /* Make sure threads do not hold shared resources when they are canceled */
10963    
10964    /* Grab the sched lock resource to keep it away from threads about to die */
10965    /* Cancel the network thread, close the net socket */
10966    if (netthreadid != AST_PTHREADT_NULL) {
10967       AST_LIST_LOCK(&iaxq.queue);
10968       ast_mutex_lock(&sched_lock);
10969       pthread_cancel(netthreadid);
10970       ast_cond_signal(&sched_cond);
10971       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10972       AST_LIST_UNLOCK(&iaxq.queue);
10973       pthread_join(netthreadid, NULL);
10974    }
10975    if (schedthreadid != AST_PTHREADT_NULL) {
10976       ast_mutex_lock(&sched_lock);  
10977       pthread_cancel(schedthreadid);
10978       ast_cond_signal(&sched_cond);
10979       ast_mutex_unlock(&sched_lock);   
10980       pthread_join(schedthreadid, NULL);
10981    }
10982    
10983    /* Call for all threads to halt */
10984    AST_LIST_LOCK(&idle_list);
10985    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10986       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10987       pthread_cancel(thread->threadid);
10988    }
10989    AST_LIST_TRAVERSE_SAFE_END
10990    AST_LIST_UNLOCK(&idle_list);
10991 
10992    AST_LIST_LOCK(&active_list);
10993    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10994       AST_LIST_REMOVE_CURRENT(&active_list, list);
10995       pthread_cancel(thread->threadid);
10996    }
10997    AST_LIST_TRAVERSE_SAFE_END
10998    AST_LIST_UNLOCK(&active_list);
10999 
11000    AST_LIST_LOCK(&dynamic_list);
11001         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
11002       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
11003       pthread_cancel(thread->threadid);
11004         }
11005    AST_LIST_TRAVERSE_SAFE_END
11006         AST_LIST_UNLOCK(&dynamic_list);
11007 
11008    AST_LIST_HEAD_DESTROY(&iaxq.queue);
11009 
11010    /* Wait for threads to exit */
11011    while(0 < iaxactivethreadcount)
11012       usleep(10000);
11013    
11014    ast_netsock_release(netsock);
11015    ast_netsock_release(outsock);
11016    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
11017       if (iaxs[x]) {
11018          iax2_destroy(x);
11019       }
11020    }
11021    ast_manager_unregister( "IAXpeers" );
11022    ast_manager_unregister( "IAXnetstats" );
11023    ast_unregister_application(papp);
11024    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11025    ast_unregister_switch(&iax2_switch);
11026    ast_channel_unregister(&iax2_tech);
11027    delete_users();
11028    iax_provision_unload();
11029    sched_context_destroy(sched);
11030    reload_firmware(1);
11031 
11032    ast_mutex_destroy(&waresl.lock);
11033 
11034    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11035       ast_mutex_destroy(&iaxsl[x]);
11036    }
11037 
11038    ao2_ref(peers, -1);
11039    ao2_ref(users, -1);
11040    ao2_ref(iax_peercallno_pvts, -1);
11041 
11042    return 0;
11043 }

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

Definition at line 5073 of file chan_iax2.c.

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

Referenced by check_access().

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

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

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

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

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

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

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

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

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

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

06383 {
06384    /* Schedule sending the authentication failure in one second, to prevent
06385       guessing */
06386    if (iaxs[callno]) {
06387       iaxs[callno]->authfail = failcode;
06388       if (delayreject) {
06389          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06390          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06391       } else
06392          auth_reject((void *)(long)callno);
06393    }
06394    return 0;
06395 }

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

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

06369 {
06370    int callno = (int)(long)(data);
06371    ast_mutex_lock(&iaxsl[callno]);
06372    if (iaxs[callno])
06373       iaxs[callno]->authid = -1;
06374    ast_mutex_unlock(&iaxsl[callno]);
06375 #ifdef SCHED_MULTITHREADED
06376    if (schedule_action(__auth_reject, data))
06377 #endif      
06378       __auth_reject(data);
06379    return 0;
06380 }

static int authenticate ( const char *  challenge,
const char *  secret,
const char *  keyn,
int  authmethods,
struct iax_ie_data ied,
struct sockaddr_in *  sin,
aes_encrypt_ctx ecx,
aes_decrypt_ctx dcx 
) [static]

Definition at line 5598 of file chan_iax2.c.

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

05599 {
05600    int res = -1;
05601    int x;
05602    if (!ast_strlen_zero(keyn)) {
05603       if (!(authmethods & IAX_AUTH_RSA)) {
05604          if (ast_strlen_zero(secret)) 
05605             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));
05606       } else if (ast_strlen_zero(challenge)) {
05607          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05608       } else {
05609          char sig[256];
05610          struct ast_key *key;
05611          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05612          if (!key) {
05613             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05614          } else {
05615             if (ast_sign(key, (char*)challenge, sig)) {
05616                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05617                res = -1;
05618             } else {
05619                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05620                res = 0;
05621             }
05622          }
05623       }
05624    } 
05625    /* Fall back */
05626    if (res && !ast_strlen_zero(secret)) {
05627       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05628          struct MD5Context md5;
05629          unsigned char digest[16];
05630          char digres[128];
05631          MD5Init(&md5);
05632          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05633          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05634          MD5Final(digest, &md5);
05635          /* If they support md5, authenticate with it.  */
05636          for (x=0;x<16;x++)
05637             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05638          if (ecx && dcx)
05639             build_enc_keys(digest, ecx, dcx);
05640          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05641          res = 0;
05642       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05643          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05644          res = 0;
05645       } else
05646          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05647    }
05648    return res;
05649 }

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

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax2_peer::authmethods, iax_ie_data::buf, chan_iax2_pvt::callno, iax2_registry::callno, iax_ies::challenge, chan_iax2_pvt::dcx, chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, iax2_peer::mask, merge_encryption(), peer_unref(), peers, iax_ie_data::pos, realtime_peer(), send_command(), and iax_ies::username.

Referenced by socket_process().

05656 {
05657    struct iax2_peer *peer = NULL;
05658    /* Start pessimistic */
05659    int res = -1;
05660    int authmethods = 0;
05661    struct iax_ie_data ied;
05662    uint16_t callno = p->callno;
05663 
05664    memset(&ied, 0, sizeof(ied));
05665    
05666    if (ies->username)
05667       ast_string_field_set(p, username, ies->username);
05668    if (ies->challenge)
05669       ast_string_field_set(p, challenge, ies->challenge);
05670    if (ies->authmethods)
05671       authmethods = ies->authmethods;
05672    if (authmethods & IAX_AUTH_MD5)
05673       merge_encryption(p, ies->encmethods);
05674    else
05675       p->encmethods = 0;
05676 
05677    /* Check for override RSA authentication first */
05678    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05679       /* Normal password authentication */
05680       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05681    } else {
05682       struct ao2_iterator i = ao2_iterator_init(peers, 0);
05683       while ((peer = ao2_iterator_next(&i))) {
05684          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05685              /* No peer specified at our end, or this is the peer */
05686              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05687              /* No username specified in peer rule, or this is the right username */
05688              && (!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)))
05689              /* No specified host, or this is our host */
05690             ) {
05691             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05692             if (!res) {
05693                peer_unref(peer);
05694                break;
05695             }
05696          }
05697          peer_unref(peer);
05698       }
05699       if (!peer) {
05700          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05701             that we're trying to authenticate *to* a realtime peer */
05702          const char *peer_name = ast_strdupa(p->peer);
05703          ast_mutex_unlock(&iaxsl[callno]);
05704          if ((peer = realtime_peer(peer_name, NULL))) {
05705             ast_mutex_lock(&iaxsl[callno]);
05706             if (!(p = iaxs[callno])) {
05707                peer_unref(peer);
05708                return -1;
05709             }
05710             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05711             peer_unref(peer);
05712          }
05713          if (!peer) {
05714             ast_mutex_lock(&iaxsl[callno]);
05715             if (!(p = iaxs[callno]))
05716                return -1;
05717          }
05718       }
05719    }
05720    if (ies->encmethods)
05721       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05722    if (!res)
05723       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05724    return res;
05725 }

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

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

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

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

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

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

Definition at line 3117 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

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

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

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

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

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

Definition at line 9151 of file chan_iax2.c.

References ast_calloc, and iax2_context::context.

Referenced by build_user().

09152 {
09153    struct iax2_context *con;
09154 
09155    if ((con = ast_calloc(1, sizeof(*con))))
09156       ast_copy_string(con->context, context, sizeof(con->context));
09157    
09158    return con;
09159 }

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

Definition at line 4105 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

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

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

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

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

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

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

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

10255 {
10256    struct sockaddr_in sin;
10257    int x;
10258    int callno;
10259    struct iax_ie_data ied;
10260    struct create_addr_info cai;
10261    struct parsed_dial_string pds;
10262    char *tmpstr;
10263 
10264    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
10265       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10266          look up entries for a single context */
10267       if (!ast_mutex_trylock(&iaxsl[x])) {
10268          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10269             return x;
10270          ast_mutex_unlock(&iaxsl[x]);
10271       }
10272    }
10273 
10274    /* No match found, we need to create a new one */
10275 
10276    memset(&cai, 0, sizeof(cai));
10277    memset(&ied, 0, sizeof(ied));
10278    memset(&pds, 0, sizeof(pds));
10279 
10280    tmpstr = ast_strdupa(data);
10281    parse_dial_string(tmpstr, &pds);
10282 
10283    if (ast_strlen_zero(pds.peer)) {
10284       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
10285       return -1;
10286    }
10287 
10288    /* Populate our address from the given */
10289    if (create_addr(pds.peer, NULL, &sin, &cai))
10290       return -1;
10291 
10292    if (option_debug)
10293       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10294          pds.peer, pds.username, pds.password, pds.context);
10295 
10296    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10297    if (callno < 1) {
10298       ast_log(LOG_WARNING, "Unable to create call\n");
10299       return -1;
10300    }
10301 
10302    ast_string_field_set(iaxs[callno], dproot, data);
10303    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10304 
10305    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10306    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10307    /* the string format is slightly different from a standard dial string,
10308       because the context appears in the 'exten' position
10309    */
10310    if (pds.exten)
10311       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10312    if (pds.username)
10313       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10314    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10315    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10316    /* Keep password handy */
10317    if (pds.password)
10318       ast_string_field_set(iaxs[callno], secret, pds.password);
10319    if (pds.key)
10320       ast_string_field_set(iaxs[callno], outkey, pds.key);
10321    /* Start the call going */
10322    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10323 
10324    return callno;
10325 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 6770 of file chan_iax2.c.

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

Referenced by socket_process().

06771 {
06772    unsigned int ourver;
06773    char rsi[80];
06774    snprintf(rsi, sizeof(rsi), "si-%s", si);
06775    if (iax_provision_version(&ourver, rsi, 1))
06776       return 0;
06777    if (option_debug)
06778       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06779    if (ourver != ver) 
06780       iax2_provision(sin, sockfd, NULL, rsi, 1);
06781    return 0;
06782 }

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

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

Referenced by peer_set_srcaddr().

09178 {
09179    int sd;
09180    int res;
09181    
09182    sd = socket(AF_INET, SOCK_DGRAM, 0);
09183    if (sd < 0) {
09184       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
09185       return -1;
09186    }
09187 
09188    res = bind(sd, sa, salen);
09189    if (res < 0) {
09190       if (option_debug)
09191          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09192       close(sd);
09193       return 1;
09194    }
09195 
09196    close(sd);
09197    return 0;
09198 }

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

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

05775 {
05776    char exten[256] = "";
05777    int status = CACHE_FLAG_UNKNOWN;
05778    int expiry = iaxdefaultdpcache;
05779    int x;
05780    int matchmore = 0;
05781    struct iax2_dpcache *dp, *prev;
05782    
05783    if (ies->called_number)
05784       ast_copy_string(exten, ies->called_number, sizeof(exten));
05785 
05786    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05787       status = CACHE_FLAG_EXISTS;
05788    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05789       status = CACHE_FLAG_CANEXIST;
05790    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05791       status = CACHE_FLAG_NONEXISTENT;
05792 
05793    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05794       /* Don't really do anything with this */
05795    }
05796    if (ies->refresh)
05797       expiry = ies->refresh;
05798    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05799       matchmore = CACHE_FLAG_MATCHMORE;
05800    ast_mutex_lock(&dpcache_lock);
05801    prev = NULL;
05802    dp = pvt->dpentries;
05803    while(dp) {
05804       if (!strcmp(dp->exten, exten)) {
05805          /* Let them go */
05806          if (prev)
05807             prev->peer = dp->peer;
05808          else
05809             pvt->dpentries = dp->peer;
05810          dp->peer = NULL;
05811          dp->callno = 0;
05812          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05813          if (dp->flags & CACHE_FLAG_PENDING) {
05814             dp->flags &= ~CACHE_FLAG_PENDING;
05815             dp->flags |= status;
05816             dp->flags |= matchmore;
05817          }
05818          /* Wake up waiters */
05819          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05820             if (dp->waiters[x] > -1)
05821                write(dp->waiters[x], "asdf", 4);
05822       }
05823       prev = dp;
05824       dp = dp->peer;
05825    }
05826    ast_mutex_unlock(&dpcache_lock);
05827    return 0;
05828 }

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

Definition at line 2392 of file chan_iax2.c.

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

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

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

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

05831 {
05832    int peercallno = 0;
05833    struct chan_iax2_pvt *pvt = iaxs[callno];
05834    struct iax_frame *cur;
05835    jb_frame frame;
05836 
05837    if (ies->callno)
05838       peercallno = ies->callno;
05839 
05840    if (peercallno < 1) {
05841       ast_log(LOG_WARNING, "Invalid transfer request\n");
05842       return -1;
05843    }
05844    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05845    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05846    /* Reset sequence numbers */
05847    pvt->oseqno = 0;
05848    pvt->rseqno = 0;
05849    pvt->iseqno = 0;
05850    pvt->aseqno = 0;
05851 
05852    if (pvt->peercallno) {
05853       remove_by_peercallno(pvt);
05854    }
05855    pvt->peercallno = peercallno;
05856    store_by_peercallno(pvt);
05857 
05858    pvt->transferring = TRANSFER_NONE;
05859    pvt->svoiceformat = -1;
05860    pvt->voiceformat = 0;
05861    pvt->svideoformat = -1;
05862    pvt->videoformat = 0;
05863    pvt->transfercallno = -1;
05864    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05865    memset(&pvt->offset, 0, sizeof(pvt->offset));
05866    /* reset jitterbuffer */
05867    while(jb_getall(pvt->jb,&frame) == JB_OK)
05868       iax2_frame_free(frame.data);
05869    jb_reset(pvt->jb);
05870    pvt->lag = 0;
05871    pvt->last = 0;
05872    pvt->lastsent = 0;
05873    pvt->nextpred = 0;
05874    pvt->pingtime = DEFAULT_RETRY_TIME;
05875    AST_LIST_LOCK(&iaxq.queue);
05876    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05877       /* We must cancel any packets that would have been transmitted
05878          because now we're talking to someone new.  It's okay, they
05879          were transmitted to someone that didn't care anyway. */
05880       if (callno == cur->callno) 
05881          cur->retries = -1;
05882    }
05883    AST_LIST_UNLOCK(&iaxq.queue);
05884    return 0; 
05885 }

static unsigned char compress_subclass ( int  subclass  )  [static]

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

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

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

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

06785 {
06786    jb_info stats;
06787    jb_getinfo(pvt->jb, &stats);
06788    
06789    memset(iep, 0, sizeof(*iep));
06790 
06791    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06792    if(stats.frames_in == 0) stats.frames_in = 1;
06793    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06794    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06795    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06796    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06797    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06798 }

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

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

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

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

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

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

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

Definition at line 4245 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

06847 {
06848    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06849    struct ast_iax2_full_hdr *fh, *cur_fh;
06850 
06851    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06852       return;
06853 
06854    pkt_buf->len = from_here->buf_len;
06855    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06856 
06857    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06858    ast_mutex_lock(&to_here->lock);
06859    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06860       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06861       if (fh->oseqno < cur_fh->oseqno) {
06862          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06863          break;
06864       }
06865    }
06866    AST_LIST_TRAVERSE_SAFE_END
06867 
06868    if (!cur_pkt_buf)
06869       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06870    
06871    ast_mutex_unlock(&to_here->lock);
06872 }

static void delete_users ( void   )  [static]

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

09770 {
09771    struct iax2_registry *reg;
09772 
09773    ao2_callback(users, 0, user_delme_cb, NULL);
09774 
09775    AST_LIST_LOCK(&registrations);
09776    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09777       ast_sched_del(sched, reg->expire);
09778       if (reg->callno) {
09779          ast_mutex_lock(&iaxsl[reg->callno]);
09780          if (iaxs[reg->callno]) {
09781             iaxs[reg->callno]->reg = NULL;
09782             iax2_destroy(reg->callno);
09783          }
09784          ast_mutex_unlock(&iaxsl[reg->callno]);
09785       }
09786       if (reg->dnsmgr)
09787          ast_dnsmgr_release(reg->dnsmgr);
09788       free(reg);
09789    }
09790    AST_LIST_UNLOCK(&registrations);
09791 
09792    ao2_callback(peers, 0, peer_delme_cb, NULL);
09793 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1743 of file chan_iax2.c.

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

Referenced by reload_firmware().

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

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

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

06619 {
06620    unsigned short dpstatus = 0;
06621    struct iax_ie_data ied1;
06622    int mm;
06623 
06624    memset(&ied1, 0, sizeof(ied1));
06625    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06626    /* Must be started */
06627    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06628       dpstatus = IAX_DPSTATUS_EXISTS;
06629    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06630       dpstatus = IAX_DPSTATUS_CANEXIST;
06631    } else {
06632       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06633    }
06634    if (ast_ignore_pattern(context, callednum))
06635       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06636    if (mm)
06637       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06638    if (!skiplock)
06639       ast_mutex_lock(&iaxsl[callno]);
06640    if (iaxs[callno]) {
06641       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06642       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06643       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06644       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06645    }
06646    if (!skiplock)
06647       ast_mutex_unlock(&iaxsl[callno]);
06648 }

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

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

06651 {
06652    /* Look up for dpreq */
06653    struct dpreq_data *dpr = data;
06654    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06655    if (dpr->callerid)
06656       free(dpr->callerid);
06657    free(dpr);
06658    return NULL;
06659 }

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

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

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

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

Definition at line 6067 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

06068 {
06069 #ifdef SCHED_MULTITHREADED
06070    if (schedule_action(__expire_registry, data))
06071 #endif      
06072       __expire_registry(data);
06073    return 0;
06074 }

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

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

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

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

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

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

References __find_callno().

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3829 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

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

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8936 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08937 {
08938    struct iax2_context *conl;
08939    while(con) {
08940       conl = con;
08941       con = con->next;
08942       free(conl);
08943    }
08944 }

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

10597 {
10598    struct iax2_peer *peer;
10599    char *peername, *colname;
10600 
10601    peername = ast_strdupa(data);
10602 
10603    /* if our channel, return the IP address of the endpoint of current channel */
10604    if (!strcmp(peername,"CURRENTCHANNEL")) {
10605            unsigned short callno;
10606       if (chan->tech != &iax2_tech)
10607          return -1;
10608       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10609       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10610       return 0;
10611    }
10612 
10613    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10614       *colname++ = '\0';
10615    else if ((colname = strchr(peername, '|')))
10616       *colname++ = '\0';
10617    else
10618       colname = "ip";
10619 
10620    if (!(peer = find_peer(peername, 1)))
10621       return -1;
10622 
10623    if (!strcasecmp(colname, "ip")) {
10624       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10625    } else  if (!strcasecmp(colname, "status")) {
10626       peer_status(peer, buf, len); 
10627    } else  if (!strcasecmp(colname, "mailbox")) {
10628       ast_copy_string(buf, peer->mailbox, len);
10629    } else  if (!strcasecmp(colname, "context")) {
10630       ast_copy_string(buf, peer->context, len);
10631    } else  if (!strcasecmp(colname, "expire")) {
10632       snprintf(buf, len, "%d", peer->expire);
10633    } else  if (!strcasecmp(colname, "dynamic")) {
10634       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10635    } else  if (!strcasecmp(colname, "callerid_name")) {
10636       ast_copy_string(buf, peer->cid_name, len);
10637    } else  if (!strcasecmp(colname, "callerid_num")) {
10638       ast_copy_string(buf, peer->cid_num, len);
10639    } else  if (!strcasecmp(colname, "codecs")) {
10640       ast_getformatname_multiple(buf, len -1, peer->capability);
10641    } else  if (!strncasecmp(colname, "codec[", 6)) {
10642       char *codecnum, *ptr;
10643       int index = 0, codec = 0;
10644       
10645       codecnum = strchr(colname, '[');
10646       *codecnum = '\0';
10647       codecnum++;
10648       if ((ptr = strchr(codecnum, ']'))) {
10649          *ptr = '\0';
10650       }
10651       index = atoi(codecnum);
10652       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10653          ast_copy_string(buf, ast_getformatname(codec), len);
10654       }
10655    }
10656 
10657    peer_unref(peer);
10658 
10659    return 0;
10660 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9161 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09162 {
09163    int methods = 0;
09164    if (strstr(value, "rsa"))
09165       methods |= IAX_AUTH_RSA;
09166    if (strstr(value, "md5"))
09167       methods |= IAX_AUTH_MD5;
09168    if (strstr(value, "plaintext"))
09169       methods |= IAX_AUTH_PLAINTEXT;
09170    return methods;
09171 }

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

Definition at line 1024 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

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

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

Definition at line 2623 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

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

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

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

06817 {
06818    struct iax2_pkt_buf *pkt_buf;
06819 
06820    ast_mutex_lock(&thread->lock);
06821 
06822    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06823       ast_mutex_unlock(&thread->lock);
06824 
06825       thread->buf = pkt_buf->buf;
06826       thread->buf_len = pkt_buf->len;
06827       thread->buf_size = pkt_buf->len + 1;
06828       
06829       socket_process(thread);
06830 
06831       thread->buf = NULL;
06832       ast_free(pkt_buf);
06833 
06834       ast_mutex_lock(&thread->lock);
06835    }
06836 
06837    ast_mutex_unlock(&thread->lock);
06838 }

static int handle_error ( void   )  [static]

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

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

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

Acknowledgment received for OUR registration.

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

05889 {
05890    struct iax2_registry *reg;
05891    /* Start pessimistic */
05892    char peer[256] = "";
05893    char msgstatus[60];
05894    int refresh = 60;
05895    char ourip[256] = "<Unspecified>";
05896    struct sockaddr_in oldus;
05897    struct sockaddr_in us;
05898    int oldmsgs;
05899 
05900    memset(&us, 0, sizeof(us));
05901    if (ies->apparent_addr)
05902       bcopy(ies->apparent_addr, &us, sizeof(us));
05903    if (ies->username)
05904       ast_copy_string(peer, ies->username, sizeof(peer));
05905    if (ies->refresh)
05906       refresh = ies->refresh;
05907    if (ies->calling_number) {
05908       /* We don't do anything with it really, but maybe we should */
05909    }
05910    reg = iaxs[callno]->reg;
05911    if (!reg) {
05912       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05913       return -1;
05914    }
05915    memcpy(&oldus, &reg->us, sizeof(oldus));
05916    oldmsgs = reg->messages;
05917    if (inaddrcmp(&reg->addr, sin)) {
05918       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05919       return -1;
05920    }
05921    memcpy(&reg->us, &us, sizeof(reg->us));
05922    if (ies->msgcount >= 0)
05923       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05924    /* always refresh the registration at the interval requested by the server
05925       we are registering to
05926    */
05927    reg->refresh = refresh;
05928    AST_SCHED_DEL(sched, reg->expire);
05929    reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05930    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05931       if (option_verbose > 2) {
05932          if (reg->messages > 255)
05933             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
05934          else if (reg->messages > 1)
05935             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
05936          else if (reg->messages > 0)
05937             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
05938          else
05939             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
05940          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05941          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
05942       }
05943       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
05944    }
05945    reg->regstate = REG_STATE_REGISTERED;
05946    return 0;
05947 }

static int iax2_answer ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

10499 {
10500    int res = 0;
10501    struct iax2_dpcache *dp;
10502 #if 0
10503    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10504 #endif
10505    if ((priority != 1) && (priority != 2))
10506       return 0;
10507    ast_mutex_lock(&dpcache_lock);
10508    dp = find_cache(chan, data, context, exten, priority);
10509    if (dp) {
10510       if (dp->flags & CACHE_FLAG_CANEXIST)
10511          res= 1;
10512    }
10513    ast_mutex_unlock(&dpcache_lock);
10514    if (!dp) {
10515       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10516    }
10517    return res;
10518 }

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

Definition at line 3126 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

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

static void iax2_destroy ( int  callno  )  [static]

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

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

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

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

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

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

10686 {
10687    struct parsed_dial_string pds;
10688    char *tmp = ast_strdupa(data);
10689    struct iax2_peer *p;
10690    int res = AST_DEVICE_INVALID;
10691 
10692    memset(&pds, 0, sizeof(pds));
10693    parse_dial_string(tmp, &pds);
10694 
10695    if (ast_strlen_zero(pds.peer)) {
10696       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10697       return res;
10698    }
10699    
10700    if (option_debug > 2)
10701       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10702 
10703    /* SLD: FIXME: second call to find_peer during registration */
10704    if (!(p = find_peer(pds.peer, 1)))
10705       return res;
10706 
10707    res = AST_DEVICE_UNAVAILABLE;
10708    if (option_debug > 2) 
10709       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10710          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10711    
10712    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10713        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10714       /* Peer is registered, or have default IP address
10715          and a valid registration */
10716       if (p->historicms == 0 || p->historicms <= p->maxms)
10717          /* let the core figure out whether it is in use or not */
10718          res = AST_DEVICE_UNKNOWN;  
10719    }
10720 
10721    peer_unref(p);
10722 
10723    return res;
10724 }

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

Definition at line 2742 of file chan_iax2.c.

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

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

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

Definition at line 2747 of file chan_iax2.c.

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

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

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

Definition at line 4935 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 4953 of file chan_iax2.c.

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

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

static int iax2_do_register ( struct iax2_registry reg  )  [static]

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

08656 {
08657    struct iax_ie_data ied;
08658    if (option_debug && iaxdebug)
08659       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08660 
08661    if (reg->dnsmgr && 
08662        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08663       /* Maybe the IP has changed, force DNS refresh */
08664       ast_dnsmgr_refresh(reg->dnsmgr);
08665    }
08666    
08667    /*
08668     * if IP has Changed, free allocated call to create a new one with new IP
08669     * call has the pointer to IP and must be updated to the new one
08670     */
08671    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08672       ast_mutex_lock(&iaxsl[reg->callno]);
08673       iax2_destroy(reg->callno);
08674       ast_mutex_unlock(&iaxsl[reg->callno]);
08675       reg->callno = 0;
08676    }
08677    if (!reg->addr.sin_addr.s_addr) {
08678       if (option_debug && iaxdebug)
08679          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08680       /* Setup the next registration attempt */
08681       AST_SCHED_DEL(sched, reg->expire);
08682       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08683       return -1;
08684    }
08685 
08686    if (!reg->callno) {
08687       if (option_debug)
08688          ast_log(LOG_DEBUG, "Allocate call number\n");
08689       reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
08690       if (reg->callno < 1) {
08691          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08692          return -1;
08693       } else if (option_debug)
08694          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08695       iaxs[reg->callno]->reg = reg;
08696       ast_mutex_unlock(&iaxsl[reg->callno]);
08697    }
08698    /* Schedule the next registration attempt */
08699    AST_SCHED_DEL(sched, reg->expire);
08700    /* Setup the next registration a little early */
08701    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08702    /* Send the request */
08703    memset(&ied, 0, sizeof(ied));
08704    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08705    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08706    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08707    reg->regstate = REG_STATE_REGSENT;
08708    return 0;
08709 }

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

Definition at line 5736 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05737 {
05738 #ifdef SCHED_MULTITHREADED
05739    if (schedule_action(__iax2_do_register_s, data))
05740 #endif      
05741       __iax2_do_register_s(data);
05742    return 0;
05743 }

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

Definition at line 4944 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

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

06428 {
06429    struct iax_ie_data ied;
06430    /* Auto-hangup with 30 seconds of inactivity */
06431    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06432    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06433    memset(&ied, 0, sizeof(ied));
06434    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06435    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06436    dp->flags |= CACHE_FLAG_TRANSMITTED;
06437 }

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

10545 {
10546    char odata[256];
10547    char req[256];
10548    char *ncontext;
10549    struct iax2_dpcache *dp;
10550    struct ast_app *dial;
10551 #if 0
10552    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);
10553 #endif
10554    if (priority == 2) {
10555       /* Indicate status, can be overridden in dialplan */
10556       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10557       if (dialstatus) {
10558          dial = pbx_findapp(dialstatus);
10559          if (dial) 
10560             pbx_exec(chan, dial, "");
10561       }
10562       return -1;
10563    } else if (priority != 1)
10564       return -1;
10565    ast_mutex_lock(&dpcache_lock);
10566    dp = find_cache(chan, data, context, exten, priority);
10567    if (dp) {
10568       if (dp->flags & CACHE_FLAG_EXISTS) {
10569          ast_copy_string(odata, data, sizeof(odata));
10570          ncontext = strchr(odata, '/');
10571          if (ncontext) {
10572             *ncontext = '\0';
10573             ncontext++;
10574             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10575          } else {
10576             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10577          }
10578          if (option_verbose > 2)
10579             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10580       } else {
10581          ast_mutex_unlock(&dpcache_lock);
10582          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10583          return -1;
10584       }
10585    }
10586    ast_mutex_unlock(&dpcache_lock);
10587    dial = pbx_findapp("Dial");
10588    if (dial) {
10589       return pbx_exec(chan, dial, req);
10590    } else {
10591       ast_log(LOG_WARNING, "No dial application registered\n");
10592    }
10593    return -1;
10594 }

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

10476 {
10477    struct iax2_dpcache *dp;
10478    int res = 0;
10479 #if 0
10480    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10481 #endif
10482    if ((priority != 1) && (priority != 2))
10483       return 0;
10484    ast_mutex_lock(&dpcache_lock);
10485    dp = find_cache(chan, data, context, exten, priority);
10486    if (dp) {
10487       if (dp->flags & CACHE_FLAG_EXISTS)
10488          res= 1;
10489    }
10490    ast_mutex_unlock(&dpcache_lock);
10491    if (!dp) {
10492       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10493    }
10494    return res;
10495 }

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

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

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

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

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

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

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

static int iax2_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

Definition at line 4962 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 4980 of file chan_iax2.c.

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

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

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

Definition at line 4971 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 8853 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08854 {
08855    struct iax2_peer *peer = (struct iax2_peer *)data;
08856    peer->pokeexpire = -1;
08857 #ifdef SCHED_MULTITHREADED
08858    if (schedule_action(__iax2_poke_noanswer, data))
08859 #endif      
08860       __iax2_poke_noanswer(data);
08861    peer_unref(peer);
08862    return 0;
08863 }

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

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

08875 {
08876    int callno;
08877    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
08878       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
08879         immediately after clearing things out */
08880       peer->lastms = 0;
08881       peer->historicms = 0;
08882       peer->pokeexpire = -1;
08883       peer->callno = 0;
08884       return 0;
08885    }
08886 
08887    /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */
08888    if ((callno = peer->callno) > 0) {
08889       ast_log(LOG_NOTICE, "Still have a callno...\n");
08890       ast_mutex_lock(&iaxsl[callno]);
08891       iax2_destroy(callno);
08892       ast_mutex_unlock(&iaxsl[callno]);
08893    }
08894    if (heldcall)
08895       ast_mutex_unlock(&iaxsl[heldcall]);
08896    callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
08897    if (heldcall)
08898       ast_mutex_lock(&iaxsl[heldcall]);
08899    if (peer->callno < 1) {
08900       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08901       return -1;
08902    }
08903 
08904    /* Speed up retransmission times for this qualify call */
08905    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08906    iaxs[peer->callno]->peerpoke = peer;
08907    
08908    /* Remove any pending pokeexpire task */
08909    if (peer->pokeexpire > -1) {
08910       if (!ast_sched_del(sched, peer->pokeexpire)) {
08911          peer->pokeexpire = -1;
08912          peer_unref(peer);
08913       }
08914    }
08915 
08916    /* Queue up a new task to handle no reply */
08917    /* If the host is already unreachable then use the unreachable interval instead */
08918    if (peer->lastms < 0) {
08919       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
08920    } else
08921       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
08922 
08923    if (peer->pokeexpire == -1)
08924       peer_unref(peer);
08925 
08926    /* And send the poke */
08927    ast_mutex_lock(&iaxsl[callno]);
08928    if (iaxs[callno]) {
08929       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08930    }
08931    ast_mutex_unlock(&iaxsl[callno]);
08932 
08933    return 0;
08934 }

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

Definition at line 8865 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08866 {
08867    struct iax2_peer *peer = obj;
08868 
08869    iax2_poke_peer(peer, 0);
08870 
08871    return 0;
08872 }

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

Definition at line 6467 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06468 {
06469    struct iax2_peer *peer = (struct iax2_peer *)data;
06470    peer->pokeexpire = -1;
06471 #ifdef SCHED_MULTITHREADED
06472    if (schedule_action(__iax2_poke_peer_s, data))
06473 #endif      
06474       __iax2_poke_peer_s(data);
06475    return 0;
06476 }

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

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

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

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

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8521 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08522 {
08523    struct iax2_thread *thread = data;
08524    ast_mutex_destroy(&thread->lock);
08525    ast_cond_destroy(&thread->cond);
08526    free(thread);
08527    ast_atomic_dec_and_test(&iaxactivethreadcount);
08528 }

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

Definition at line 8808 of file chan_iax2.c.

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

08809 {
08810    int force = 0;
08811    int res;
08812    if (argc < 4)
08813       return RESULT_SHOWUSAGE;
08814    if ((argc > 4)) {
08815       if (!strcasecmp(argv[4], "forced"))
08816          force = 1;
08817       else
08818          return RESULT_SHOWUSAGE;
08819    }
08820    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08821    if (res < 0)
08822       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08823    else if (res < 1)
08824       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08825    else
08826       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08827    return RESULT_SUCCESS;
08828 }

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

Definition at line 8711 of file chan_iax2.c.

References iax_prov_complete_template().

08712 {
08713    if (pos != 3)
08714       return NULL;
08715    return iax_prov_complete_template(line, word, pos, state);
08716 }

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

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

08719 {
08720    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08721       is found for template */
08722    struct iax_ie_data provdata;
08723    struct iax_ie_data ied;
08724    unsigned int sig;
08725    struct sockaddr_in sin;
08726    int callno;
08727    struct create_addr_info cai;
08728 
08729    memset(&cai, 0, sizeof(cai));
08730 
08731    if (option_debug)
08732       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08733 
08734    if (iax_provision_build(&provdata, &sig, template, force)) {
08735       if (option_debug)
08736          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08737       return 0;
08738    }
08739 
08740    if (end) {
08741       memcpy(&sin, end, sizeof(sin));
08742       cai.sockfd = sockfd;
08743    } else if (create_addr(dest, NULL, &sin, &cai))
08744       return -1;
08745 
08746    /* Build the rest of the message */
08747    memset(&ied, 0, sizeof(ied));
08748    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08749 
08750    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08751    if (!callno)
08752       return -1;
08753 
08754    if (iaxs[callno]) {
08755       /* Schedule autodestruct in case they don't ever give us anything back */
08756       AST_SCHED_DEL(sched, iaxs[callno]->autoid);
08757       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08758       ast_set_flag(iaxs[callno], IAX_PROVISION);
08759       /* Got a call number now, so go ahead and send the provisioning information */
08760       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08761    }
08762    ast_mutex_unlock(&iaxsl[callno]);
08763 
08764    return 1;
08765 }

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

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

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

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

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

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

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

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

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

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

Definition at line 3431 of file chan_iax2.c.

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

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

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

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

05950 {
05951    struct iax2_registry *reg;
05952    char copy[256];
05953    char *username, *hostname, *secret;
05954    char *porta;
05955    char *stringp=NULL;
05956    
05957    if (!value)
05958       return -1;
05959    ast_copy_string(copy, value, sizeof(copy));
05960    stringp=copy;
05961    username = strsep(&stringp, "@");
05962    hostname = strsep(&stringp, "@");
05963    if (!hostname) {
05964       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
05965       return -1;
05966    }
05967    stringp=username;
05968    username = strsep(&stringp, ":");
05969    secret = strsep(&stringp, ":");
05970    stringp=hostname;
05971    hostname = strsep(&stringp, ":");
05972    porta = strsep(&stringp, ":");
05973    
05974    if (porta && !atoi(porta)) {
05975       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
05976       return -1;
05977    }
05978    if (!(reg = ast_calloc(1, sizeof(*reg))))
05979       return -1;
05980    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
05981       free(reg);
05982       return -1;
05983    }
05984    ast_copy_string(reg->username, username, sizeof(reg->username));
05985    if (secret)
05986       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
05987    reg->expire = -1;
05988    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
05989    reg->addr.sin_family = AF_INET;
05990    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
05991    AST_LIST_LOCK(&registrations);
05992    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
05993    AST_LIST_UNLOCK(&registrations);
05994    
05995    return 0;
05996 }

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

Definition at line 10244 of file chan_iax2.c.

References reload_config().

10245 {
10246    return reload_config();
10247 }

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

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

08947 {
08948    int callno;
08949    int res;
08950    int fmt, native;
08951    struct sockaddr_in sin;
08952    struct ast_channel *c;
08953    struct parsed_dial_string pds;
08954    struct create_addr_info cai;
08955    char *tmpstr;
08956 
08957    memset(&pds, 0, sizeof(pds));
08958    tmpstr = ast_strdupa(data);
08959    parse_dial_string(tmpstr, &pds);
08960 
08961    if (ast_strlen_zero(pds.peer)) {
08962       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
08963       return NULL;
08964    }
08965           
08966    memset(&cai, 0, sizeof(cai));
08967    cai.capability = iax2_capability;
08968 
08969    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08970    
08971    /* Populate our address from the given */
08972    if (create_addr(pds.peer, NULL, &sin, &cai)) {
08973       *cause = AST_CAUSE_UNREGISTERED;
08974       return NULL;
08975    }
08976 
08977    if (pds.port)
08978       sin.sin_port = htons(atoi(pds.port));
08979 
08980    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08981    if (callno < 1) {
08982       ast_log(LOG_WARNING, "Unable to create call\n");
08983       *cause = AST_CAUSE_CONGESTION;
08984       return NULL;
08985    }
08986 
08987    /* If this is a trunk, update it now */
08988    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08989    if (ast_test_flag(&cai, IAX_TRUNK)) {
08990       int new_callno;
08991       if ((new_callno = make_trunk(callno, 1)) != -1)
08992          callno = new_callno;
08993    }
08994    iaxs[callno]->maxtime = cai.maxtime;
08995    if (cai.found)
08996       ast_string_field_set(iaxs[callno], host, pds.peer);
08997 
08998    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08999 
09000    ast_mutex_unlock(&iaxsl[callno]);
09001 
09002    if (c) {
09003       /* Choose a format we can live with */
09004       if (c->nativeformats & format) 
09005          c->nativeformats &= format;
09006       else {
09007          native = c->nativeformats;
09008          fmt = format;
09009          res = ast_translator_best_choice(&fmt, &native);
09010          if (res < 0) {
09011             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
09012                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
09013             ast_hangup(c);
09014             return NULL;
09015          }
09016          c->nativeformats = native;
09017       }
09018       c->readformat = ast_best_codec(c->nativeformats);
09019       c->writeformat = c->readformat;
09020    }
09021 
09022    return c;
09023 }

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

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

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

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

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

Definition at line 2764 of file chan_iax2.c.

References AST_FRAME_HTML, 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_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02767 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4923 of file chan_iax2.c.

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

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

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

Show one peer in detail.

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

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

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

Definition at line 4700 of file chan_iax2.c.

References __iax2_show_peers().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2264 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

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

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

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

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

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

Definition at line 6522 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06523 {
06524    /* Drop when trunk is about 5 seconds idle */
06525    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06526       return 1;
06527    return 0;
06528 }

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

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

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

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6439 of file chan_iax2.c.

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

Referenced by socket_process().

06440 {
06441    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06442 }

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

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

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

static int iax_check_version ( char *  dev  )  [static]

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

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

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

Definition at line 764 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 770 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

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

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

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

06711 {
06712    struct iax_dual *d;
06713    struct ast_channel *chan1m, *chan2m;
06714    pthread_t th;
06715    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06716    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06717    if (chan2m && chan1m) {
06718       /* Make formats okay */
06719       chan1m->readformat = chan1->readformat;
06720       chan1m->writeformat = chan1->writeformat;
06721       ast_channel_masquerade(chan1m, chan1);
06722       /* Setup the extensions and such */
06723       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06724       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06725       chan1m->priority = chan1->priority;
06726       
06727       /* We make a clone of the peer channel too, so we can play
06728          back the announcement */
06729       /* Make formats okay */
06730       chan2m->readformat = chan2->readformat;
06731       chan2m->writeformat = chan2->writeformat;
06732       ast_channel_masquerade(chan2m, chan2);
06733       /* Setup the extensions and such */
06734       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06735       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06736       chan2m->priority = chan2->priority;
06737       if (ast_do_masquerade(chan2m)) {
06738          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06739          ast_hangup(chan2m);
06740          return -1;
06741       }
06742    } else {
06743       if (chan1m)
06744          ast_hangup(chan1m);
06745       if (chan2m)
06746          ast_hangup(chan2m);
06747       return -1;
06748    }
06749    if ((d = ast_calloc(1, sizeof(*d)))) {
06750       pthread_attr_t attr;
06751 
06752       pthread_attr_init(&attr);
06753       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06754 
06755       d->chan1 = chan1m;
06756       d->chan2 = chan2m;
06757       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06758          pthread_attr_destroy(&attr);
06759          return 0;
06760       }
06761       pthread_attr_destroy(&attr);
06762       free(d);
06763    }
06764    return -1;
06765 }

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

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

06691 {
06692    struct ast_channel *chan1, *chan2;
06693    struct iax_dual *d;
06694    struct ast_frame *f;
06695    int ext;
06696    int res;
06697    d = stuff;
06698    chan1 = d->chan1;
06699    chan2 = d->chan2;
06700    free(d);
06701    f = ast_read(chan1);
06702    if (f)
06703       ast_frfree(f);
06704    res = ast_park_call(chan1, chan2, 0, &ext);
06705    ast_hangup(chan2);
06706    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06707    return NULL;
06708 }

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

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

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

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

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

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

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

Definition at line 799 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 775 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 787 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

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

11081 {
11082    char *config = "iax.conf";
11083    int res = 0;
11084    int x;
11085    struct iax2_registry *reg = NULL;
11086 
11087    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
11088    if (!peers)
11089       return AST_MODULE_LOAD_FAILURE;
11090    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
11091    if (!users) {
11092       ao2_ref(peers, -1);
11093       return AST_MODULE_LOAD_FAILURE;
11094    }
11095    iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
11096    if (!iax_peercallno_pvts) {
11097       ao2_ref(peers, -1);
11098       ao2_ref(users, -1);
11099       return AST_MODULE_LOAD_FAILURE;
11100    }
11101 
11102    ast_custom_function_register(&iaxpeer_function);
11103 
11104    iax_set_output(iax_debug_output);
11105    iax_set_error(iax_error_output);
11106    jb_setoutput(jb_error_output, jb_warning_output, NULL);
11107    
11108 #ifdef HAVE_ZAPTEL
11109 #ifdef ZT_TIMERACK
11110    timingfd = open("/dev/zap/timer", O_RDWR);
11111    if (timingfd < 0)
11112 #endif
11113       timingfd = open("/dev/zap/pseudo", O_RDWR);
11114    if (timingfd < 0) 
11115       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
11116 #endif      
11117 
11118    memset(iaxs, 0, sizeof(iaxs));
11119 
11120    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11121       ast_mutex_init(&iaxsl[x]);
11122    }
11123    
11124    ast_cond_init(&sched_cond, NULL);
11125 
11126    io = io_context_create();
11127    sched = sched_context_create();
11128    
11129    if (!io || !sched) {
11130       ast_log(LOG_ERROR, "Out of memory\n");
11131       return -1;
11132    }
11133 
11134    netsock = ast_netsock_list_alloc();
11135    if (!netsock) {
11136       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
11137       return -1;
11138    }
11139    ast_netsock_init(netsock);
11140 
11141    outsock = ast_netsock_list_alloc();
11142    if (!outsock) {
11143       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
11144       return -1;
11145    }
11146    ast_netsock_init(outsock);
11147 
11148    ast_mutex_init(&waresl.lock);
11149 
11150    AST_LIST_HEAD_INIT(&iaxq.queue);
11151    
11152    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11153 
11154    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
11155    
11156    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
11157    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
11158 
11159    if(set_config(config, 0) == -1)
11160       return AST_MODULE_LOAD_DECLINE;
11161 
11162    if (ast_channel_register(&iax2_tech)) {
11163       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
11164       __unload_module();
11165       return -1;
11166    }
11167 
11168    if (ast_register_switch(&iax2_switch)) 
11169       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
11170 
11171    res = start_network_thread();
11172    if (!res) {
11173       if (option_verbose > 1) 
11174          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
11175    } else {
11176       ast_log(LOG_ERROR, "Unable to start network thread\n");
11177       ast_netsock_release(netsock);
11178       ast_netsock_release(outsock);
11179    }
11180 
11181    AST_LIST_LOCK(&registrations);
11182    AST_LIST_TRAVERSE(&registrations, reg, entry)
11183       iax2_do_register(reg);
11184    AST_LIST_UNLOCK(&registrations); 
11185 
11186    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
11187    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
11188 
11189    reload_firmware(0);
11190    iax_provision_reload();
11191    return res;
11192 }

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

Definition at line 3465 of file chan_iax2.c.

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

Referenced by iax2_bridge().

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

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

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

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

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

Definition at line 4704 of file chan_iax2.c.

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

Referenced by load_module().

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

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

Definition at line 4737 of file chan_iax2.c.

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

Referenced by load_module().

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

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

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

Definition at line 4111 of file chan_iax2.c.

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

Referenced by decode_frame().

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

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

Definition at line 4135 of file chan_iax2.c.

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

Referenced by encrypt_frame().

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

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

Definition at line 5315 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05316 {
05317    /* Select exactly one common encryption if there are any */
05318    p->encmethods &= enc;
05319    if (p->encmethods) {
05320       if (p->encmethods & IAX_ENCRYPT_AES128)
05321          p->encmethods = IAX_ENCRYPT_AES128;
05322       else
05323          p->encmethods = 0;
05324    }
05325 }

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

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

09054 {
09055    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
09056       from the network, and queue them for delivery to the channels */
09057    int res, count, wakeup;
09058    struct iax_frame *f;
09059 
09060    if (timingfd > -1)
09061       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
09062    
09063    for(;;) {
09064       pthread_testcancel();
09065 
09066       /* Go through the queue, sending messages which have not yet been
09067          sent, and scheduling retransmissions if appropriate */
09068       AST_LIST_LOCK(&iaxq.queue);
09069       count = 0;
09070       wakeup = -1;
09071       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
09072          if (f->sentyet)
09073             continue;
09074          
09075          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
09076          if (ast_mutex_trylock(&iaxsl[f->callno])) {
09077             wakeup = 1;
09078             continue;
09079          }
09080 
09081          f->sentyet++;
09082 
09083          if (iaxs[f->callno]) {
09084             send_packet(f);
09085             count++;
09086          } 
09087 
09088          ast_mutex_unlock(&iaxsl[f->callno]);
09089 
09090          if (f->retries < 0) {
09091             /* This is not supposed to be retransmitted */
09092             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
09093             iaxq.count--;
09094             /* Free the iax frame */
09095             iax_frame_free(f);
09096          } else {
09097             /* We need reliable delivery.  Schedule a retransmission */
09098             f->retries++;
09099             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
09100          }
09101       }
09102       AST_LIST_TRAVERSE_SAFE_END
09103       AST_LIST_UNLOCK(&iaxq.queue);
09104 
09105       pthread_testcancel();
09106 
09107       if (option_debug && count >= 20)
09108          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
09109 
09110       /* Now do the IO, and run scheduled tasks */
09111       res = ast_io_wait(io, wakeup);
09112       if (res >= 0) {
09113          if (option_debug && res >= 20)
09114             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
09115       }
09116    }
09117    return NULL;
09118 }

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

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

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

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

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

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

Referenced by load_module().

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

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

Definition at line 9751 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09752 {
09753    struct iax2_peer *peer = obj;
09754 
09755    ast_set_flag(peer, IAX_DELME);
09756 
09757    return 0;
09758 }

static void peer_destructor ( void *  obj  )  [static]

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

09277 {
09278    struct iax2_peer *peer = obj;
09279 
09280    ast_free_ha(peer->ha);
09281 
09282    if (peer->callno > 0) {
09283       ast_mutex_lock(&iaxsl[peer->callno]);
09284       iax2_destroy(peer->callno);
09285       ast_mutex_unlock(&iaxsl[peer->callno]);
09286    }
09287 
09288    register_peer_exten(peer, 0);
09289 
09290    if (peer->dnsmgr)
09291       ast_dnsmgr_release(peer->dnsmgr);
09292 
09293    ast_string_field_free_memory(peer);
09294 }

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

References ast_str_hash().

Referenced by load_module().

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

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

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

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

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

Definition at line 11051 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

11052 {
11053    struct iax2_peer *peer = obj;
11054 
11055    if (peer->sockfd < 0)
11056       peer->sockfd = defaultsockfd;
11057 
11058    return 0;
11059 }

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

09204 {
09205    struct sockaddr_in sin;
09206    int nonlocal = 1;
09207    int port = IAX_DEFAULT_PORTNO;
09208    int sockfd = defaultsockfd;
09209    char *tmp;
09210    char *addr;
09211    char *portstr;
09212 
09213    if (!(tmp = ast_strdupa(srcaddr)))
09214       return -1;
09215 
09216    addr = strsep(&tmp, ":");
09217    portstr = tmp;
09218 
09219    if (portstr) {
09220       port = atoi(portstr);
09221       if (port < 1)
09222          port = IAX_DEFAULT_PORTNO;
09223    }
09224    
09225    if (!ast_get_ip(&sin, addr)) {
09226       struct ast_netsock *sock;
09227       int res;
09228 
09229       sin.sin_port = 0;
09230       sin.sin_family = AF_INET;
09231       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
09232       if (res == 0) {
09233          /* ip address valid. */
09234          sin.sin_port = htons(port);
09235          if (!(sock = ast_netsock_find(netsock, &sin)))
09236             sock = ast_netsock_find(outsock, &sin);
09237          if (sock) {
09238             sockfd = ast_netsock_sockfd(sock);
09239             nonlocal = 0;
09240          } else {
09241             unsigned int orig_saddr = sin.sin_addr.s_addr;
09242             /* INADDR_ANY matches anyway! */
09243             sin.sin_addr.s_addr = INADDR_ANY;
09244             if (ast_netsock_find(netsock, &sin)) {
09245                sin.sin_addr.s_addr = orig_saddr;
09246                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09247                if (sock) {
09248                   sockfd = ast_netsock_sockfd(sock);
09249                   ast_netsock_unref(sock);
09250                   nonlocal = 0;
09251                } else {
09252                   nonlocal = 2;
09253                }
09254             }
09255          }
09256       }
09257    }
09258       
09259    peer->sockfd = sockfd;
09260 
09261    if (nonlocal == 1) {
09262       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09263          srcaddr, peer->name);
09264       return -1;
09265         } else if (nonlocal == 2) {
09266       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09267          srcaddr, peer->name);
09268          return -1;
09269    } else {
09270       if (option_debug)
09271          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09272       return 0;
09273    }
09274 }

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

peer_status: Report Peer status in character string

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

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

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

static void poke_all_peers ( void   )  [static]

Definition at line 10212 of file chan_iax2.c.

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

Referenced by reload_config().

10213 {
10214    struct ao2_iterator i;
10215    struct iax2_peer *peer;
10216 
10217    i = ao2_iterator_init(peers, 0);
10218    while ((peer = ao2_iterator_next(&i))) {
10219       iax2_poke_peer(peer, 0);
10220       peer_unref(peer);
10221    }
10222 }

static void prune_peers ( void   )  [static]

Definition at line 9809 of file chan_iax2.c.

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

09810 {
09811    struct iax2_peer *peer;
09812    struct ao2_iterator i;
09813 
09814    i = ao2_iterator_init(peers, 0);
09815    while ((peer = ao2_iterator_next(&i))) {
09816       if (ast_test_flag(peer, IAX_DELME))
09817          unlink_peer(peer);
09818       peer_unref(peer);
09819    }
09820 }

static void prune_users ( void   )  [static]

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

09796 {
09797    struct iax2_user *user;
09798    struct ao2_iterator i;
09799 
09800    i = ao2_iterator_init(users, 0);
09801    while ((user = ao2_iterator_next(&i))) {
09802       if (ast_test_flag(user, IAX_DELME))
09803          ao2_unlink(users, user);
09804       user_unref(user);
09805    }
09806 }

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

Definition at line 11068 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

11069 {
11070    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
11071 
11072    /* The frames_received field is used to hold whether we're matching
11073     * against a full frame or not ... */
11074 
11075    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
11076       pvt2->frames_received) ? CMP_MATCH : 0;
11077 }

static void pvt_destructor ( void *  obj  )  [static]

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

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

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

Definition at line 11061 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

11062 {
11063    const struct chan_iax2_pvt *pvt = obj;
11064 
11065    return pvt->peercallno;
11066 }

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

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

05298 {
05299    struct ast_iax2_full_hdr fh;
05300    fh.scallno = htons(src | IAX_FLAG_FULL);
05301    fh.dcallno = htons(dst);
05302    fh.ts = 0;
05303    fh.oseqno = 0;
05304    fh.iseqno = 0;
05305    fh.type = AST_FRAME_IAX;
05306    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05307    if (iaxdebug)
05308        iax_showframe(NULL, &fh, 0, sin, 0);
05309    if (option_debug)
05310       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05311          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05312    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05313 }

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

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

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

Definition at line 2978 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

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

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

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

static void reg_source_db ( struct iax2_peer p  )  [static]

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

06079 {
06080    char data[80];
06081    struct in_addr in;
06082    char *c, *d;
06083    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
06084       c = strchr(data, ':');
06085       if (c) {
06086          *c = '\0';
06087          c++;
06088          if (inet_aton(data, &in)) {
06089             d = strchr(c, ':');
06090             if (d) {
06091                *d = '\0';
06092                d++;
06093                if (option_verbose > 2)
06094                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
06095                   ast_inet_ntoa(in), atoi(c), atoi(d));
06096                iax2_poke_peer(p, 0);
06097                p->expiry = atoi(d);
06098                memset(&p->addr, 0, sizeof(p->addr));
06099                p->addr.sin_family = AF_INET;
06100                p->addr.sin_addr = in;
06101                p->addr.sin_port = htons(atoi(c));
06102                if (p->expire > -1) {
06103                   if (!ast_sched_del(sched, p->expire)) {
06104                      p->expire = -1;
06105                      peer_unref(p);
06106                   }
06107                }
06108                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06109                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06110                if (p->expire == -1)
06111                   peer_unref(p);
06112                if (iax2_regfunk)
06113                   iax2_regfunk(p->name, 1);
06114                register_peer_exten(p, 1);
06115             }              
06116                
06117          }
06118       }
06119    }
06120 }

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

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

05999 {
06000    char multi[256];
06001    char *stringp, *ext;
06002    if (!ast_strlen_zero(regcontext)) {
06003       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
06004       stringp = multi;
06005       while((ext = strsep(&stringp, "&"))) {
06006          if (onoff) {
06007             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
06008                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
06009                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
06010          } else
06011             ast_context_remove_extension(regcontext, ext, 1, NULL);
06012       }
06013    }
06014 }

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

Verify inbound registration.

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

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

static int registry_authrequest ( int  callno  )  [static]

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

06258 {
06259    struct iax_ie_data ied;
06260    struct iax2_peer *p;
06261    char challenge[10];
06262    const char *peer_name;
06263    int res = -1;
06264 
06265    peer_name = ast_strdupa(iaxs[callno]->peer);
06266 
06267    /* SLD: third call to find_peer in registration */
06268    ast_mutex_unlock(&iaxsl[callno]);
06269    p = find_peer(peer_name, 1);
06270    ast_mutex_lock(&iaxsl[callno]);
06271    if (!iaxs[callno])
06272       goto return_unref;
06273    if (!p) {
06274       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06275       goto return_unref;
06276    }
06277    
06278    memset(&ied, 0, sizeof(ied));
06279    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06280    if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06281       /* Build the challenge */
06282       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06283       ast_string_field_set(iaxs[callno], challenge, challenge);
06284       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06285    }
06286    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06287 
06288    res = 0;
06289 
06290 return_unref:
06291    peer_unref(p);
06292 
06293    return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
06294 }

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

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

06297 {
06298    struct iax2_registry *reg;
06299    /* Start pessimistic */
06300    struct iax_ie_data ied;
06301    char peer[256] = "";
06302    char challenge[256] = "";
06303    int res;
06304    int authmethods = 0;
06305    if (ies->authmethods)
06306       authmethods = ies->authmethods;
06307    if (ies->username)
06308       ast_copy_string(peer, ies->username, sizeof(peer));
06309    if (ies->challenge)
06310       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06311    memset(&ied, 0, sizeof(ied));
06312    reg = iaxs[callno]->reg;
06313    if (reg) {
06314          if (inaddrcmp(&reg->addr, sin)) {
06315             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06316             return -1;
06317          }
06318          if (ast_strlen_zero(reg->secret)) {
06319             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06320             reg->regstate = REG_STATE_NOAUTH;
06321             return -1;
06322          }
06323          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06324          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06325          if (reg->secret[0] == '[') {
06326             char tmpkey[256];
06327             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06328             tmpkey[strlen(tmpkey) - 1] = '\0';
06329             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
06330          } else
06331             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
06332          if (!res) {
06333             reg->regstate = REG_STATE_AUTHSENT;
06334             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06335          } else
06336             return -1;
06337          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06338    } else   
06339       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06340    return -1;
06341 }

static char* regstate2str ( int  regstate  )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 10249 of file chan_iax2.c.

References reload_config().

10250 {
10251    return reload_config();
10252 }

static int reload_config ( void   )  [static]

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

10224 {
10225    char *config = "iax.conf";
10226    struct iax2_registry *reg;
10227 
10228    if (set_config(config, 1) > 0) {
10229       prune_peers();
10230       prune_users();
10231       AST_LIST_LOCK(&registrations);
10232       AST_LIST_TRAVERSE(&registrations, reg, entry)
10233          iax2_do_register(reg);
10234       AST_LIST_UNLOCK(&registrations);
10235       /* Qualify hosts, too */
10236       poke_all_peers();
10237    }
10238    reload_firmware(0);
10239    iax_provision_reload();
10240 
10241    return 0;
10242 }

static void reload_firmware ( int  unload  )  [static]

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

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

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

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

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

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

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

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

09026 {
09027    int count;
09028    int res;
09029    struct timeval tv;
09030    struct timespec ts;
09031 
09032    for (;;) {
09033       res = ast_sched_wait(sched);
09034       if ((res > 1000) || (res < 0))
09035          res = 1000;
09036       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
09037       ts.tv_sec = tv.tv_sec;
09038       ts.tv_nsec = tv.tv_usec * 1000;
09039 
09040       pthread_testcancel();
09041       ast_mutex_lock(&sched_lock);
09042       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
09043       ast_mutex_unlock(&sched_lock);
09044       pthread_testcancel();
09045 
09046       count = ast_sched_runq(sched);
09047       if (option_debug && count >= 20)
09048          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
09049    }
09050    return NULL;
09051 }

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

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

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

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

Referenced by socket_process().

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

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

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

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

References __send_command().

Referenced by iax2_vnak(), and socket_process().

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

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

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

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

References __send_command().

Referenced by socket_process(), and try_transfer().

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

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

Definition at line 1055 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

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

static int send_packet ( struct iax_frame f  )  [static]

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

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

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

Definition at line 1015 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

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

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

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

06479 {
06480    int res = 0;
06481    struct iax_frame *fr;
06482    struct ast_iax2_meta_hdr *meta;
06483    struct ast_iax2_meta_trunk_hdr *mth;
06484    int calls = 0;
06485    
06486    /* Point to frame */
06487    fr = (struct iax_frame *)tpeer->trunkdata;
06488    /* Point to meta data */
06489    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06490    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06491    if (tpeer->trunkdatalen) {
06492       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06493       meta->zeros = 0;
06494       meta->metacmd = IAX_META_TRUNK;
06495       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06496          meta->cmddata = IAX_META_TRUNK_MINI;
06497       else
06498          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06499       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06500       /* And the rest of the ast_iax2 header */
06501       fr->direction = DIRECTION_OUTGRESS;
06502       fr->retrans = -1;
06503       fr->transfer = 0;
06504       /* Any appropriate call will do */
06505       fr->data = fr->afdata;
06506       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06507       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06508       calls = tpeer->calls;
06509 #if 0
06510       if (option_debug)
06511          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));
06512 #endif      
06513       /* Reset transmit trunk side data */
06514       tpeer->trunkdatalen = 0;
06515       tpeer->calls = 0;
06516    }
06517    if (res < 0)
06518       return res;
06519    return calls;
06520 }

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

Load configuration.

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

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

static void set_config_destroy ( void   )  [static]

Definition at line 9837 of file chan_iax2.c.

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

Referenced by set_config().

09838 {
09839    strcpy(accountcode, "");
09840    strcpy(language, "");
09841    strcpy(mohinterpret, "default");
09842    strcpy(mohsuggest, "");
09843    amaflags = 0;
09844    delayreject = 0;
09845    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09846    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09847    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09848    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09849    delete_users();
09850 }

static void set_timing ( void   )  [static]

Definition at line 9822 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09823 {
09824 #ifdef HAVE_ZAPTEL
09825    int bs = trunkfreq * 8;
09826    if (timingfd > -1) {
09827       if (
09828 #ifdef ZT_TIMERACK
09829          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09830 #endif         
09831          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09832          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09833    }
09834 #endif
09835 }

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

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

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

static int socket_process ( struct iax2_thread thread  )  [static]

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

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

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

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

06875 {
06876    struct iax2_thread *thread;
06877    socklen_t len;
06878    time_t t;
06879    static time_t last_errtime = 0;
06880    struct ast_iax2_full_hdr *fh;
06881 
06882    if (!(thread = find_idle_thread())) {
06883       time(&t);
06884       if (t != last_errtime && option_debug)
06885          ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n");
06886       last_errtime = t;
06887       usleep(1);
06888       return 1;
06889    }
06890 
06891    len = sizeof(thread->iosin);
06892    thread->iofd = fd;
06893    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06894    thread->buf_size = sizeof(thread->readbuf);
06895    thread->buf = thread->readbuf;
06896    if (thread->buf_len < 0) {
06897       if (errno != ECONNREFUSED && errno != EAGAIN)
06898          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06899       handle_error();
06900       thread->iostate = IAX_IOSTATE_IDLE;
06901       signal_condition(&thread->lock, &thread->cond);
06902       return 1;
06903    }
06904    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06905       thread->iostate = IAX_IOSTATE_IDLE;
06906       signal_condition(&thread->lock, &thread->cond);
06907       return 1;
06908    }
06909    
06910    /* Determine if this frame is a full frame; if so, and any thread is currently
06911       processing a full frame for the same callno from this peer, then drop this
06912       frame (and the peer will retransmit it) */
06913    fh = (struct ast_iax2_full_hdr *) thread->buf;
06914    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06915       struct iax2_thread *cur = NULL;
06916       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06917       
06918       AST_LIST_LOCK(&active_list);
06919       AST_LIST_TRAVERSE(&active_list, cur, list) {
06920          if ((cur->ffinfo.callno == callno) &&
06921              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06922             break;
06923       }
06924       if (cur) {
06925          /* we found another thread processing a full frame for this call,
06926             so queue it up for processing later. */
06927          defer_full_frame(thread, cur);
06928          AST_LIST_UNLOCK(&active_list);
06929          thread->iostate = IAX_IOSTATE_IDLE;
06930          signal_condition(&thread->lock, &thread->cond);
06931          return 1;
06932       } else {
06933          /* this thread is going to process this frame, so mark it */
06934          thread->ffinfo.callno = callno;
06935          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
06936          thread->ffinfo.type = fh->type;
06937          thread->ffinfo.csub = fh->csub;
06938       }
06939       AST_LIST_UNLOCK(&active_list);
06940    }
06941    
06942    /* Mark as ready and send on its way */
06943    thread->iostate = IAX_IOSTATE_READY;
06944 #ifdef DEBUG_SCHED_MULTITHREAD
06945    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06946 #endif
06947    signal_condition(&thread->lock, &thread->cond);
06948 
06949    return 1;
06950 }

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

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

06662 {
06663    pthread_t newthread;
06664    struct dpreq_data *dpr;
06665    pthread_attr_t attr;
06666    
06667    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06668       return;
06669 
06670    pthread_attr_init(&attr);
06671    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06672 
06673    dpr->callno = callno;
06674    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06675    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06676    if (callerid)
06677       dpr->callerid = ast_strdup(callerid);
06678    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06679       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06680    }
06681 
06682    pthread_attr_destroy(&attr);
06683 }

static int start_network_thread ( void   )  [static]

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

09121 {
09122    pthread_attr_t attr;
09123    int threadcount = 0;
09124    int x;
09125    for (x = 0; x < iaxthreadcount; x++) {
09126       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
09127       if (thread) {
09128          thread->type = IAX_TYPE_POOL;
09129          thread->threadnum = ++threadcount;
09130          ast_mutex_init(&thread->lock);
09131          ast_cond_init(&thread->cond, NULL);
09132          pthread_attr_init(&attr);
09133          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
09134          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
09135             ast_log(LOG_WARNING, "Failed to create new thread!\n");
09136             free(thread);
09137             thread = NULL;
09138          }
09139          AST_LIST_LOCK(&idle_list);
09140          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
09141          AST_LIST_UNLOCK(&idle_list);
09142       }
09143    }
09144    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
09145    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
09146    if (option_verbose > 1)
09147       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
09148    return 0;
09149 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6343 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06344 {
06345    iax2_destroy_helper(iaxs[callno]);
06346 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

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

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

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

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

06531 {
06532    char buf[1024];
06533    int res;
06534    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06535    int processed = 0;
06536    int totalcalls = 0;
06537 #ifdef ZT_TIMERACK
06538    int x = 1;
06539 #endif
06540    struct timeval now;
06541    if (iaxtrunkdebug)
06542       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06543    gettimeofday(&now, NULL);
06544    if (events & AST_IO_PRI) {
06545 #ifdef ZT_TIMERACK
06546       /* Great, this is a timing interface, just call the ioctl */
06547       if (ioctl(fd, ZT_TIMERACK, &x)) {
06548          ast_log(LOG_WARNING, "Unable to acknowledge zap timer. IAX trunking will fail!\n");
06549          usleep(1);
06550          return -1;
06551       }
06552 #endif      
06553    } else {
06554       /* Read and ignore from the pseudo channel for timing */
06555       res = read(fd, buf, sizeof(buf));
06556       if (res < 1) {
06557          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06558          return 1;
06559       }
06560    }
06561    /* For each peer that supports trunking... */
06562    ast_mutex_lock(&tpeerlock);
06563    tpeer = tpeers;
06564    while(tpeer) {
06565       processed++;
06566       res = 0;
06567       ast_mutex_lock(&tpeer->lock);
06568       /* We can drop a single tpeer per pass.  That makes all this logic
06569          substantially easier */
06570       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06571          /* Take it out of the list, but don't free it yet, because it
06572             could be in use */
06573          if (prev)
06574             prev->next = tpeer->next;
06575          else
06576             tpeers = tpeer->next;
06577          drop = tpeer;
06578       } else {
06579          res = send_trunk(tpeer, &now);
06580          if (iaxtrunkdebug)
06581             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);
06582       }     
06583       totalcalls += res;   
06584       res = 0;
06585       ast_mutex_unlock(&tpeer->lock);
06586       prev = tpeer;
06587       tpeer = tpeer->next;
06588    }
06589    ast_mutex_unlock(&tpeerlock);
06590    if (drop) {
06591       ast_mutex_lock(&drop->lock);
06592       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06593          because by the time they could get tpeerlock, we've already grabbed it */
06594       if (option_debug)
06595          ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06596       if (drop->trunkdata) {
06597          free(drop->trunkdata);
06598          drop->trunkdata = NULL;
06599       }
06600       ast_mutex_unlock(&drop->lock);
06601       ast_mutex_destroy(&drop->lock);
06602       free(drop);
06603       
06604    }
06605    if (iaxtrunkdebug)
06606       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06607    iaxtrunkdebug =0;
06608    return 1;
06609 }

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

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

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

static int try_firmware ( char *  s  )  [static]

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

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

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

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

05746 {
05747    int newcall = 0;
05748    char newip[256];
05749    struct iax_ie_data ied;
05750    struct sockaddr_in new;
05751    
05752    
05753    memset(&ied, 0, sizeof(ied));
05754    if (ies->apparent_addr)
05755       bcopy(ies->apparent_addr, &new, sizeof(new));
05756    if (ies->callno)
05757       newcall = ies->callno;
05758    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05759       ast_log(LOG_WARNING, "Invalid transfer request\n");
05760       return -1;
05761    }
05762    pvt->transfercallno = newcall;
05763    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05764    inet_aton(newip, &pvt->transfer.sin_addr);
05765    pvt->transfer.sin_family = AF_INET;
05766    pvt->transferring = TRANSFER_BEGIN;
05767    pvt->transferid = ies->transferid;
05768    if (ies->transferid)
05769       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05770    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05771    return 0; 
05772 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1084 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

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

static void unlink_peer ( struct iax2_peer peer  )  [static]

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

06018 {
06019    if (peer->expire > -1) {
06020       if (!ast_sched_del(sched, peer->expire)) {
06021          peer->expire = -1;
06022          peer_unref(peer);
06023       }
06024    }
06025 
06026    if (peer->pokeexpire > -1) {
06027       if (!ast_sched_del(sched, peer->pokeexpire)) {
06028          peer->pokeexpire = -1;
06029          peer_unref(peer);
06030       }
06031    }
06032 
06033    ao2_unlink(peers, peer);
06034 }

static int unload_module ( void   )  [static]

Definition at line 11045 of file chan_iax2.c.

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

11046 {
11047    ast_custom_function_unregister(&iaxpeer_function);
11048    return __unload_module();
11049 }

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

Definition at line 3473 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

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

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

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

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

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

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

static void update_max_nontrunk ( void   )  [static]

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

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

static void update_max_trunk ( void   )  [static]

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

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

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2136 of file chan_iax2.c.

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

Referenced by __attempt_transmit().

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

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

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

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

Referenced by load_module().

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

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

Definition at line 9760 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09761 {
09762    struct iax2_user *user = obj;
09763 
09764    ast_set_flag(user, IAX_DELME);
09765 
09766    return 0;
09767 }

static void user_destructor ( void *  obj  )  [static]

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

09525 {
09526    struct iax2_user *user = obj;
09527 
09528    ast_free_ha(user->ha);
09529    free_context(user->contexts);
09530    if(user->vars) {
09531       ast_variables_destroy(user->vars);
09532       user->vars = NULL;
09533    }
09534    ast_string_field_free_memory(user);
09535 }

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

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1170 of file chan_iax2.c.

References ao2_ref().

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

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

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

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

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

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

06445 {
06446    struct iax_frame *f;
06447 
06448    AST_LIST_LOCK(&iaxq.queue);
06449    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06450       /* Send a copy immediately */
06451       if ((f->callno == callno) && iaxs[f->callno] &&
06452          ((unsigned char ) (f->oseqno - last) < 128) &&
06453          (f->retries >= 0)) {
06454          send_packet(f);
06455       }
06456    }
06457    AST_LIST_UNLOCK(&iaxq.queue);
06458 }


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

Initial value:

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

Definition at line 10846 of file chan_iax2.c.

Initial value:

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

Definition at line 10856 of file chan_iax2.c.

Initial value:

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

Definition at line 10851 of file chan_iax2.c.

Initial value:

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

Definition at line 10836 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 10810 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 10802 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 10794 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 10752 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10726 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 10818 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 825 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 10662 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 814 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 832 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_nontrunk().

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 831 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 10814 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 10806 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 10798 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 8767 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 8769 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 10748 of file chan_iax2.c.

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

Definition at line 8768 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 10740 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 10768 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 10786 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 10772 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 10744 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 10780 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10756 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 10790 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 10736 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 10776 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 10763 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 Tue Sep 30 01:19:48 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.6