Mon Mar 31 07:39:27 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"

Include dependency graph for chan_iax2.c:

Go to the source code of this file.

Data Structures

struct  ast_firmware_list
struct  ast_iax2_queue
struct  chan_iax2_pvt
struct  create_addr_info
struct  dpreq_data
struct  iax2_context
struct  iax2_dpcache
struct  iax2_peer
struct  iax2_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   0x4000
#define TS_GAP_FOR_JB_RESYNC   5000

Enumerations

enum  { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2), IAX_STATE_UNCHANGED = (1 << 3) }
enum  {
  IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3),
  IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7),
  IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12),
  IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16),
  IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20),
  IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24),
  IAX_DELAYPBXSTART = (1 << 25)
}
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 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)
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)
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 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 save_rr (struct iax_frame *fr, struct iax_ies *ies)
static void * sched_thread (void *ignore)
static int schedule_delivery (struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout)
static int send_command (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_final (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_immediate (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_locked (unsigned short callno, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_transfer (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int)
static int send_lagrq (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 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 int iaxactivethreadcount = 0
static int iaxcompat = 0
static int iaxdebug = 0
static int iaxdefaultdpcache = 10 * 60
static int iaxdefaulttimeout = 5
static int iaxdynamicthreadcount = 0
static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT
ast_custom_function iaxpeer_function
static struct ast_iax2_queue iaxq
static struct chan_iax2_pvtiaxs [IAX_MAX_CALLS]
static ast_mutex_t iaxsl [IAX_MAX_CALLS]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct io_contextio
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static struct timeval lastused [IAX_MAX_CALLS]
static int max_reg_expire
static int max_retries = 4
static int maxauthreq = 3
static int maxjitterbuffer = 1000
static int maxjitterinterps = 10
static int maxnontrunkcall = 1
static int maxtrunkcall = TRUNK_CALL_START
static int min_reg_expire
static char mohinterpret [MAX_MUSICCLASS]
static char mohsuggest [MAX_MUSICCLASS]
static struct ast_netsock_listnetsock
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_jb_usage []
static char no_debug_trunk_usage []
static char no_debug_usage []
static struct ast_netsock_listoutsock
static char * papp = "IAX2Provision"
static char * pdescrip
static struct ao2_containerpeers
static int ping_time = 21
static struct ast_codec_pref prefs
static char prune_realtime_usage []
static char * psyn = "Provision a calling IAXy with a given template"
static char regcontext [AST_MAX_CONTEXT] = ""
static int resyncthreshold = 1000
static struct sched_contextsched
static ast_cond_t sched_cond
static pthread_t schedthreadid = AST_PTHREADT_NULL
static char show_cache_usage []
static char show_channels_usage []
static char show_firmware_usage []
static char show_netstats_usage []
static char show_peer_usage []
static char show_peers_usage []
static char show_prov_usage []
static char show_reg_usage []
static char show_stats_usage []
static char show_threads_usage []
static char show_users_usage []
static const char tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)"
static int test_losspct = 0
static int timingfd = -1
static unsigned int tos = 0
static struct iax2_trunk_peertpeers
static int trunkfreq = 20
static struct ao2_containerusers
static struct ast_firmware_list waresl


Detailed Description

Implementation of Inter-Asterisk eXchange Version 2.

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

Definition in file chan_iax2.c.


Define Documentation

#define CACHE_FLAG_CANEXIST   (1 << 2)

Extension can exist

Definition at line 666 of file chan_iax2.c.

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

#define CACHE_FLAG_EXISTS   (1 << 0)

Extension exists

Definition at line 662 of file chan_iax2.c.

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

#define CACHE_FLAG_MATCHMORE   (1 << 7)

Matchmore

Definition at line 676 of file chan_iax2.c.

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

#define CACHE_FLAG_NONEXISTENT   (1 << 1)

Extension is nonexistent

Definition at line 664 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

#define CACHE_FLAG_PENDING   (1 << 3)

Waiting to hear back response

Definition at line 668 of file chan_iax2.c.

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

#define CACHE_FLAG_TIMEOUT   (1 << 4)

Timed out

Definition at line 670 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

Definition at line 672 of file chan_iax2.c.

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

#define CACHE_FLAG_UNKNOWN   (1 << 6)

Timeout

Definition at line 674 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 123 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 111 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 134 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

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

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 126 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 199 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 127 of file chan_iax2.c.

Referenced by complete_transfer(), and find_callno().

#define DEFAULT_THREAD_COUNT   10

Definition at line 125 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

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

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 182 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 190 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 195 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 184 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 697 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 699 of file chan_iax2.c.

#define IAX_IOSTATE_READY   1

Definition at line 698 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 700 of file chan_iax2.c.

Referenced by __schedule_action().

#define IAX_TYPE_DYNAMIC   2

Definition at line 703 of file chan_iax2.c.

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

#define IAX_TYPE_POOL   1

Definition at line 702 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 114 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 440 of file chan_iax2.c.

#define MAX_PEER_BUCKETS   1

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

Definition at line 648 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 444 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 653 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 128 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 441 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

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

Referenced by find_callno(), and socket_process().

#define NEW_FORCE   2

Definition at line 1240 of file chan_iax2.c.

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

#define NEW_PREVENT   0

Definition at line 1238 of file chan_iax2.c.

Referenced by socket_process().

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

Definition at line 122 of file chan_iax2.c.

Referenced by __auto_congest(), __get_from_jb(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), and iax2_write().

#define SCHED_MULTITHREADED

Definition at line 107 of file chan_iax2.c.

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

Definition at line 966 of file chan_iax2.c.

Referenced by attempt_transmit(), auth_reject(), auto_congest(), auto_hangup(), expire_registry(), get_from_jb(), iax2_do_register_s(), iax2_poke_noanswer(), iax2_poke_peer_s(), send_lagrq(), and send_ping().

#define TRUNK_CALL_START   0x4000

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

00235      {
00236    IAX_STATE_STARTED =     (1 << 0),
00237    IAX_STATE_AUTHENTICATED =  (1 << 1),
00238    IAX_STATE_TBD =      (1 << 2),
00239    IAX_STATE_UNCHANGED =      (1 << 3),
00240 } 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

Definition at line 247 of file chan_iax2.c.

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

enum iax_reg_state

Enumerator:
REG_STATE_UNREGISTERED 
REG_STATE_REGSENT 
REG_STATE_AUTHSENT 
REG_STATE_REGISTERED 
REG_STATE_REJECTED 
REG_STATE_TIMEOUT 
REG_STATE_NOAUTH 

Definition at line 395 of file chan_iax2.c.

enum iax_transfer_state

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

Definition at line 405 of file chan_iax2.c.


Function Documentation

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

Definition at line 2034 of file chan_iax2.c.

References chan_iax2_pvt::addr, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, chan_iax2_pvt::error, f, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), send_packet(), ast_frame::subclass, update_packet(), and iax2_registry::us.

Referenced by attempt_transmit().

02035 {
02036    /* Attempt to transmit the frame to the remote peer...
02037       Called without iaxsl held. */
02038    struct iax_frame *f = (struct iax_frame *)data;
02039    int freeme=0;
02040    int callno = f->callno;
02041    /* Make sure this call is still active */
02042    if (callno) 
02043       ast_mutex_lock(&iaxsl[callno]);
02044    if (callno && iaxs[callno]) {
02045       if ((f->retries < 0) /* Already ACK'd */ ||
02046           (f->retries >= max_retries) /* Too many attempts */) {
02047             /* Record an error if we've transmitted too many times */
02048             if (f->retries >= max_retries) {
02049                if (f->transfer) {
02050                   /* Transfer timeout */
02051                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
02052                } else if (f->final) {
02053                   if (f->final) 
02054                      iax2_destroy(callno);
02055                } else {
02056                   if (iaxs[callno]->owner)
02057                      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);
02058                   iaxs[callno]->error = ETIMEDOUT;
02059                   if (iaxs[callno]->owner) {
02060                      struct ast_frame fr = { 0, };
02061                      /* Hangup the fd */
02062                      fr.frametype = AST_FRAME_CONTROL;
02063                      fr.subclass = AST_CONTROL_HANGUP;
02064                      iax2_queue_frame(callno, &fr); // XXX
02065                      /* Remember, owner could disappear */
02066                      if (iaxs[callno] && iaxs[callno]->owner)
02067                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
02068                   } else {
02069                      if (iaxs[callno]->reg) {
02070                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
02071                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
02072                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
02073                      }
02074                      iax2_destroy(callno);
02075                   }
02076                }
02077 
02078             }
02079             freeme++;
02080       } else {
02081          /* Update it if it needs it */
02082          update_packet(f);
02083          /* Attempt transmission */
02084          send_packet(f);
02085          f->retries++;
02086          /* Try again later after 10 times as long */
02087          f->retrytime *= 10;
02088          if (f->retrytime > MAX_RETRY_TIME)
02089             f->retrytime = MAX_RETRY_TIME;
02090          /* Transfer messages max out at one second */
02091          if (f->transfer && (f->retrytime > 1000))
02092             f->retrytime = 1000;
02093          f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
02094       }
02095    } else {
02096       /* Make sure it gets freed */
02097       f->retries = -1;
02098       freeme++;
02099    }
02100    if (callno)
02101       ast_mutex_unlock(&iaxsl[callno]);
02102    /* Do not try again */
02103    if (freeme) {
02104       /* Don't attempt delivery, just remove it from the queue */
02105       AST_LIST_LOCK(&iaxq.queue);
02106       AST_LIST_REMOVE(&iaxq.queue, f, list);
02107       iaxq.count--;
02108       AST_LIST_UNLOCK(&iaxq.queue);
02109       f->retrans = -1;
02110       /* Free the IAX frame */
02111       iax2_frame_free(f);
02112    }
02113 }

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

Definition at line 6203 of file chan_iax2.c.

References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, and send_command_final().

Referenced by auth_reject().

06204 {
06205    /* Called from IAX thread only, without iaxs lock */
06206    int callno = (int)(long)(nothing);
06207    struct iax_ie_data ied;
06208    ast_mutex_lock(&iaxsl[callno]);
06209    if (iaxs[callno]) {
06210       memset(&ied, 0, sizeof(ied));
06211       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06212          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06213          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06214       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06215          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06216          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06217       }
06218       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06219    }
06220    ast_mutex_unlock(&iaxsl[callno]);
06221 }

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

Definition at line 2995 of file chan_iax2.c.

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

Referenced by auto_congest().

02996 {
02997    int callno = PTR_TO_CALLNO(nothing);
02998    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
02999    ast_mutex_lock(&iaxsl[callno]);
03000    if (iaxs[callno]) {
03001       iaxs[callno]->initid = -1;
03002       iax2_queue_frame(callno, &f);
03003       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03004    }
03005    ast_mutex_unlock(&iaxsl[callno]);
03006 }

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

Definition at line 6252 of file chan_iax2.c.

References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, and send_command_final().

Referenced by auto_hangup().

06253 {
06254    /* Called from IAX thread only, without iaxs lock */
06255    int callno = (int)(long)(nothing);
06256    struct iax_ie_data ied;
06257    ast_mutex_lock(&iaxsl[callno]);
06258    if (iaxs[callno]) {
06259       memset(&ied, 0, sizeof(ied));
06260       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06261       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06262       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06263    }
06264    ast_mutex_unlock(&iaxsl[callno]);
06265 }

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

01798 {
01799    /* Just deliver the packet by using queueing.  This is called by
01800      the IAX thread with the iaxsl lock held. */
01801    struct iax_frame *fr = data;
01802    fr->retrans = -1;
01803    ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
01804    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
01805       iax2_queue_frame(fr->callno, &fr->af);
01806    /* Free our iax frame */
01807    iax2_frame_free(fr);
01808    /* And don't run again */
01809    return 0;
01810 }

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

Definition at line 5891 of file chan_iax2.c.

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

Referenced by expire_registry().

05892 {
05893    struct iax2_peer *peer = (struct iax2_peer *) data;
05894 
05895    if (!peer)
05896       return;
05897 
05898    peer->expire = -1;
05899 
05900    if (option_debug)
05901       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
05902    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
05903       realtime_update_peer(peer->name, &peer->addr, 0);
05904    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
05905    /* Reset the address */
05906    memset(&peer->addr, 0, sizeof(peer->addr));
05907    /* Reset expiry value */
05908    peer->expiry = min_reg_expire;
05909    if (!ast_test_flag(peer, IAX_TEMPONLY))
05910       ast_db_del("IAX/Registry", peer->name);
05911    register_peer_exten(peer, 0);
05912    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
05913    if (iax2_regfunk)
05914       iax2_regfunk(peer->name, 0);
05915 
05916    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
05917       unlink_peer(peer);
05918 
05919    peer_unref(peer);
05920 }

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

Definition at line 2431 of file chan_iax2.c.

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

Referenced by get_from_jb().

02432 {
02433    int callno = PTR_TO_CALLNO(p);
02434    struct chan_iax2_pvt *pvt = NULL;
02435    struct iax_frame *fr;
02436    jb_frame frame;
02437    int ret;
02438    long now;
02439    long next;
02440    struct timeval tv;
02441    
02442    /* Make sure we have a valid private structure before going on */
02443    ast_mutex_lock(&iaxsl[callno]);
02444    pvt = iaxs[callno];
02445    if (!pvt) {
02446       /* No go! */
02447       ast_mutex_unlock(&iaxsl[callno]);
02448       return;
02449    }
02450     
02451     if( pvt->jb == NULL ) {
02452    ast_log( LOG_ERROR, "__get_from_jb(): why p->jb is null?\n" );
02453    ast_backtrace();
02454    return;
02455     }
02456 
02457    pvt->jbid = -1;
02458    
02459    gettimeofday(&tv,NULL);
02460    /* round up a millisecond since ast_sched_runq does; */
02461    /* prevents us from spinning while waiting for our now */
02462    /* to catch up with runq's now */
02463    tv.tv_usec += 1000;
02464    
02465    now = ast_tvdiff_ms(tv, pvt->rxcore);
02466    
02467    if(now >= (next = jb_next(pvt->jb))) {
02468       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02469       switch(ret) {
02470       case JB_OK:
02471          fr = frame.data;
02472          __do_deliver(fr);
02473          /* __do_deliver() can cause the call to disappear */
02474          pvt = iaxs[callno];
02475          break;
02476       case JB_INTERP:
02477       {
02478          struct ast_frame af = { 0, };
02479          
02480          /* create an interpolation frame */
02481          af.frametype = AST_FRAME_VOICE;
02482          af.subclass = pvt->voiceformat;
02483          af.samples  = frame.ms * 8;
02484          af.src  = "IAX2 JB interpolation";
02485          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02486          af.offset = AST_FRIENDLY_OFFSET;
02487          
02488          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02489           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02490          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
02491             iax2_queue_frame(callno, &af);
02492             /* iax2_queue_frame() could cause the call to disappear */
02493             pvt = iaxs[callno];
02494          }
02495       }
02496          break;
02497       case JB_DROP:
02498          iax2_frame_free(frame.data);
02499          break;
02500       case JB_NOFRAME:
02501       case JB_EMPTY:
02502          /* do nothing */
02503          break;
02504       default:
02505          /* shouldn't happen */
02506          break;
02507       }
02508    }
02509    if (pvt)
02510       update_jbsched(pvt);
02511    ast_mutex_unlock(&iaxsl[callno]);
02512 }

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

Definition at line 5590 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05591 {
05592    struct iax2_registry *reg = (struct iax2_registry *)data;
05593    reg->expire = -1;
05594    iax2_do_register(reg);
05595 }

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

Definition at line 8639 of file chan_iax2.c.

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

Referenced by iax2_poke_noanswer().

08640 {
08641    struct iax2_peer *peer = (struct iax2_peer *)data;
08642    if (peer->lastms > -1) {
08643       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08644       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08645       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08646    }
08647    if (peer->callno > 0) {
08648       ast_mutex_lock(&iaxsl[peer->callno]);
08649       iax2_destroy(peer->callno);
08650       ast_mutex_unlock(&iaxsl[peer->callno]);
08651    }
08652    peer->callno = 0;
08653    peer->lastms = -1;
08654    /* Try again quickly */
08655    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08656    if (peer->pokeexpire == -1)
08657       peer_unref(peer);
08658 }

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

Definition at line 6315 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06316 {
06317    struct iax2_peer *peer = (struct iax2_peer *)data;
06318    iax2_poke_peer(peer, 0);
06319    peer_unref(peer);
06320 }

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

Definition at line 4380 of file chan_iax2.c.

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

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04381 {
04382    regex_t regexbuf;
04383    int havepattern = 0;
04384    int total_peers = 0;
04385    int online_peers = 0;
04386    int offline_peers = 0;
04387    int unmonitored_peers = 0;
04388    struct ao2_iterator i;
04389 
04390 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04391 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04392 
04393    struct iax2_peer *peer = NULL;
04394    char name[256];
04395    int registeredonly=0;
04396    char *term = manager ? "\r\n" : "\n";
04397 
04398    switch (argc) {
04399    case 6:
04400       if (!strcasecmp(argv[3], "registered"))
04401          registeredonly = 1;
04402       else
04403          return RESULT_SHOWUSAGE;
04404       if (!strcasecmp(argv[4], "like")) {
04405          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04406             return RESULT_SHOWUSAGE;
04407          havepattern = 1;
04408       } else
04409          return RESULT_SHOWUSAGE;
04410       break;
04411    case 5:
04412       if (!strcasecmp(argv[3], "like")) {
04413          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04414             return RESULT_SHOWUSAGE;
04415          havepattern = 1;
04416       } else
04417          return RESULT_SHOWUSAGE;
04418       break;
04419    case 4:
04420       if (!strcasecmp(argv[3], "registered"))
04421          registeredonly = 1;
04422       else
04423          return RESULT_SHOWUSAGE;
04424       break;
04425    case 3:
04426       break;
04427    default:
04428       return RESULT_SHOWUSAGE;
04429    }
04430 
04431 
04432    if (s)
04433       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04434    else
04435       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04436 
04437    i = ao2_iterator_init(peers, 0);
04438    for (peer = ao2_iterator_next(&i); peer; 
04439       peer_unref(peer), peer = ao2_iterator_next(&i)) {
04440       char nm[20];
04441       char status[20];
04442       char srch[2000];
04443       int retstatus;
04444 
04445       if (registeredonly && !peer->addr.sin_addr.s_addr)
04446          continue;
04447       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04448          continue;
04449 
04450       if (!ast_strlen_zero(peer->username))
04451          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04452       else
04453          ast_copy_string(name, peer->name, sizeof(name));
04454       
04455       retstatus = peer_status(peer, status, sizeof(status));
04456       if (retstatus > 0)
04457          online_peers++;
04458       else if (!retstatus)
04459          offline_peers++;
04460       else
04461          unmonitored_peers++;
04462       
04463       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04464       
04465       snprintf(srch, sizeof(srch), FORMAT, name, 
04466           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04467           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04468           nm,
04469           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04470           peer->encmethods ? "(E)" : "   ", status, term);
04471       
04472       if (s)
04473          astman_append(s, FORMAT, name, 
04474                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04475                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04476                   nm,
04477                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04478                   peer->encmethods ? "(E)" : "   ", status, term);
04479       else
04480          ast_cli(fd, FORMAT, name, 
04481             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04482             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04483             nm,
04484             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04485             peer->encmethods ? "(E)" : "   ", status, term);
04486       total_peers++;
04487    }
04488 
04489    if (s)
04490       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04491    else
04492       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04493 
04494    if (havepattern)
04495       regfree(&regexbuf);
04496 
04497    return RESULT_SUCCESS;
04498 #undef FORMAT
04499 #undef FORMAT2
04500 }

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

Definition at line 941 of file chan_iax2.c.

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

00942 {
00943    struct iax2_thread *thread = NULL;
00944    static time_t lasterror;
00945    static time_t t;
00946 
00947    thread = find_idle_thread();
00948 
00949    if (thread != NULL) {
00950       thread->schedfunc = func;
00951       thread->scheddata = data;
00952       thread->iostate = IAX_IOSTATE_SCHEDREADY;
00953 #ifdef DEBUG_SCHED_MULTITHREAD
00954       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
00955 #endif
00956       signal_condition(&thread->lock, &thread->cond);
00957       return 0;
00958    }
00959    time(&t);
00960    if (t != lasterror && option_debug) 
00961       ast_log(LOG_DEBUG, "Out of idle IAX2 threads for scheduling!\n");
00962    lasterror = t;
00963 
00964    return -1;
00965 }

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

References f, and iax2_send().

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

04883 {
04884    struct ast_frame f = { 0, };
04885 
04886    f.frametype = type;
04887    f.subclass = command;
04888    f.datalen = datalen;
04889    f.src = __FUNCTION__;
04890    f.data = (void *) data;
04891 
04892    return iax2_send(i, &f, ts, seqno, now, transfer, final);
04893 }

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

Definition at line 1015 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, sched, send_command(), and send_lagrq().

Referenced by send_lagrq().

01016 {
01017    int callno = (long)data;
01018    /* Ping only if it's real not if it's bridged */
01019    ast_mutex_lock(&iaxsl[callno]);
01020    if (iaxs[callno] && iaxs[callno]->lagid > -1) {
01021       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01022       iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01023    }
01024    ast_mutex_unlock(&iaxsl[callno]);
01025 }

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

Definition at line 981 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, sched, send_command(), and send_ping().

Referenced by send_ping().

00982 {
00983    int callno = (long)data;
00984    ast_mutex_lock(&iaxsl[callno]);
00985    if (iaxs[callno] && iaxs[callno]->pingid != -1) {
00986       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
00987       iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
00988    }
00989    ast_mutex_unlock(&iaxsl[callno]);
00990 }

static int __unload_module ( void   )  [static]

Definition at line 10758 of file chan_iax2.c.

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

Referenced by load_module(), and unload_module().

10759 {
10760    struct iax2_thread *thread = NULL;
10761    int x;
10762 
10763    /* Make sure threads do not hold shared resources when they are canceled */
10764    
10765    /* Grab the sched lock resource to keep it away from threads about to die */
10766    /* Cancel the network thread, close the net socket */
10767    if (netthreadid != AST_PTHREADT_NULL) {
10768       AST_LIST_LOCK(&iaxq.queue);
10769       ast_mutex_lock(&sched_lock);
10770       pthread_cancel(netthreadid);
10771       ast_cond_signal(&sched_cond);
10772       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10773       AST_LIST_UNLOCK(&iaxq.queue);
10774       pthread_join(netthreadid, NULL);
10775    }
10776    if (schedthreadid != AST_PTHREADT_NULL) {
10777       ast_mutex_lock(&sched_lock);  
10778       pthread_cancel(schedthreadid);
10779       ast_cond_signal(&sched_cond);
10780       ast_mutex_unlock(&sched_lock);   
10781       pthread_join(schedthreadid, NULL);
10782    }
10783    
10784    /* Call for all threads to halt */
10785    AST_LIST_LOCK(&idle_list);
10786    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10787       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10788       pthread_cancel(thread->threadid);
10789    }
10790    AST_LIST_TRAVERSE_SAFE_END
10791    AST_LIST_UNLOCK(&idle_list);
10792 
10793    AST_LIST_LOCK(&active_list);
10794    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10795       AST_LIST_REMOVE_CURRENT(&active_list, list);
10796       pthread_cancel(thread->threadid);
10797    }
10798    AST_LIST_TRAVERSE_SAFE_END
10799    AST_LIST_UNLOCK(&active_list);
10800 
10801    AST_LIST_LOCK(&dynamic_list);
10802         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
10803       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
10804       pthread_cancel(thread->threadid);
10805         }
10806    AST_LIST_TRAVERSE_SAFE_END
10807         AST_LIST_UNLOCK(&dynamic_list);
10808 
10809    AST_LIST_HEAD_DESTROY(&iaxq.queue);
10810 
10811    /* Wait for threads to exit */
10812    while(0 < iaxactivethreadcount)
10813       usleep(10000);
10814    
10815    ast_netsock_release(netsock);
10816    ast_netsock_release(outsock);
10817    for (x=0;x<IAX_MAX_CALLS;x++)
10818       if (iaxs[x])
10819          iax2_destroy(x);
10820    ast_manager_unregister( "IAXpeers" );
10821    ast_manager_unregister( "IAXnetstats" );
10822    ast_unregister_application(papp);
10823    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10824    ast_unregister_switch(&iax2_switch);
10825    ast_channel_unregister(&iax2_tech);
10826    delete_users();
10827    iax_provision_unload();
10828    sched_context_destroy(sched);
10829    reload_firmware(1);
10830 
10831    ast_mutex_destroy(&waresl.lock);
10832 
10833    for (x = 0; x < IAX_MAX_CALLS; x++)
10834       ast_mutex_destroy(&iaxsl[x]);
10835 
10836    ao2_ref(peers, -1);
10837    ao2_ref(users, -1);
10838 
10839    return 0;
10840 }

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

Definition at line 4934 of file chan_iax2.c.

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

Referenced by check_access().

04935 {
04936    while(con) {
04937       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
04938          return -1;
04939       con = con->next;
04940    }
04941    return 0;
04942 }

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

Definition at line 4708 of file chan_iax2.c.

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

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04709 {
04710    int x;
04711    int numchans = 0;
04712    for (x=0;x<IAX_MAX_CALLS;x++) {
04713       ast_mutex_lock(&iaxsl[x]);
04714       if (iaxs[x]) {
04715          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04716          char *fmt;
04717          jb_info jbinfo;
04718          
04719          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04720             jb_getinfo(iaxs[x]->jb, &jbinfo);
04721             localjitter = jbinfo.jitter;
04722             localdelay = jbinfo.current - jbinfo.min;
04723             locallost = jbinfo.frames_lost;
04724             locallosspct = jbinfo.losspct/1000;
04725             localdropped = jbinfo.frames_dropped;
04726             localooo = jbinfo.frames_ooo;
04727          } else {
04728             localjitter = -1;
04729             localdelay = 0;
04730             locallost = -1;
04731             locallosspct = -1;
04732             localdropped = 0;
04733             localooo = -1;
04734          }
04735          if (limit_fmt)
04736             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04737          else
04738             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04739          if (s)
04740             
04741             astman_append(s, fmt,
04742                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04743                      iaxs[x]->pingtime,
04744                      localjitter, 
04745                      localdelay,
04746                      locallost,
04747                      locallosspct,
04748                      localdropped,
04749                      localooo,
04750                      iaxs[x]->frames_received/1000,
04751                      iaxs[x]->remote_rr.jitter,
04752                      iaxs[x]->remote_rr.delay,
04753                      iaxs[x]->remote_rr.losscnt,
04754                      iaxs[x]->remote_rr.losspct,
04755                      iaxs[x]->remote_rr.dropped,
04756                      iaxs[x]->remote_rr.ooo,
04757                      iaxs[x]->remote_rr.packets/1000);
04758          else
04759             ast_cli(fd, fmt,
04760                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04761                iaxs[x]->pingtime,
04762                localjitter, 
04763                localdelay,
04764                locallost,
04765                locallosspct,
04766                localdropped,
04767                localooo,
04768                iaxs[x]->frames_received/1000,
04769                iaxs[x]->remote_rr.jitter,
04770                iaxs[x]->remote_rr.delay,
04771                iaxs[x]->remote_rr.losscnt,
04772                iaxs[x]->remote_rr.losspct,
04773                iaxs[x]->remote_rr.dropped,
04774                iaxs[x]->remote_rr.ooo,
04775                iaxs[x]->remote_rr.packets/1000
04776                );
04777          numchans++;
04778       }
04779       ast_mutex_unlock(&iaxsl[x]);
04780    }
04781    return numchans;
04782 }

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

Create new call, interface with the PBX core.

Definition at line 3594 of file chan_iax2.c.

References chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_string_field_set, ast_strlen_zero(), chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, chan_iax2_pvt::callno, CALLNO_TO_PTR, chan_iax2_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_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().

03595 {
03596    struct ast_channel *tmp;
03597    struct chan_iax2_pvt *i;
03598    struct ast_variable *v = NULL;
03599 
03600    if (!(i = iaxs[callno])) {
03601       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03602       return NULL;
03603    }
03604 
03605    /* Don't hold call lock */
03606    ast_mutex_unlock(&iaxsl[callno]);
03607    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);
03608    ast_mutex_lock(&iaxsl[callno]);
03609    if (!tmp)
03610       return NULL;
03611    tmp->tech = &iax2_tech;
03612    /* We can support any format by default, until we get restricted */
03613    tmp->nativeformats = capability;
03614    tmp->readformat = ast_best_codec(capability);
03615    tmp->writeformat = ast_best_codec(capability);
03616    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03617 
03618    /* Don't use ast_set_callerid() here because it will
03619     * generate a NewCallerID event before the NewChannel event */
03620    if (!ast_strlen_zero(i->ani))
03621       tmp->cid.cid_ani = ast_strdup(i->ani);
03622    else
03623       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03624    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03625    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03626    tmp->cid.cid_pres = i->calling_pres;
03627    tmp->cid.cid_ton = i->calling_ton;
03628    tmp->cid.cid_tns = i->calling_tns;
03629    if (!ast_strlen_zero(i->language))
03630       ast_string_field_set(tmp, language, i->language);
03631    if (!ast_strlen_zero(i->accountcode))
03632       ast_string_field_set(tmp, accountcode, i->accountcode);
03633    if (i->amaflags)
03634       tmp->amaflags = i->amaflags;
03635    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03636    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03637    if (i->adsi)
03638       tmp->adsicpe = i->peeradsicpe;
03639    else
03640       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03641    i->owner = tmp;
03642    i->capability = capability;
03643 
03644    for (v = i->vars ; v ; v = v->next)
03645       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03646 
03647    if (state != AST_STATE_DOWN) {
03648       if (ast_pbx_start(tmp)) {
03649          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03650          ast_hangup(tmp);
03651          i->owner = NULL;
03652          return NULL;
03653       }
03654    }
03655 
03656    ast_module_ref(ast_module_info->self);
03657    
03658    return tmp;
03659 }

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02116 {
02117 #ifdef SCHED_MULTITHREADED
02118    if (schedule_action(__attempt_transmit, data))
02119 #endif      
02120       __attempt_transmit(data);
02121    return 0;
02122 }

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

Definition at line 6237 of file chan_iax2.c.

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

Referenced by socket_process().

06238 {
06239    /* Schedule sending the authentication failure in one second, to prevent
06240       guessing */
06241    if (iaxs[callno]) {
06242       iaxs[callno]->authfail = failcode;
06243       if (delayreject) {
06244          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06245          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06246       } else
06247          auth_reject((void *)(long)callno);
06248    }
06249    return 0;
06250 }

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

Definition at line 6223 of file chan_iax2.c.

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

Referenced by auth_fail().

06224 {
06225    int callno = (int)(long)(data);
06226    ast_mutex_lock(&iaxsl[callno]);
06227    if (iaxs[callno])
06228       iaxs[callno]->authid = -1;
06229    ast_mutex_unlock(&iaxsl[callno]);
06230 #ifdef SCHED_MULTITHREADED
06231    if (schedule_action(__auth_reject, data))
06232 #endif      
06233       __auth_reject(data);
06234    return 0;
06235 }

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

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

05460 {
05461    int res = -1;
05462    int x;
05463    if (!ast_strlen_zero(keyn)) {
05464       if (!(authmethods & IAX_AUTH_RSA)) {
05465          if (ast_strlen_zero(secret)) 
05466             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));
05467       } else if (ast_strlen_zero(challenge)) {
05468          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05469       } else {
05470          char sig[256];
05471          struct ast_key *key;
05472          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05473          if (!key) {
05474             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05475          } else {
05476             if (ast_sign(key, (char*)challenge, sig)) {
05477                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05478                res = -1;
05479             } else {
05480                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05481                res = 0;
05482             }
05483          }
05484       }
05485    } 
05486    /* Fall back */
05487    if (res && !ast_strlen_zero(secret)) {
05488       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05489          struct MD5Context md5;
05490          unsigned char digest[16];
05491          char digres[128];
05492          MD5Init(&md5);
05493          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05494          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05495          MD5Final(digest, &md5);
05496          /* If they support md5, authenticate with it.  */
05497          for (x=0;x<16;x++)
05498             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05499          if (ecx && dcx)
05500             build_enc_keys(digest, ecx, dcx);
05501          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05502          res = 0;
05503       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05504          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05505          res = 0;
05506       } else
05507          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05508    }
05509    return res;
05510 }

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

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

Referenced by socket_process().

05517 {
05518    struct iax2_peer *peer = NULL;
05519    /* Start pessimistic */
05520    int res = -1;
05521    int authmethods = 0;
05522    struct iax_ie_data ied;
05523    uint16_t callno = p->callno;
05524 
05525    memset(&ied, 0, sizeof(ied));
05526    
05527    if (ies->username)
05528       ast_string_field_set(p, username, ies->username);
05529    if (ies->challenge)
05530       ast_string_field_set(p, challenge, ies->challenge);
05531    if (ies->authmethods)
05532       authmethods = ies->authmethods;
05533    if (authmethods & IAX_AUTH_MD5)
05534       merge_encryption(p, ies->encmethods);
05535    else
05536       p->encmethods = 0;
05537 
05538    /* Check for override RSA authentication first */
05539    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05540       /* Normal password authentication */
05541       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05542    } else {
05543       struct ao2_iterator i = ao2_iterator_init(peers, 0);
05544       while ((peer = ao2_iterator_next(&i))) {
05545          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05546              /* No peer specified at our end, or this is the peer */
05547              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05548              /* No username specified in peer rule, or this is the right username */
05549              && (!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)))
05550              /* No specified host, or this is our host */
05551             ) {
05552             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05553             if (!res) {
05554                peer_unref(peer);
05555                break;
05556             }
05557          }
05558          peer_unref(peer);
05559       }
05560       if (!peer) {
05561          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05562             that we're trying to authenticate *to* a realtime peer */
05563          const char *peer_name = ast_strdupa(p->peer);
05564          ast_mutex_unlock(&iaxsl[callno]);
05565          if ((peer = realtime_peer(peer_name, NULL))) {
05566             ast_mutex_lock(&iaxsl[callno]);
05567             if (!(p = iaxs[callno])) {
05568                peer_unref(peer);
05569                return -1;
05570             }
05571             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05572             peer_unref(peer);
05573          }
05574          if (!peer) {
05575             ast_mutex_lock(&iaxsl[callno]);
05576             if (!(p = iaxs[callno]))
05577                return -1;
05578          }
05579       }
05580    }
05581    if (ies->encmethods)
05582       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05583    if (!res)
05584       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05585    return res;
05586 }

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

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

Referenced by socket_process().

05195 {
05196    struct iax_ie_data ied;
05197    int res = -1, authreq_restrict = 0;
05198    char challenge[10];
05199    struct chan_iax2_pvt *p = iaxs[call_num];
05200 
05201    memset(&ied, 0, sizeof(ied));
05202 
05203    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05204    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05205       struct iax2_user *user, tmp_user = {
05206          .name = p->username, 
05207       };
05208 
05209       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05210       if (user) {
05211          if (user->curauthreq == user->maxauthreq)
05212             authreq_restrict = 1;
05213          else
05214             user->curauthreq++;
05215          user = user_unref(user);
05216       }
05217    }
05218 
05219    /* If the AUTHREQ limit test failed, send back an error */
05220    if (authreq_restrict) {
05221       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05222       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05223       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05224       return 0;
05225    }
05226 
05227    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05228    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05229       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05230       ast_string_field_set(p, challenge, challenge);
05231       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05232       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05233    }
05234    if (p->encmethods)
05235       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05236 
05237    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05238 
05239    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05240 
05241    if (p->encmethods)
05242       ast_set_flag(p, IAX_ENCRYPTED);
05243 
05244    return res;
05245 }

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

Definition at line 5247 of file chan_iax2.c.

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

Referenced by socket_process().

05248 {
05249    char requeststr[256];
05250    char md5secret[256] = "";
05251    char secret[256] = "";
05252    char rsasecret[256] = "";
05253    int res = -1; 
05254    int x;
05255    struct iax2_user *user, tmp_user = {
05256       .name = p->username, 
05257    };
05258 
05259    user = ao2_find(users, &tmp_user, OBJ_POINTER);
05260    if (user) {
05261       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05262          ast_atomic_fetchadd_int(&user->curauthreq, -1);
05263          ast_clear_flag(p, IAX_MAXAUTHREQ);
05264       }
05265       ast_string_field_set(p, host, user->name);
05266       user = user_unref(user);
05267    }
05268 
05269    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
05270       return res;
05271    if (ies->password)
05272       ast_copy_string(secret, ies->password, sizeof(secret));
05273    if (ies->md5_result)
05274       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05275    if (ies->rsa_result)
05276       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05277    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
05278       struct ast_key *key;
05279       char *keyn;
05280       char tmpkey[256];
05281       char *stringp=NULL;
05282       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
05283       stringp=tmpkey;
05284       keyn = strsep(&stringp, ":");
05285       while(keyn) {
05286          key = ast_key_get(keyn, AST_KEY_PUBLIC);
05287          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
05288             res = 0;
05289             break;
05290          } else if (!key)
05291             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
05292          keyn = strsep(&stringp, ":");
05293       }
05294    } else if (p->authmethods & IAX_AUTH_MD5) {
05295       struct MD5Context md5;
05296       unsigned char digest[16];
05297       char *tmppw, *stringp;
05298       
05299       tmppw = ast_strdupa(p->secret);
05300       stringp = tmppw;
05301       while((tmppw = strsep(&stringp, ";"))) {
05302          MD5Init(&md5);
05303          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05304          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05305          MD5Final(digest, &md5);
05306          /* If they support md5, authenticate with it.  */
05307          for (x=0;x<16;x++)
05308             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05309          if (!strcasecmp(requeststr, md5secret)) {
05310             res = 0;
05311             break;
05312          }
05313       }
05314    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05315       if (!strcmp(secret, p->secret))
05316          res = 0;
05317    }
05318    return res;
05319 }

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

Definition at line 3008 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03009 {
03010 #ifdef SCHED_MULTITHREADED
03011    if (schedule_action(__auto_congest, data))
03012 #endif      
03013       __auto_congest(data);
03014    return 0;
03015 }

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

Definition at line 6267 of file chan_iax2.c.

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

Referenced by iax2_dprequest(), and iax2_provision().

06268 {
06269    int callno = (int)(long)(data);
06270    ast_mutex_lock(&iaxsl[callno]);
06271    if (iaxs[callno]) {
06272       iaxs[callno]->autoid = -1;
06273    }
06274    ast_mutex_unlock(&iaxsl[callno]);
06275 #ifdef SCHED_MULTITHREADED
06276    if (schedule_action(__auto_hangup, data))
06277 #endif      
06278       __auto_hangup(data);
06279    return 0;
06280 }

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

Definition at line 8953 of file chan_iax2.c.

References ast_calloc.

Referenced by build_user().

08954 {
08955    struct iax2_context *con;
08956 
08957    if ((con = ast_calloc(1, sizeof(*con))))
08958       ast_copy_string(con->context, context, sizeof(con->context));
08959    
08960    return con;
08961 }

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

Definition at line 3966 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

03967 {
03968    aes_encrypt_key128(digest, ecx);
03969    aes_decrypt_key128(digest, dcx);
03970 }

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

Create peer structure based on configuration.

Definition at line 9099 of file chan_iax2.c.

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

09100 {
09101    struct iax2_peer *peer = NULL;
09102    struct ast_ha *oldha = NULL;
09103    int maskfound=0;
09104    int found=0;
09105    int firstpass=1;
09106    struct iax2_peer tmp_peer = {
09107       .name = name,
09108    };
09109 
09110    if (!temponly) {
09111       peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
09112       if (peer && !ast_test_flag(peer, IAX_DELME))
09113          firstpass = 0;
09114    }
09115 
09116    if (peer) {
09117       found++;
09118       if (firstpass) {
09119          oldha = peer->ha;
09120          peer->ha = NULL;
09121       }
09122       unlink_peer(peer);
09123    } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
09124       peer->expire = -1;
09125       peer->pokeexpire = -1;
09126       peer->sockfd = defaultsockfd;
09127       if (ast_string_field_init(peer, 32))
09128          peer = peer_unref(peer);
09129    }
09130 
09131    if (peer) {
09132       if (firstpass) {
09133          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
09134          peer->encmethods = iax2_encryption;
09135          peer->adsi = adsi;
09136          ast_string_field_set(peer,secret,"");
09137          if (!found) {
09138             ast_string_field_set(peer, name, name);
09139             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09140             peer->expiry = min_reg_expire;
09141          }
09142          peer->prefs = prefs;
09143          peer->capability = iax2_capability;
09144          peer->smoothing = 0;
09145          peer->pokefreqok = DEFAULT_FREQ_OK;
09146          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
09147          ast_string_field_set(peer,context,"");
09148          ast_string_field_set(peer,peercontext,"");
09149          ast_clear_flag(peer, IAX_HASCALLERID);
09150          ast_string_field_set(peer, cid_name, "");
09151          ast_string_field_set(peer, cid_num, "");
09152       }
09153 
09154       if (!v) {
09155          v = alt;
09156          alt = NULL;
09157       }
09158       while(v) {
09159          if (!strcasecmp(v->name, "secret")) {
09160             ast_string_field_set(peer, secret, v->value);
09161          } else if (!strcasecmp(v->name, "mailbox")) {
09162             ast_string_field_set(peer, mailbox, v->value);
09163          } else if (!strcasecmp(v->name, "mohinterpret")) {
09164             ast_string_field_set(peer, mohinterpret, v->value);
09165          } else if (!strcasecmp(v->name, "mohsuggest")) {
09166             ast_string_field_set(peer, mohsuggest, v->value);
09167          } else if (!strcasecmp(v->name, "dbsecret")) {
09168             ast_string_field_set(peer, dbsecret, v->value);
09169          } else if (!strcasecmp(v->name, "trunk")) {
09170             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
09171             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
09172                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name);
09173                ast_clear_flag(peer, IAX_TRUNK);
09174             }
09175          } else if (!strcasecmp(v->name, "auth")) {
09176             peer->authmethods = get_auth_methods(v->value);
09177          } else if (!strcasecmp(v->name, "encryption")) {
09178             peer->encmethods = get_encrypt_methods(v->value);
09179          } else if (!strcasecmp(v->name, "notransfer")) {
09180             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09181             ast_clear_flag(peer, IAX_TRANSFERMEDIA);  
09182             ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 
09183          } else if (!strcasecmp(v->name, "transfer")) {
09184             if (!strcasecmp(v->value, "mediaonly")) {
09185                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09186             } else if (ast_true(v->value)) {
09187                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09188             } else 
09189                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09190          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09191             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
09192          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09193             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
09194          } else if (!strcasecmp(v->name, "host")) {
09195             if (!strcasecmp(v->value, "dynamic")) {
09196                /* They'll register with us */
09197                ast_set_flag(peer, IAX_DYNAMIC); 
09198                if (!found) {
09199                   /* Initialize stuff iff we're not found, otherwise
09200                      we keep going with what we had */
09201                   memset(&peer->addr.sin_addr, 0, 4);
09202                   if (peer->addr.sin_port) {
09203                      /* If we've already got a port, make it the default rather than absolute */
09204                      peer->defaddr.sin_port = peer->addr.sin_port;
09205                      peer->addr.sin_port = 0;
09206                   }
09207                }
09208             } else {
09209                /* Non-dynamic.  Make sure we become that way if we're not */
09210                AST_SCHED_DEL(sched, peer->expire);
09211                ast_clear_flag(peer, IAX_DYNAMIC);
09212                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr))
09213                   return peer_unref(peer);
09214                if (!peer->addr.sin_port)
09215                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09216             }
09217             if (!maskfound)
09218                inet_aton("255.255.255.255", &peer->mask);
09219          } else if (!strcasecmp(v->name, "defaultip")) {
09220             if (ast_get_ip(&peer->defaddr, v->value))
09221                return peer_unref(peer);
09222          } else if (!strcasecmp(v->name, "sourceaddress")) {
09223             peer_set_srcaddr(peer, v->value);
09224          } else if (!strcasecmp(v->name, "permit") ||
09225                   !strcasecmp(v->name, "deny")) {
09226             peer->ha = ast_append_ha(v->name, v->value, peer->ha);
09227          } else if (!strcasecmp(v->name, "mask")) {
09228             maskfound++;
09229             inet_aton(v->value, &peer->mask);
09230          } else if (!strcasecmp(v->name, "context")) {
09231             ast_string_field_set(peer, context, v->value);
09232          } else if (!strcasecmp(v->name, "regexten")) {
09233             ast_string_field_set(peer, regexten, v->value);
09234          } else if (!strcasecmp(v->name, "peercontext")) {
09235             ast_string_field_set(peer, peercontext, v->value);
09236          } else if (!strcasecmp(v->name, "port")) {
09237             if (ast_test_flag(peer, IAX_DYNAMIC))
09238                peer->defaddr.sin_port = htons(atoi(v->value));
09239             else
09240                peer->addr.sin_port = htons(atoi(v->value));
09241          } else if (!strcasecmp(v->name, "username")) {
09242             ast_string_field_set(peer, username, v->value);
09243          } else if (!strcasecmp(v->name, "allow")) {
09244             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
09245          } else if (!strcasecmp(v->name, "disallow")) {
09246             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
09247          } else if (!strcasecmp(v->name, "callerid")) {
09248             if (!ast_strlen_zero(v->value)) {
09249                char name2[80];
09250                char num2[80];
09251                ast_callerid_split(v->value, name2, 80, num2, 80);
09252                ast_string_field_set(peer, cid_name, name2);
09253                ast_string_field_set(peer, cid_num, num2);
09254                ast_set_flag(peer, IAX_HASCALLERID);
09255             } else {
09256                ast_clear_flag(peer, IAX_HASCALLERID);
09257                ast_string_field_set(peer, cid_name, "");
09258                ast_string_field_set(peer, cid_num, "");
09259             }
09260          } else if (!strcasecmp(v->name, "fullname")) {
09261             if (!ast_strlen_zero(v->value)) {
09262                ast_string_field_set(peer, cid_name, v->value);
09263                ast_set_flag(peer, IAX_HASCALLERID);
09264             } else {
09265                ast_string_field_set(peer, cid_name, "");
09266                if (ast_strlen_zero(peer->cid_num))
09267                   ast_clear_flag(peer, IAX_HASCALLERID);
09268             }
09269          } else if (!strcasecmp(v->name, "cid_number")) {
09270             if (!ast_strlen_zero(v->value)) {
09271                ast_string_field_set(peer, cid_num, v->value);
09272                ast_set_flag(peer, IAX_HASCALLERID);
09273             } else {
09274                ast_string_field_set(peer, cid_num, "");
09275                if (ast_strlen_zero(peer->cid_name))
09276                   ast_clear_flag(peer, IAX_HASCALLERID);
09277             }
09278          } else if (!strcasecmp(v->name, "sendani")) {
09279             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
09280          } else if (!strcasecmp(v->name, "inkeys")) {
09281             ast_string_field_set(peer, inkeys, v->value);
09282          } else if (!strcasecmp(v->name, "outkey")) {
09283             ast_string_field_set(peer, outkey, v->value);
09284          } else if (!strcasecmp(v->name, "qualify")) {
09285             if (!strcasecmp(v->value, "no")) {
09286                peer->maxms = 0;
09287             } else if (!strcasecmp(v->value, "yes")) {
09288                peer->maxms = DEFAULT_MAXMS;
09289             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
09290                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);
09291                peer->maxms = 0;
09292             }
09293          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
09294             peer->smoothing = ast_true(v->value);
09295          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
09296             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
09297                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);
09298             }
09299          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
09300             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
09301                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);
09302             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
09303          } else if (!strcasecmp(v->name, "timezone")) {
09304             ast_string_field_set(peer, zonetag, v->value);
09305          } else if (!strcasecmp(v->name, "adsi")) {
09306             peer->adsi = ast_true(v->value);
09307          }/* else if (strcasecmp(v->name,"type")) */
09308          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09309          v = v->next;
09310          if (!v) {
09311             v = alt;
09312             alt = NULL;
09313          }
09314       }
09315       if (!peer->authmethods)
09316          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09317       ast_clear_flag(peer, IAX_DELME); 
09318       /* Make sure these are IPv4 addresses */
09319       peer->addr.sin_family = AF_INET;
09320    }
09321    if (oldha)
09322       ast_free_ha(oldha);
09323    return peer;
09324 }

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

Create in-memory user structure from configuration.

Definition at line 9340 of file chan_iax2.c.

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

09341 {
09342    struct iax2_user *user = NULL;
09343    struct iax2_context *con, *conl = NULL;
09344    struct ast_ha *oldha = NULL;
09345    struct iax2_context *oldcon = NULL;
09346    int format;
09347    int firstpass=1;
09348    int oldcurauthreq = 0;
09349    char *varname = NULL, *varval = NULL;
09350    struct ast_variable *tmpvar = NULL;
09351    struct iax2_user tmp_user = {
09352       .name = name,
09353    };
09354 
09355    if (!temponly) {
09356       user = ao2_find(users, &tmp_user, OBJ_POINTER);
09357       if (user && !ast_test_flag(user, IAX_DELME))
09358          firstpass = 0;
09359    }
09360 
09361    if (user) {
09362       if (firstpass) {
09363          oldcurauthreq = user->curauthreq;
09364          oldha = user->ha;
09365          oldcon = user->contexts;
09366          user->ha = NULL;
09367          user->contexts = NULL;
09368       }
09369       /* Already in the list, remove it and it will be added back (or FREE'd) */
09370       ao2_unlink(users, user);
09371    } else {
09372       user = ao2_alloc(sizeof(*user), user_destructor);
09373    }
09374    
09375    if (user) {
09376       if (firstpass) {
09377          ast_string_field_free_memory(user);
09378          memset(user, 0, sizeof(struct iax2_user));
09379          if (ast_string_field_init(user, 32)) {
09380             user = user_unref(user);
09381             goto cleanup;
09382          }
09383          user->maxauthreq = maxauthreq;
09384          user->curauthreq = oldcurauthreq;
09385          user->prefs = prefs;
09386          user->capability = iax2_capability;
09387          user->encmethods = iax2_encryption;
09388          user->adsi = adsi;
09389          ast_string_field_set(user, name, name);
09390          ast_string_field_set(user, language, language);
09391          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
09392          ast_clear_flag(user, IAX_HASCALLERID);
09393          ast_string_field_set(user, cid_name, "");
09394          ast_string_field_set(user, cid_num, "");
09395       }
09396       if (!v) {
09397          v = alt;
09398          alt = NULL;
09399       }
09400       while(v) {
09401          if (!strcasecmp(v->name, "context")) {
09402             con = build_context(v->value);
09403             if (con) {
09404                if (conl)
09405                   conl->next = con;
09406                else
09407                   user->contexts = con;
09408                conl = con;
09409             }
09410          } else if (!strcasecmp(v->name, "permit") ||
09411                   !strcasecmp(v->name, "deny")) {
09412             user->ha = ast_append_ha(v->name, v->value, user->ha);
09413          } else if (!strcasecmp(v->name, "setvar")) {
09414             varname = ast_strdupa(v->value);
09415             if (varname && (varval = strchr(varname,'='))) {
09416                *varval = '\0';
09417                varval++;
09418                if((tmpvar = ast_variable_new(varname, varval))) {
09419                   tmpvar->next = user->vars; 
09420                   user->vars = tmpvar;
09421                }
09422             }
09423          } else if (!strcasecmp(v->name, "allow")) {
09424             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
09425          } else if (!strcasecmp(v->name, "disallow")) {
09426             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
09427          } else if (!strcasecmp(v->name, "trunk")) {
09428             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
09429             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
09430                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name);
09431                ast_clear_flag(user, IAX_TRUNK);
09432             }
09433          } else if (!strcasecmp(v->name, "auth")) {
09434             user->authmethods = get_auth_methods(v->value);
09435          } else if (!strcasecmp(v->name, "encryption")) {
09436             user->encmethods = get_encrypt_methods(v->value);
09437          } else if (!strcasecmp(v->name, "notransfer")) {
09438             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09439             ast_clear_flag(user, IAX_TRANSFERMEDIA);  
09440             ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 
09441          } else if (!strcasecmp(v->name, "transfer")) {
09442             if (!strcasecmp(v->value, "mediaonly")) {
09443                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09444             } else if (ast_true(v->value)) {
09445                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09446             } else 
09447                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09448          } else if (!strcasecmp(v->name, "codecpriority")) {
09449             if(!strcasecmp(v->value, "caller"))
09450                ast_set_flag(user, IAX_CODEC_USER_FIRST);
09451             else if(!strcasecmp(v->value, "disabled"))
09452                ast_set_flag(user, IAX_CODEC_NOPREFS);
09453             else if(!strcasecmp(v->value, "reqonly")) {
09454                ast_set_flag(user, IAX_CODEC_NOCAP);
09455                ast_set_flag(user, IAX_CODEC_NOPREFS);
09456             }
09457          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09458             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
09459          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09460             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
09461          } else if (!strcasecmp(v->name, "dbsecret")) {
09462             ast_string_field_set(user, dbsecret, v->value);
09463          } else if (!strcasecmp(v->name, "secret")) {
09464             if (!ast_strlen_zero(user->secret)) {
09465                char *old = ast_strdupa(user->secret);
09466 
09467                ast_string_field_build(user, secret, "%s;%s", old, v->value);
09468             } else
09469                ast_string_field_set(user, secret, v->value);
09470          } else if (!strcasecmp(v->name, "callerid")) {
09471             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
09472                char name2[80];
09473                char num2[80];
09474                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
09475                ast_string_field_set(user, cid_name, name2);
09476                ast_string_field_set(user, cid_num, num2);
09477                ast_set_flag(user, IAX_HASCALLERID);
09478             } else {
09479                ast_clear_flag(user, IAX_HASCALLERID);
09480                ast_string_field_set(user, cid_name, "");
09481                ast_string_field_set(user, cid_num, "");
09482             }
09483          } else if (!strcasecmp(v->name, "fullname")) {
09484             if (!ast_strlen_zero(v->value)) {
09485                ast_string_field_set(user, cid_name, v->value);
09486                ast_set_flag(user, IAX_HASCALLERID);
09487             } else {
09488                ast_string_field_set(user, cid_name, "");
09489                if (ast_strlen_zero(user->cid_num))
09490                   ast_clear_flag(user, IAX_HASCALLERID);
09491             }
09492          } else if (!strcasecmp(v->name, "cid_number")) {
09493             if (!ast_strlen_zero(v->value)) {
09494                ast_string_field_set(user, cid_num, v->value);
09495                ast_set_flag(user, IAX_HASCALLERID);
09496             } else {
09497                ast_string_field_set(user, cid_num, "");
09498                if (ast_strlen_zero(user->cid_name))
09499                   ast_clear_flag(user, IAX_HASCALLERID);
09500             }
09501          } else if (!strcasecmp(v->name, "accountcode")) {
09502             ast_string_field_set(user, accountcode, v->value);
09503          } else if (!strcasecmp(v->name, "mohinterpret")) {
09504             ast_string_field_set(user, mohinterpret, v->value);
09505          } else if (!strcasecmp(v->name, "mohsuggest")) {
09506             ast_string_field_set(user, mohsuggest, v->value);
09507          } else if (!strcasecmp(v->name, "language")) {
09508             ast_string_field_set(user, language, v->value);
09509          } else if (!strcasecmp(v->name, "amaflags")) {
09510             format = ast_cdr_amaflags2int(v->value);
09511             if (format < 0) {
09512                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09513             } else {
09514                user->amaflags = format;
09515             }
09516          } else if (!strcasecmp(v->name, "inkeys")) {
09517             ast_string_field_set(user, inkeys, v->value);
09518          } else if (!strcasecmp(v->name, "maxauthreq")) {
09519             user->maxauthreq = atoi(v->value);
09520             if (user->maxauthreq < 0)
09521                user->maxauthreq = 0;
09522          } else if (!strcasecmp(v->name, "adsi")) {
09523             user->adsi = ast_true(v->value);
09524          }/* else if (strcasecmp(v->name,"type")) */
09525          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09526          v = v->next;
09527          if (!v) {
09528             v = alt;
09529             alt = NULL;
09530          }
09531       }
09532       if (!user->authmethods) {
09533          if (!ast_strlen_zero(user->secret)) {
09534             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09535             if (!ast_strlen_zero(user->inkeys))
09536                user->authmethods |= IAX_AUTH_RSA;
09537          } else if (!ast_strlen_zero(user->inkeys)) {
09538             user->authmethods = IAX_AUTH_RSA;
09539          } else {
09540             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09541          }
09542       }
09543       ast_clear_flag(user, IAX_DELME);
09544    }
09545 cleanup:
09546    if (oldha)
09547       ast_free_ha(oldha);
09548    if (oldcon)
09549       free_context(oldcon);
09550    return user;
09551 }

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

Definition at line 10054 of file chan_iax2.c.

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

Referenced by find_cache().

10055 {
10056    struct sockaddr_in sin;
10057    int x;
10058    int callno;
10059    struct iax_ie_data ied;
10060    struct create_addr_info cai;
10061    struct parsed_dial_string pds;
10062    char *tmpstr;
10063 
10064    for (x=0; x<IAX_MAX_CALLS; x++) {
10065       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10066          look up entries for a single context */
10067       if (!ast_mutex_trylock(&iaxsl[x])) {
10068          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10069             return x;
10070          ast_mutex_unlock(&iaxsl[x]);
10071       }
10072    }
10073 
10074    /* No match found, we need to create a new one */
10075 
10076    memset(&cai, 0, sizeof(cai));
10077    memset(&ied, 0, sizeof(ied));
10078    memset(&pds, 0, sizeof(pds));
10079 
10080    tmpstr = ast_strdupa(data);
10081    parse_dial_string(tmpstr, &pds);
10082 
10083    if (ast_strlen_zero(pds.peer)) {
10084       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
10085       return -1;
10086    }
10087 
10088    /* Populate our address from the given */
10089    if (create_addr(pds.peer, NULL, &sin, &cai))
10090       return -1;
10091 
10092    if (option_debug)
10093       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10094          pds.peer, pds.username, pds.password, pds.context);
10095 
10096    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
10097    if (callno < 1) {
10098       ast_log(LOG_WARNING, "Unable to create call\n");
10099       return -1;
10100    }
10101 
10102    ast_mutex_lock(&iaxsl[callno]);
10103    ast_string_field_set(iaxs[callno], dproot, data);
10104    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10105 
10106    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10107    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10108    /* the string format is slightly different from a standard dial string,
10109       because the context appears in the 'exten' position
10110    */
10111    if (pds.exten)
10112       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10113    if (pds.username)
10114       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10115    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10116    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10117    /* Keep password handy */
10118    if (pds.password)
10119       ast_string_field_set(iaxs[callno], secret, pds.password);
10120    if (pds.key)
10121       ast_string_field_set(iaxs[callno], outkey, pds.key);
10122    /* Start the call going */
10123    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10124 
10125    return callno;
10126 }

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

Definition at line 3834 of file chan_iax2.c.

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

03835 {
03836    /* Returns where in "receive time" we are.  That is, how many ms
03837       since we received (or would have received) the frame with timestamp 0 */
03838    int ms;
03839 #ifdef IAXTESTS
03840    int jit;
03841 #endif /* IAXTESTS */
03842    /* Setup rxcore if necessary */
03843    if (ast_tvzero(p->rxcore)) {
03844       p->rxcore = ast_tvnow();
03845       if (option_debug && iaxdebug)
03846          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
03847                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
03848       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
03849 #if 1
03850       if (option_debug && iaxdebug)
03851          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
03852                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
03853 #endif
03854    }
03855 
03856    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
03857 #ifdef IAXTESTS
03858    if (test_jit) {
03859       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
03860          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
03861          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
03862             jit = -jit;
03863          ms += jit;
03864       }
03865    }
03866    if (test_late) {
03867       ms += test_late;
03868       test_late = 0;
03869    }
03870 #endif /* IAXTESTS */
03871    return ms;
03872 }

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

Definition at line 3705 of file chan_iax2.c.

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

Referenced by iax2_send(), and socket_process().

03706 {
03707    int ms;
03708    int voice = 0;
03709    int genuine = 0;
03710    int adjust;
03711    struct timeval *delivery = NULL;
03712 
03713 
03714    /* What sort of frame do we have?: voice is self-explanatory
03715       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
03716       non-genuine frames are CONTROL frames [ringing etc], DTMF
03717       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
03718       the others need a timestamp slaved to the voice frames so that they go in sequence
03719    */
03720    if (f) {
03721       if (f->frametype == AST_FRAME_VOICE) {
03722          voice = 1;
03723          delivery = &f->delivery;
03724       } else if (f->frametype == AST_FRAME_IAX) {
03725          genuine = 1;
03726       } else if (f->frametype == AST_FRAME_CNG) {
03727          p->notsilenttx = 0;  
03728       }
03729    }
03730    if (ast_tvzero(p->offset)) {
03731       gettimeofday(&p->offset, NULL);
03732       /* Round to nearest 20ms for nice looking traces */
03733       p->offset.tv_usec -= p->offset.tv_usec % 20000;
03734    }
03735    /* If the timestamp is specified, just send it as is */
03736    if (ts)
03737       return ts;
03738    /* If we have a time that the frame arrived, always use it to make our timestamp */
03739    if (delivery && !ast_tvzero(*delivery)) {
03740       ms = ast_tvdiff_ms(*delivery, p->offset);
03741       if (option_debug > 2 && iaxdebug)
03742          ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
03743    } else {
03744       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
03745       if (ms < 0)
03746          ms = 0;
03747       if (voice) {
03748          /* On a voice frame, use predicted values if appropriate */
03749          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
03750             /* Adjust our txcore, keeping voice and non-voice synchronized */
03751             /* AN EXPLANATION:
03752                When we send voice, we usually send "calculated" timestamps worked out
03753                on the basis of the number of samples sent. When we send other frames,
03754                we usually send timestamps worked out from the real clock.
03755                The problem is that they can tend to drift out of step because the 
03756                   source channel's clock and our clock may not be exactly at the same rate.
03757                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
03758                for this call.  Moving it adjusts timestamps for non-voice frames.
03759                We make the adjustment in the style of a moving average.  Each time we
03760                adjust p->offset by 10% of the difference between our clock-derived
03761                timestamp and the predicted timestamp.  That's why you see "10000"
03762                below even though IAX2 timestamps are in milliseconds.
03763                The use of a moving average avoids offset moving too radically.
03764                Generally, "adjust" roams back and forth around 0, with offset hardly
03765                changing at all.  But if a consistent different starts to develop it
03766                will be eliminated over the course of 10 frames (200-300msecs) 
03767             */
03768             adjust = (ms - p->nextpred);
03769             if (adjust < 0)
03770                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
03771             else if (adjust > 0)
03772                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
03773 
03774             if (!p->nextpred) {
03775                p->nextpred = ms; /*f->samples / 8;*/
03776                if (p->nextpred <= p->lastsent)
03777                   p->nextpred = p->lastsent + 3;
03778             }
03779             ms = p->nextpred;
03780          } else {
03781                 /* in this case, just use the actual
03782             * time, since we're either way off
03783             * (shouldn't happen), or we're  ending a
03784             * silent period -- and seed the next
03785             * predicted time.  Also, round ms to the
03786             * next multiple of frame size (so our
03787             * silent periods are multiples of
03788             * frame size too) */
03789 
03790             if (option_debug && iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
03791                ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
03792                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
03793 
03794             if (f->samples >= 8) /* check to make sure we dont core dump */
03795             {
03796                int diff = ms % (f->samples / 8);
03797                if (diff)
03798                    ms += f->samples/8 - diff;
03799             }
03800 
03801             p->nextpred = ms;
03802             p->notsilenttx = 1;
03803          }
03804       } else if ( f->frametype == AST_FRAME_VIDEO ) {
03805          /*
03806          * IAX2 draft 03 says that timestamps MUST be in order.
03807          * It does not say anything about several frames having the same timestamp
03808          * When transporting video, we can have a frame that spans multiple iax packets
03809          * (so called slices), so it would make sense to use the same timestamp for all of
03810          * them
03811          * We do want to make sure that frames don't go backwards though
03812          */
03813          if ( (unsigned int)ms < p->lastsent )
03814             ms = p->lastsent;
03815       } else {
03816          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
03817             it's a genuine frame */
03818          if (genuine) {
03819             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
03820             if (ms <= p->lastsent)
03821                ms = p->lastsent + 3;
03822          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
03823             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
03824             ms = p->lastsent + 3;
03825          }
03826       }
03827    }
03828    p->lastsent = ms;
03829    if (voice)
03830       p->nextpred = p->nextpred + f->samples / 8;
03831    return ms;
03832 }

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

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

03662 {
03663    unsigned long int mssincetx; /* unsigned to handle overflows */
03664    long int ms, pred;
03665 
03666    tpeer->trunkact = *tv;
03667    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03668    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03669       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03670       tpeer->txtrunktime = *tv;
03671       tpeer->lastsent = 999999;
03672    }
03673    /* Update last transmit time now */
03674    tpeer->lasttxtime = *tv;
03675    
03676    /* Calculate ms offset */
03677    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03678    /* Predict from last value */
03679    pred = tpeer->lastsent + sampms;
03680    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03681       ms = pred;
03682    
03683    /* We never send the same timestamp twice, so fudge a little if we must */
03684    if (ms == tpeer->lastsent)
03685       ms = tpeer->lastsent + 1;
03686    tpeer->lastsent = ms;
03687    return ms;
03688 }

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

Definition at line 4945 of file chan_iax2.c.

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

Referenced by socket_process().

04946 {
04947    /* Start pessimistic */
04948    int res = -1;
04949    int version = 2;
04950    struct iax2_user *user = NULL, *best = NULL;
04951    int bestscore = 0;
04952    int gotcapability = 0;
04953    struct ast_variable *v = NULL, *tmpvar = NULL;
04954    struct ao2_iterator i;
04955 
04956    if (!iaxs[callno])
04957       return res;
04958    if (ies->called_number)
04959       ast_string_field_set(iaxs[callno], exten, ies->called_number);
04960    if (ies->calling_number) {
04961       ast_shrink_phone_number(ies->calling_number);
04962       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
04963    }
04964    if (ies->calling_name)
04965       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
04966    if (ies->calling_ani)
04967       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
04968    if (ies->dnid)
04969       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
04970    if (ies->rdnis)
04971       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
04972    if (ies->called_context)
04973       ast_string_field_set(iaxs[callno], context, ies->called_context);
04974    if (ies->language)
04975       ast_string_field_set(iaxs[callno], language, ies->language);
04976    if (ies->username)
04977       ast_string_field_set(iaxs[callno], username, ies->username);
04978    if (ies->calling_ton > -1)
04979       iaxs[callno]->calling_ton = ies->calling_ton;
04980    if (ies->calling_tns > -1)
04981       iaxs[callno]->calling_tns = ies->calling_tns;
04982    if (ies->calling_pres > -1)
04983       iaxs[callno]->calling_pres = ies->calling_pres;
04984    if (ies->format)
04985       iaxs[callno]->peerformat = ies->format;
04986    if (ies->adsicpe)
04987       iaxs[callno]->peeradsicpe = ies->adsicpe;
04988    if (ies->capability) {
04989       gotcapability = 1;
04990       iaxs[callno]->peercapability = ies->capability;
04991    } 
04992    if (ies->version)
04993       version = ies->version;
04994 
04995    /* Use provided preferences until told otherwise for actual preferences */
04996    if(ies->codec_prefs) {
04997       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
04998       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
04999    }
05000 
05001    if (!gotcapability) 
05002       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
05003    if (version > IAX_PROTO_VERSION) {
05004       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
05005          ast_inet_ntoa(sin->sin_addr), version);
05006       return res;
05007    }
05008    /* Search the userlist for a compatible entry, and fill in the rest */
05009    i = ao2_iterator_init(users, 0);
05010    while ((user = ao2_iterator_next(&i))) {
05011       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
05012          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
05013          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
05014          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
05015               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
05016          if (!ast_strlen_zero(iaxs[callno]->username)) {
05017             /* Exact match, stop right now. */
05018             if (best)
05019                user_unref(best);
05020             best = user;
05021             break;
05022          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) {
05023             /* No required authentication */
05024             if (user->ha) {
05025                /* There was host authentication and we passed, bonus! */
05026                if (bestscore < 4) {
05027                   bestscore = 4;
05028                   if (best)
05029                      user_unref(best);
05030                   best = user;
05031                   continue;
05032                }
05033             } else {
05034                /* No host access, but no secret, either, not bad */
05035                if (bestscore < 3) {
05036                   bestscore = 3;
05037                   if (best)
05038                      user_unref(best);
05039                   best = user;
05040                   continue;
05041                }
05042             }
05043          } else {
05044             if (user->ha) {
05045                /* Authentication, but host access too, eh, it's something.. */
05046                if (bestscore < 2) {
05047                   bestscore = 2;
05048                   if (best)
05049                      user_unref(best);
05050                   best = user;
05051                   continue;
05052                }
05053             } else {
05054                /* Authentication and no host access...  This is our baseline */
05055                if (bestscore < 1) {
05056                   bestscore = 1;
05057                   if (best)
05058                      user_unref(best);
05059                   best = user;
05060                   continue;
05061                }
05062             }
05063          }
05064       }
05065       user_unref(user);
05066    }
05067    user = best;
05068    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
05069       user = realtime_user(iaxs[callno]->username, sin);
05070       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
05071           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
05072          user = user_unref(user);
05073       }
05074    }
05075    if (user) {
05076       /* We found our match (use the first) */
05077       /* copy vars */
05078       for (v = user->vars ; v ; v = v->next) {
05079          if((tmpvar = ast_variable_new(v->name, v->value))) {
05080             tmpvar->next = iaxs[callno]->vars; 
05081             iaxs[callno]->vars = tmpvar;
05082          }
05083       }
05084       /* If a max AUTHREQ restriction is in place, activate it */
05085       if (user->maxauthreq > 0)
05086          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
05087       iaxs[callno]->prefs = user->prefs;
05088       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
05089       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
05090       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
05091       iaxs[callno]->encmethods = user->encmethods;
05092       /* Store the requested username if not specified */
05093       if (ast_strlen_zero(iaxs[callno]->username))
05094          ast_string_field_set(iaxs[callno], username, user->name);
05095       /* Store whether this is a trunked call, too, of course, and move if appropriate */
05096       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
05097       iaxs[callno]->capability = user->capability;
05098       /* And use the default context */
05099       if (ast_strlen_zero(iaxs[callno]->context)) {
05100          if (user->contexts)
05101             ast_string_field_set(iaxs[callno], context, user->contexts->context);
05102          else
05103             ast_string_field_set(iaxs[callno], context, context);
05104       }
05105       /* And any input keys */
05106       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
05107       /* And the permitted authentication methods */
05108       iaxs[callno]->authmethods = user->authmethods;
05109       iaxs[callno]->adsi = user->adsi;
05110       /* If they have callerid, override the given caller id.  Always store the ANI */
05111       if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) {
05112          if (ast_test_flag(user, IAX_HASCALLERID)) {
05113             iaxs[callno]->calling_tns = 0;
05114             iaxs[callno]->calling_ton = 0;
05115             ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
05116             ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
05117             iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
05118          }
05119          if (ast_strlen_zero(iaxs[callno]->ani))
05120             ast_string_field_set(iaxs[callno], ani, user->cid_num);
05121       } else {
05122          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
05123       }
05124       if (!ast_strlen_zero(user->accountcode))
05125          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
05126       if (!ast_strlen_zero(user->mohinterpret))
05127          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
05128       if (!ast_strlen_zero(user->mohsuggest))
05129          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
05130       if (user->amaflags)
05131          iaxs[callno]->amaflags = user->amaflags;
05132       if (!ast_strlen_zero(user->language))
05133          ast_string_field_set(iaxs[callno], language, user->language);
05134       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
05135       /* Keep this check last */
05136       if (!ast_strlen_zero(user->dbsecret)) {
05137          char *family, *key=NULL;
05138          char buf[80];
05139          family = ast_strdupa(user->dbsecret);
05140          key = strchr(family, '/');
05141          if (key) {
05142             *key = '\0';
05143             key++;
05144          }
05145          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
05146             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
05147          else
05148             ast_string_field_set(iaxs[callno], secret, buf);
05149       } else
05150          ast_string_field_set(iaxs[callno], secret, user->secret);
05151       res = 0;
05152       user = user_unref(user);
05153    }
05154    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
05155    return res;
05156 }

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

Definition at line 6625 of file chan_iax2.c.

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

Referenced by socket_process().

06626 {
06627    unsigned int ourver;
06628    char rsi[80];
06629    snprintf(rsi, sizeof(rsi), "si-%s", si);
06630    if (iax_provision_version(&ourver, rsi, 1))
06631       return 0;
06632    if (option_debug)
06633       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06634    if (ourver != ver) 
06635       iax2_provision(sin, sockfd, NULL, rsi, 1);
06636    return 0;
06637 }

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

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

Referenced by peer_set_srcaddr().

08980 {
08981    int sd;
08982    int res;
08983    
08984    sd = socket(AF_INET, SOCK_DGRAM, 0);
08985    if (sd < 0) {
08986       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
08987       return -1;
08988    }
08989 
08990    res = bind(sd, sa, salen);
08991    if (res < 0) {
08992       if (option_debug)
08993          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
08994       close(sd);
08995       return 1;
08996    }
08997 
08998    close(sd);
08999    return 0;
09000 }

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

Definition at line 5635 of file chan_iax2.c.

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

Referenced by socket_process().

05636 {
05637    char exten[256] = "";
05638    int status = CACHE_FLAG_UNKNOWN;
05639    int expiry = iaxdefaultdpcache;
05640    int x;
05641    int matchmore = 0;
05642    struct iax2_dpcache *dp, *prev;
05643    
05644    if (ies->called_number)
05645       ast_copy_string(exten, ies->called_number, sizeof(exten));
05646 
05647    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05648       status = CACHE_FLAG_EXISTS;
05649    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05650       status = CACHE_FLAG_CANEXIST;
05651    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05652       status = CACHE_FLAG_NONEXISTENT;
05653 
05654    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05655       /* Don't really do anything with this */
05656    }
05657    if (ies->refresh)
05658       expiry = ies->refresh;
05659    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05660       matchmore = CACHE_FLAG_MATCHMORE;
05661    ast_mutex_lock(&dpcache_lock);
05662    prev = NULL;
05663    dp = pvt->dpentries;
05664    while(dp) {
05665       if (!strcmp(dp->exten, exten)) {
05666          /* Let them go */
05667          if (prev)
05668             prev->peer = dp->peer;
05669          else
05670             pvt->dpentries = dp->peer;
05671          dp->peer = NULL;
05672          dp->callno = 0;
05673          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05674          if (dp->flags & CACHE_FLAG_PENDING) {
05675             dp->flags &= ~CACHE_FLAG_PENDING;
05676             dp->flags |= status;
05677             dp->flags |= matchmore;
05678          }
05679          /* Wake up waiters */
05680          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05681             if (dp->waiters[x] > -1)
05682                write(dp->waiters[x], "asdf", 4);
05683       }
05684       prev = dp;
05685       dp = dp->peer;
05686    }
05687    ast_mutex_unlock(&dpcache_lock);
05688    return 0;
05689 }

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

Definition at line 2277 of file chan_iax2.c.

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

02278 {
02279    int which = 0;
02280    struct iax2_peer *peer;
02281    char *res = NULL;
02282    int wordlen = strlen(word);
02283    struct ao2_iterator i;
02284 
02285    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02286    if (pos != 3)
02287       return NULL;
02288 
02289    i = ao2_iterator_init(peers, 0);
02290    while ((peer = ao2_iterator_next(&i))) {
02291       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02292          res = ast_strdup(peer->name);
02293          peer_unref(peer);
02294          break;
02295       }
02296       peer_unref(peer);
02297    }
02298 
02299    return res;
02300 }

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

Definition at line 5691 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), iaxq, iaxs, ies, chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, TRANSFER_NONE, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, chan_iax2_pvt::videoformat, and chan_iax2_pvt::voiceformat.

Referenced by socket_process().

05692 {
05693    int peercallno = 0;
05694    struct chan_iax2_pvt *pvt = iaxs[callno];
05695    struct iax_frame *cur;
05696    jb_frame frame;
05697 
05698    if (ies->callno)
05699       peercallno = ies->callno;
05700 
05701    if (peercallno < 1) {
05702       ast_log(LOG_WARNING, "Invalid transfer request\n");
05703       return -1;
05704    }
05705    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05706    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05707    /* Reset sequence numbers */
05708    pvt->oseqno = 0;
05709    pvt->rseqno = 0;
05710    pvt->iseqno = 0;
05711    pvt->aseqno = 0;
05712    pvt->peercallno = peercallno;
05713    pvt->transferring = TRANSFER_NONE;
05714    pvt->svoiceformat = -1;
05715    pvt->voiceformat = 0;
05716    pvt->svideoformat = -1;
05717    pvt->videoformat = 0;
05718    pvt->transfercallno = -1;
05719    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05720    memset(&pvt->offset, 0, sizeof(pvt->offset));
05721    /* reset jitterbuffer */
05722    while(jb_getall(pvt->jb,&frame) == JB_OK)
05723       iax2_frame_free(frame.data);
05724    jb_reset(pvt->jb);
05725    pvt->lag = 0;
05726    pvt->last = 0;
05727    pvt->lastsent = 0;
05728    pvt->nextpred = 0;
05729    pvt->pingtime = DEFAULT_RETRY_TIME;
05730    AST_LIST_LOCK(&iaxq.queue);
05731    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05732       /* We must cancel any packets that would have been transmitted
05733          because now we're talking to someone new.  It's okay, they
05734          were transmitted to someone that didn't care anyway. */
05735       if (callno == cur->callno) 
05736          cur->retries = -1;
05737    }
05738    AST_LIST_UNLOCK(&iaxq.queue);
05739    return 0; 
05740 }

static unsigned char compress_subclass ( int  subclass  )  [static]

Definition at line 1036 of file chan_iax2.c.

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

Referenced by iax2_send(), and raw_hangup().

01037 {
01038    int x;
01039    int power=-1;
01040    /* If it's 128 or smaller, just return it */
01041    if (subclass < IAX_FLAG_SC_LOG)
01042       return subclass;
01043    /* Otherwise find its power */
01044    for (x = 0; x < IAX_MAX_SHIFT; x++) {
01045       if (subclass & (1 << x)) {
01046          if (power > -1) {
01047             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
01048             return 0;
01049          } else
01050             power = x;
01051       }
01052    }
01053    return power | IAX_FLAG_SC_LOG;
01054 }

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

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

06640 {
06641    jb_info stats;
06642    jb_getinfo(pvt->jb, &stats);
06643    
06644    memset(iep, 0, sizeof(*iep));
06645 
06646    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06647    if(stats.frames_in == 0) stats.frames_in = 1;
06648    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06649    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06650    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06651    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06652    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06653 }

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

Definition at line 2900 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ahp, ast_clear_flag, ast_codec_pref_convert(), ast_codec_pref_prepend(), ast_copy_flags, ast_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, key(), iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, create_addr_info::outkey, peer_unref(), create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.

02901 {
02902    struct ast_hostent ahp;
02903    struct hostent *hp;
02904    struct iax2_peer *peer;
02905    int res = -1;
02906    struct ast_codec_pref ourprefs;
02907 
02908    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
02909    cai->sockfd = defaultsockfd;
02910    cai->maxtime = 0;
02911    sin->sin_family = AF_INET;
02912 
02913    if (!(peer = find_peer(peername, 1))) {
02914       cai->found = 0;
02915 
02916       hp = ast_gethostbyname(peername, &ahp);
02917       if (hp) {
02918          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
02919          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
02920          /* use global iax prefs for unknown peer/user */
02921          /* But move the calling channel's native codec to the top of the preference list */
02922          memcpy(&ourprefs, &prefs, sizeof(ourprefs));
02923          if (c)
02924             ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
02925          ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
02926          return 0;
02927       } else {
02928          ast_log(LOG_WARNING, "No such host: %s\n", peername);
02929          return -1;
02930       }
02931    }
02932 
02933    cai->found = 1;
02934    
02935    /* if the peer has no address (current or default), return failure */
02936    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr))
02937       goto return_unref;
02938 
02939    /* if the peer is being monitored and is currently unreachable, return failure */
02940    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
02941       goto return_unref;
02942 
02943    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
02944    cai->maxtime = peer->maxms;
02945    cai->capability = peer->capability;
02946    cai->encmethods = peer->encmethods;
02947    cai->sockfd = peer->sockfd;
02948    cai->adsi = peer->adsi;
02949    memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
02950    /* Move the calling channel's native codec to the top of the preference list */
02951    if (c) {
02952       ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
02953       ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
02954    }
02955    ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
02956    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
02957    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
02958    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
02959    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
02960    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
02961    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
02962    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
02963    if (ast_strlen_zero(peer->dbsecret)) {
02964       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
02965    } else {
02966       char *family;
02967       char *key = NULL;
02968 
02969       family = ast_strdupa(peer->dbsecret);
02970       key = strchr(family, '/');
02971       if (key)
02972          *key++ = '\0';
02973       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
02974          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
02975          goto return_unref;
02976       }
02977    }
02978 
02979    if (peer->addr.sin_addr.s_addr) {
02980       sin->sin_addr = peer->addr.sin_addr;
02981       sin->sin_port = peer->addr.sin_port;
02982    } else {
02983       sin->sin_addr = peer->defaddr.sin_addr;
02984       sin->sin_port = peer->defaddr.sin_port;
02985    }
02986 
02987    res = 0;
02988 
02989 return_unref:
02990    peer_unref(peer);
02991 
02992    return res;
02993 }

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

Definition at line 4020 of file chan_iax2.c.

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

Referenced by decrypt_frame().

04021 {
04022    int padding;
04023    unsigned char *workspace;
04024 
04025    workspace = alloca(*datalen);
04026    memset(f, 0, sizeof(*f));
04027    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04028       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04029       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04030          return -1;
04031       /* Decrypt */
04032       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04033 
04034       padding = 16 + (workspace[15] & 0xf);
04035       if (option_debug && iaxdebug)
04036          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04037       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04038          return -1;
04039 
04040       *datalen -= padding;
04041       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04042       f->frametype = fh->type;
04043       if (f->frametype == AST_FRAME_VIDEO) {
04044          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04045       } else {
04046          f->subclass = uncompress_subclass(fh->csub);
04047       }
04048    } else {
04049       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04050       if (option_debug && iaxdebug)
04051          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04052       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04053          return -1;
04054       /* Decrypt */
04055       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04056       padding = 16 + (workspace[15] & 0x0f);
04057       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04058          return -1;
04059       *datalen -= padding;
04060       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04061    }
04062    return 0;
04063 }

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

Definition at line 4106 of file chan_iax2.c.

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

Referenced by socket_process().

04107 {
04108    int res=-1;
04109    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04110       /* Search for possible keys, given secrets */
04111       struct MD5Context md5;
04112       unsigned char digest[16];
04113       char *tmppw, *stringp;
04114       
04115       tmppw = ast_strdupa(iaxs[callno]->secret);
04116       stringp = tmppw;
04117       while ((tmppw = strsep(&stringp, ";"))) {
04118          MD5Init(&md5);
04119          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04120          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04121          MD5Final(digest, &md5);
04122          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04123          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04124          if (!res) {
04125             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04126             break;
04127          }
04128       }
04129    } else 
04130       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04131    return res;
04132 }

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

06702 {
06703    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06704    struct ast_iax2_full_hdr *fh, *cur_fh;
06705 
06706    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06707       return;
06708 
06709    pkt_buf->len = from_here->buf_len;
06710    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06711 
06712    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06713    ast_mutex_lock(&to_here->lock);
06714    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06715       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06716       if (fh->oseqno < cur_fh->oseqno) {
06717          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06718          break;
06719       }
06720    }
06721    AST_LIST_TRAVERSE_SAFE_END
06722 
06723    if (!cur_pkt_buf)
06724       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06725    
06726    ast_mutex_unlock(&to_here->lock);
06727 }

static void delete_users ( void   )  [static]

Definition at line 9571 of file chan_iax2.c.

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

09572 {
09573    struct iax2_registry *reg;
09574 
09575    ao2_callback(users, 0, user_delme_cb, NULL);
09576 
09577    AST_LIST_LOCK(&registrations);
09578    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09579       ast_sched_del(sched, reg->expire);
09580       if (reg->callno) {
09581          ast_mutex_lock(&iaxsl[reg->callno]);
09582          if (iaxs[reg->callno]) {
09583             iaxs[reg->callno]->reg = NULL;
09584             iax2_destroy(reg->callno);
09585          }
09586          ast_mutex_unlock(&iaxsl[reg->callno]);
09587       }
09588       if (reg->dnsmgr)
09589          ast_dnsmgr_release(reg->dnsmgr);
09590       free(reg);
09591    }
09592    AST_LIST_UNLOCK(&registrations);
09593 
09594    ao2_callback(peers, 0, peer_delme_cb, NULL);
09595 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1524 of file chan_iax2.c.

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

Referenced by reload_firmware().

01525 {
01526    /* Close firmware */
01527    if (cur->fwh) {
01528       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01529    }
01530    close(cur->fd);
01531    free(cur);
01532 }

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

Definition at line 6473 of file chan_iax2.c.

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

Referenced by dp_lookup_thread(), and socket_process().

06474 {
06475    unsigned short dpstatus = 0;
06476    struct iax_ie_data ied1;
06477    int mm;
06478 
06479    memset(&ied1, 0, sizeof(ied1));
06480    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06481    /* Must be started */
06482    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06483       dpstatus = IAX_DPSTATUS_EXISTS;
06484    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06485       dpstatus = IAX_DPSTATUS_CANEXIST;
06486    } else {
06487       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06488    }
06489    if (ast_ignore_pattern(context, callednum))
06490       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06491    if (mm)
06492       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06493    if (!skiplock)
06494       ast_mutex_lock(&iaxsl[callno]);
06495    if (iaxs[callno]) {
06496       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06497       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06498       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06499       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06500    }
06501    if (!skiplock)
06502       ast_mutex_unlock(&iaxsl[callno]);
06503 }

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

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

06506 {
06507    /* Look up for dpreq */
06508    struct dpreq_data *dpr = data;
06509    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06510    if (dpr->callerid)
06511       free(dpr->callerid);
06512    free(dpr);
06513    return NULL;
06514 }

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

Definition at line 4065 of file chan_iax2.c.

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

Referenced by iax2_send().

04066 {
04067    int padding;
04068    unsigned char *workspace;
04069    workspace = alloca(*datalen + 32);
04070    if (!workspace)
04071       return -1;
04072    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04073       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04074       if (option_debug && iaxdebug)
04075          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04076       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04077       padding = 16 + (padding & 0xf);
04078       memcpy(workspace, poo, padding);
04079       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04080       workspace[15] &= 0xf0;
04081       workspace[15] |= (padding & 0xf);
04082       if (option_debug && iaxdebug)
04083          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]);
04084       *datalen += padding;
04085       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04086       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04087          memcpy(poo, workspace + *datalen - 32, 32);
04088    } else {
04089       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04090       if (option_debug && iaxdebug)
04091          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04092       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04093       padding = 16 + (padding & 0xf);
04094       memcpy(workspace, poo, padding);
04095       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04096       workspace[15] &= 0xf0;
04097       workspace[15] |= (padding & 0x0f);
04098       *datalen += padding;
04099       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04100       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04101          memcpy(poo, workspace + *datalen - 32, 32);
04102    }
04103    return 0;
04104 }

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

Definition at line 5922 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

05923 {
05924 #ifdef SCHED_MULTITHREADED
05925    if (schedule_action(__expire_registry, data))
05926 #endif      
05927       __expire_registry(data);
05928    return 0;
05929 }

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

Definition at line 10128 of file chan_iax2.c.

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

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

10129 {
10130    struct iax2_dpcache *dp, *prev = NULL, *next;
10131    struct timeval tv;
10132    int x;
10133    int com[2];
10134    int timeout;
10135    int old=0;
10136    int outfd;
10137    int abort;
10138    int callno;
10139    struct ast_channel *c;
10140    struct ast_frame *f;
10141    gettimeofday(&tv, NULL);
10142    dp = dpcache;
10143    while(dp) {
10144       next = dp->next;
10145       /* Expire old caches */
10146       if (ast_tvcmp(tv, dp->expiry) > 0) {
10147             /* It's expired, let it disappear */
10148             if (prev)
10149                prev->next = dp->next;
10150             else
10151                dpcache = dp->next;
10152             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
10153                /* Free memory and go again */
10154                free(dp);
10155             } else {
10156                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);
10157             }
10158             dp = next;
10159             continue;
10160       }
10161       /* We found an entry that matches us! */
10162       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
10163          break;
10164       prev = dp;
10165       dp = next;
10166    }
10167    if (!dp) {
10168       /* No matching entry.  Create a new one. */
10169       /* First, can we make a callno? */
10170       callno = cache_get_callno_locked(data);
10171       if (callno < 0) {
10172          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
10173          return NULL;
10174       }
10175       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
10176          ast_mutex_unlock(&iaxsl[callno]);
10177          return NULL;
10178       }
10179       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
10180       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
10181       gettimeofday(&dp->expiry, NULL);
10182       dp->orig = dp->expiry;
10183       /* Expires in 30 mins by default */
10184       dp->expiry.tv_sec += iaxdefaultdpcache;
10185       dp->next = dpcache;
10186       dp->flags = CACHE_FLAG_PENDING;
10187       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10188          dp->waiters[x] = -1;
10189       dpcache = dp;
10190       dp->peer = iaxs[callno]->dpentries;
10191       iaxs[callno]->dpentries = dp;
10192       /* Send the request if we're already up */
10193       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
10194          iax2_dprequest(dp, callno);
10195       ast_mutex_unlock(&iaxsl[callno]);
10196    }
10197    /* By here we must have a dp */
10198    if (dp->flags & CACHE_FLAG_PENDING) {
10199       /* Okay, here it starts to get nasty.  We need a pipe now to wait
10200          for a reply to come back so long as it's pending */
10201       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
10202          /* Find an empty slot */
10203          if (dp->waiters[x] < 0)
10204             break;
10205       }
10206       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
10207          ast_log(LOG_WARNING, "No more waiter positions available\n");
10208          return NULL;
10209       }
10210       if (pipe(com)) {
10211          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
10212          return NULL;
10213       }
10214       dp->waiters[x] = com[1];
10215       /* Okay, now we wait */
10216       timeout = iaxdefaulttimeout * 1000;
10217       /* Temporarily unlock */
10218       ast_mutex_unlock(&dpcache_lock);
10219       /* Defer any dtmf */
10220       if (chan)
10221          old = ast_channel_defer_dtmf(chan);
10222       abort = 0;
10223       while(timeout) {
10224          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
10225          if (outfd > -1) {
10226             break;
10227          }
10228          if (c) {
10229             f = ast_read(c);
10230             if (f)
10231                ast_frfree(f);
10232             else {
10233                /* Got hung up on, abort! */
10234                break;
10235                abort = 1;
10236             }
10237          }
10238       }
10239       if (!timeout) {
10240          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
10241       }
10242       ast_mutex_lock(&dpcache_lock);
10243       dp->waiters[x] = -1;
10244       close(com[1]);
10245       close(com[0]);
10246       if (abort) {
10247          /* Don't interpret anything, just abort.  Not sure what th epoint
10248            of undeferring dtmf on a hung up channel is but hey whatever */
10249          if (!old && chan)
10250             ast_channel_undefer_dtmf(chan);
10251          return NULL;
10252       }
10253       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
10254          /* Now to do non-independent analysis the results of our wait */
10255          if (dp->flags & CACHE_FLAG_PENDING) {
10256             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
10257                pending.  Don't let it take as long to timeout. */
10258             dp->flags &= ~CACHE_FLAG_PENDING;
10259             dp->flags |= CACHE_FLAG_TIMEOUT;
10260             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
10261                systems without leaving it unavailable once the server comes back online */
10262             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
10263             for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10264                if (dp->waiters[x] > -1)
10265                   write(dp->waiters[x], "asdf", 4);
10266          }
10267       }
10268       /* Our caller will obtain the rest */
10269       if (!old && chan)
10270          ast_channel_undefer_dtmf(chan);
10271    }
10272    return dp;  
10273 }

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

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

Definition at line 1339 of file chan_iax2.c.

References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, globalflags, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, LOG_DEBUG, LOG_WARNING, match(), MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, sched, send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, TRUNK_CALL_START, and update_max_nontrunk().

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

01340 {
01341    int res = 0;
01342    int x;
01343    struct timeval now;
01344    char host[80];
01345 
01346    if (new <= NEW_ALLOW) {
01347       /* Look for an existing connection first */
01348       for (x=1;(res < 1) && (x<maxnontrunkcall);x++) {
01349          ast_mutex_lock(&iaxsl[x]);
01350          if (iaxs[x]) {
01351             /* Look for an exact match */
01352             if (match(sin, callno, dcallno, iaxs[x])) {
01353                res = x;
01354             }
01355          }
01356          ast_mutex_unlock(&iaxsl[x]);
01357       }
01358       for (x=TRUNK_CALL_START;(res < 1) && (x<maxtrunkcall);x++) {
01359          ast_mutex_lock(&iaxsl[x]);
01360          if (iaxs[x]) {
01361             /* Look for an exact match */
01362             if (match(sin, callno, dcallno, iaxs[x])) {
01363                res = x;
01364             }
01365          }
01366          ast_mutex_unlock(&iaxsl[x]);
01367       }
01368    }
01369    if ((res < 1) && (new >= NEW_ALLOW)) {
01370       /* It may seem odd that we look through the peer list for a name for
01371        * this *incoming* call.  Well, it is weird.  However, users don't
01372        * have an IP address/port number that we can match against.  So,
01373        * this is just checking for a peer that has that IP/port and
01374        * assuming that we have a user of the same name.  This isn't always
01375        * correct, but it will be changed if needed after authentication. */
01376       if (!iax2_getpeername(*sin, host, sizeof(host)))
01377          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01378       gettimeofday(&now, NULL);
01379       for (x=1;x<TRUNK_CALL_START;x++) {
01380          /* Find first unused call number that hasn't been used in a while */
01381          ast_mutex_lock(&iaxsl[x]);
01382          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) break;
01383          ast_mutex_unlock(&iaxsl[x]);
01384       }
01385       /* We've still got lock held if we found a spot */
01386       if (x >= TRUNK_CALL_START) {
01387          ast_log(LOG_WARNING, "No more space\n");
01388          return 0;
01389       }
01390       iaxs[x] = new_iax(sin, host);
01391       update_max_nontrunk();
01392       if (iaxs[x]) {
01393          if (option_debug && iaxdebug)
01394             ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
01395          iaxs[x]->sockfd = sockfd;
01396          iaxs[x]->addr.sin_port = sin->sin_port;
01397          iaxs[x]->addr.sin_family = sin->sin_family;
01398          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01399          iaxs[x]->peercallno = callno;
01400          iaxs[x]->callno = x;
01401          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01402          iaxs[x]->expiry = min_reg_expire;
01403          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01404          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01405          iaxs[x]->amaflags = amaflags;
01406          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01407          
01408          ast_string_field_set(iaxs[x], accountcode, accountcode);
01409          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01410          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01411       } else {
01412          ast_log(LOG_WARNING, "Out of resources\n");
01413          ast_mutex_unlock(&iaxsl[x]);
01414          return 0;
01415       }
01416       ast_mutex_unlock(&iaxsl[x]);
01417       res = x;
01418    }
01419    return res;
01420 }

static struct iax2_thread* find_idle_thread ( void   )  [static]

Definition at line 892 of file chan_iax2.c.

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

Referenced by __schedule_action(), and socket_read().

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

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

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

Definition at line 1114 of file chan_iax2.c.

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

01115 {
01116    struct iax2_peer *peer = NULL;
01117    struct iax2_peer tmp_peer = {
01118       .name = name,
01119    };
01120 
01121    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
01122 
01123    /* Now go for realtime if applicable */
01124    if(!peer && realtime)
01125       peer = realtime_peer(name, NULL);
01126 
01127    return peer;
01128 }

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

Definition at line 3874 of file chan_iax2.c.

References iax2_trunk_peer::addr, ast_mutex_lock(), inaddrcmp(), iax2_trunk_peer::lock, iax2_trunk_peer::next, and tpeers.

Referenced by iax2_trunk_queue(), and socket_process().

03875 {
03876    struct iax2_trunk_peer *tpeer;
03877    
03878    /* Finds and locks trunk peer */
03879    ast_mutex_lock(&tpeerlock);
03880    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
03881       /* We don't lock here because tpeer->addr *never* changes */
03882       if (!inaddrcmp(&tpeer->addr, sin)) {
03883          ast_mutex_lock(&tpeer->lock);
03884          break;
03885       }
03886    }
03887    if (!tpeer) {
03888       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
03889          ast_mutex_init(&tpeer->lock);
03890          tpeer->lastsent = 9999;
03891          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
03892          tpeer->trunkact = ast_tvnow();
03893          ast_mutex_lock(&tpeer->lock);
03894          tpeer->next = tpeers;
03895          tpeer->sockfd = fd;
03896          tpeers = tpeer;
03897 #ifdef SO_NO_CHECK
03898          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
03899 #endif
03900          if (option_debug)
03901             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
03902       }
03903    }
03904    ast_mutex_unlock(&tpeerlock);
03905    return tpeer;
03906 }

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

Definition at line 3690 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03691 {
03692    long ms; /* NOT unsigned */
03693    if (ast_tvzero(iaxs[callno]->rxcore)) {
03694       /* Initialize rxcore time if appropriate */
03695       gettimeofday(&iaxs[callno]->rxcore, NULL);
03696       /* Round to nearest 20ms so traces look pretty */
03697       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03698    }
03699    /* Calculate difference between trunk and channel */
03700    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03701    /* Return as the sum of trunk time and the difference between trunk and real time */
03702    return ms + ts;
03703 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8736 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08737 {
08738    struct iax2_context *conl;
08739    while(con) {
08740       conl = con;
08741       con = con->next;
08742       free(conl);
08743    }
08744 }

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

Definition at line 10397 of file chan_iax2.c.

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

10398 {
10399    struct iax2_peer *peer;
10400    char *peername, *colname;
10401 
10402    peername = ast_strdupa(data);
10403 
10404    /* if our channel, return the IP address of the endpoint of current channel */
10405    if (!strcmp(peername,"CURRENTCHANNEL")) {
10406            unsigned short callno;
10407       if (chan->tech != &iax2_tech)
10408          return -1;
10409       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10410       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10411       return 0;
10412    }
10413 
10414    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10415       *colname++ = '\0';
10416    else if ((colname = strchr(peername, '|')))
10417       *colname++ = '\0';
10418    else
10419       colname = "ip";
10420 
10421    if (!(peer = find_peer(peername, 1)))
10422       return -1;
10423 
10424    if (!strcasecmp(colname, "ip")) {
10425       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10426    } else  if (!strcasecmp(colname, "status")) {
10427       peer_status(peer, buf, len); 
10428    } else  if (!strcasecmp(colname, "mailbox")) {
10429       ast_copy_string(buf, peer->mailbox, len);
10430    } else  if (!strcasecmp(colname, "context")) {
10431       ast_copy_string(buf, peer->context, len);
10432    } else  if (!strcasecmp(colname, "expire")) {
10433       snprintf(buf, len, "%d", peer->expire);
10434    } else  if (!strcasecmp(colname, "dynamic")) {
10435       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10436    } else  if (!strcasecmp(colname, "callerid_name")) {
10437       ast_copy_string(buf, peer->cid_name, len);
10438    } else  if (!strcasecmp(colname, "callerid_num")) {
10439       ast_copy_string(buf, peer->cid_num, len);
10440    } else  if (!strcasecmp(colname, "codecs")) {
10441       ast_getformatname_multiple(buf, len -1, peer->capability);
10442    } else  if (!strncasecmp(colname, "codec[", 6)) {
10443       char *codecnum, *ptr;
10444       int index = 0, codec = 0;
10445       
10446       codecnum = strchr(colname, '[');
10447       *codecnum = '\0';
10448       codecnum++;
10449       if ((ptr = strchr(codecnum, ']'))) {
10450          *ptr = '\0';
10451       }
10452       index = atoi(codecnum);
10453       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10454          ast_copy_string(buf, ast_getformatname(codec), len);
10455       }
10456    }
10457 
10458    peer_unref(peer);
10459 
10460    return 0;
10461 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 8963 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

08964 {
08965    int methods = 0;
08966    if (strstr(value, "rsa"))
08967       methods |= IAX_AUTH_RSA;
08968    if (strstr(value, "md5"))
08969       methods |= IAX_AUTH_MD5;
08970    if (strstr(value, "plaintext"))
08971       methods |= IAX_AUTH_PLAINTEXT;
08972    return methods;
08973 }

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

Definition at line 1001 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

01002 {
01003    int e;
01004    if (!strcasecmp(s, "aes128"))
01005       e = IAX_ENCRYPT_AES128;
01006    else if (ast_true(s))
01007       e = IAX_ENCRYPT_AES128;
01008    else
01009       e = 0;
01010    return e;
01011 }

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

Definition at line 2514 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02515 {
02516 #ifdef SCHED_MULTITHREADED
02517    if (schedule_action(__get_from_jb, data))
02518 #endif      
02519       __get_from_jb(data);
02520    return 0;
02521 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6671 of file chan_iax2.c.

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

06672 {
06673    struct iax2_pkt_buf *pkt_buf;
06674 
06675    ast_mutex_lock(&thread->lock);
06676 
06677    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06678       ast_mutex_unlock(&thread->lock);
06679 
06680       thread->buf = pkt_buf->buf;
06681       thread->buf_len = pkt_buf->len;
06682       thread->buf_size = pkt_buf->len + 1;
06683       
06684       socket_process(thread);
06685 
06686       thread->buf = NULL;
06687       ast_free(pkt_buf);
06688 
06689       ast_mutex_lock(&thread->lock);
06690    }
06691 
06692    ast_mutex_unlock(&thread->lock);
06693 }

static int handle_error ( void   )  [static]

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

01813 {
01814    /* XXX Ideally we should figure out why an error occured and then abort those
01815       rather than continuing to try.  Unfortunately, the published interface does
01816       not seem to work XXX */
01817 #if 0
01818    struct sockaddr_in *sin;
01819    int res;
01820    struct msghdr m;
01821    struct sock_extended_err e;
01822    m.msg_name = NULL;
01823    m.msg_namelen = 0;
01824    m.msg_iov = NULL;
01825    m.msg_control = &e;
01826    m.msg_controllen = sizeof(e);
01827    m.msg_flags = 0;
01828    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
01829    if (res < 0)
01830       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
01831    else {
01832       if (m.msg_controllen) {
01833          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
01834          if (sin) 
01835             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
01836          else
01837             ast_log(LOG_WARNING, "No address detected??\n");
01838       } else {
01839          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
01840       }
01841    }
01842 #endif
01843    return 0;
01844 }

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

Acknowledgment received for OUR registration.

Definition at line 5743 of file chan_iax2.c.

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

Referenced by socket_process().

05744 {
05745    struct iax2_registry *reg;
05746    /* Start pessimistic */
05747    char peer[256] = "";
05748    char msgstatus[60];
05749    int refresh = 60;
05750    char ourip[256] = "<Unspecified>";
05751    struct sockaddr_in oldus;
05752    struct sockaddr_in us;
05753    int oldmsgs;
05754 
05755    memset(&us, 0, sizeof(us));
05756    if (ies->apparent_addr)
05757       bcopy(ies->apparent_addr, &us, sizeof(us));
05758    if (ies->username)
05759       ast_copy_string(peer, ies->username, sizeof(peer));
05760    if (ies->refresh)
05761       refresh = ies->refresh;
05762    if (ies->calling_number) {
05763       /* We don't do anything with it really, but maybe we should */
05764    }
05765    reg = iaxs[callno]->reg;
05766    if (!reg) {
05767       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05768       return -1;
05769    }
05770    memcpy(&oldus, &reg->us, sizeof(oldus));
05771    oldmsgs = reg->messages;
05772    if (inaddrcmp(&reg->addr, sin)) {
05773       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05774       return -1;
05775    }
05776    memcpy(&reg->us, &us, sizeof(reg->us));
05777    if (ies->msgcount >= 0)
05778       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05779    /* always refresh the registration at the interval requested by the server
05780       we are registering to
05781    */
05782    reg->refresh = refresh;
05783    AST_SCHED_DEL(sched, reg->expire);
05784    reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05785    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05786       if (option_verbose > 2) {
05787          if (reg->messages > 255)
05788             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
05789          else if (reg->messages > 1)
05790             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
05791          else if (reg->messages > 0)
05792             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
05793          else
05794             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
05795          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05796          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
05797       }
05798       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
05799    }
05800    reg->regstate = REG_STATE_REGISTERED;
05801    return 0;
05802 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3511 of file chan_iax2.c.

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

03512 {
03513    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03514    if (option_debug)
03515       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03516    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03517 }

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

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

03362 {
03363    struct ast_channel *cs[3];
03364    struct ast_channel *who, *other;
03365    int to = -1;
03366    int res = -1;
03367    int transferstarted=0;
03368    struct ast_frame *f;
03369    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03370    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03371    struct timeval waittimer = {0, 0}, tv;
03372 
03373    lock_both(callno0, callno1);
03374    if (!iaxs[callno0] || !iaxs[callno1]) {
03375       unlock_both(callno0, callno1);
03376       return AST_BRIDGE_FAILED;
03377    }
03378    /* Put them in native bridge mode */
03379    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
03380       iaxs[callno0]->bridgecallno = callno1;
03381       iaxs[callno1]->bridgecallno = callno0;
03382    }
03383    unlock_both(callno0, callno1);
03384 
03385    /* If not, try to bridge until we can execute a transfer, if we can */
03386    cs[0] = c0;
03387    cs[1] = c1;
03388    for (/* ever */;;) {
03389       /* Check in case we got masqueraded into */
03390       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
03391          if (option_verbose > 2)
03392             ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
03393          /* Remove from native mode */
03394          if (c0->tech == &iax2_tech) {
03395             ast_mutex_lock(&iaxsl[callno0]);
03396             iaxs[callno0]->bridgecallno = 0;
03397             ast_mutex_unlock(&iaxsl[callno0]);
03398          }
03399          if (c1->tech == &iax2_tech) {
03400             ast_mutex_lock(&iaxsl[callno1]);
03401             iaxs[callno1]->bridgecallno = 0;
03402             ast_mutex_unlock(&iaxsl[callno1]);
03403          }
03404          return AST_BRIDGE_FAILED_NOWARN;
03405       }
03406       if (c0->nativeformats != c1->nativeformats) {
03407          if (option_verbose > 2) {
03408             char buf0[255];
03409             char buf1[255];
03410             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
03411             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
03412             ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
03413          }
03414          /* Remove from native mode */
03415          lock_both(callno0, callno1);
03416          if (iaxs[callno0])
03417             iaxs[callno0]->bridgecallno = 0;
03418          if (iaxs[callno1])
03419             iaxs[callno1]->bridgecallno = 0;
03420          unlock_both(callno0, callno1);
03421          return AST_BRIDGE_FAILED_NOWARN;
03422       }
03423       /* check if transfered and if we really want native bridging */
03424       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
03425          /* Try the transfer */
03426          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
03427                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
03428             ast_log(LOG_WARNING, "Unable to start the transfer\n");
03429          transferstarted = 1;
03430       }
03431       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
03432          /* Call has been transferred.  We're no longer involved */
03433          gettimeofday(&tv, NULL);
03434          if (ast_tvzero(waittimer)) {
03435             waittimer = tv;
03436          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
03437             c0->_softhangup |= AST_SOFTHANGUP_DEV;
03438             c1->_softhangup |= AST_SOFTHANGUP_DEV;
03439             *fo = NULL;
03440             *rc = c0;
03441             res = AST_BRIDGE_COMPLETE;
03442             break;
03443          }
03444       }
03445       to = 1000;
03446       who = ast_waitfor_n(cs, 2, &to);
03447       if (timeoutms > -1) {
03448          timeoutms -= (1000 - to);
03449          if (timeoutms < 0)
03450             timeoutms = 0;
03451       }
03452       if (!who) {
03453          if (!timeoutms) {
03454             res = AST_BRIDGE_RETRY;
03455             break;
03456          }
03457          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03458             res = AST_BRIDGE_FAILED;
03459             break;
03460          }
03461          continue;
03462       }
03463       f = ast_read(who);
03464       if (!f) {
03465          *fo = NULL;
03466          *rc = who;
03467          res = AST_BRIDGE_COMPLETE;
03468          break;
03469       }
03470       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03471          *fo = f;
03472          *rc = who;
03473          res =  AST_BRIDGE_COMPLETE;
03474          break;
03475       }
03476       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
03477       if ((f->frametype == AST_FRAME_VOICE) ||
03478           (f->frametype == AST_FRAME_TEXT) ||
03479           (f->frametype == AST_FRAME_VIDEO) || 
03480           (f->frametype == AST_FRAME_IMAGE) ||
03481           (f->frametype == AST_FRAME_DTMF)) {
03482          /* monitored dtmf take out of the bridge.
03483           * check if we monitor the specific source.
03484           */
03485          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
03486          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
03487             *rc = who;
03488             *fo = f;
03489             res = AST_BRIDGE_COMPLETE;
03490             /* Remove from native mode */
03491             break;
03492          }
03493          /* everything else goes to the other side */
03494          ast_write(other, f);
03495       }
03496       ast_frfree(f);
03497       /* Swap who gets priority */
03498       cs[2] = cs[0];
03499       cs[0] = cs[1];
03500       cs[1] = cs[2];
03501    }
03502    lock_both(callno0, callno1);
03503    if(iaxs[callno0])
03504       iaxs[callno0]->bridgecallno = 0;
03505    if(iaxs[callno1])
03506       iaxs[callno1]->bridgecallno = 0;
03507    unlock_both(callno0, callno1);
03508    return res;
03509 }

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

Definition at line 3105 of file chan_iax2.c.

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

03106 {
03107    struct sockaddr_in sin;
03108    char *l=NULL, *n=NULL, *tmpstr;
03109    struct iax_ie_data ied;
03110    char *defaultrdest = "s";
03111    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03112    struct parsed_dial_string pds;
03113    struct create_addr_info cai;
03114 
03115    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
03116       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
03117       return -1;
03118    }
03119 
03120    memset(&cai, 0, sizeof(cai));
03121    cai.encmethods = iax2_encryption;
03122 
03123    memset(&pds, 0, sizeof(pds));
03124    tmpstr = ast_strdupa(dest);
03125    parse_dial_string(tmpstr, &pds);
03126 
03127    if (ast_strlen_zero(pds.peer)) {
03128       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest);
03129       return -1;
03130    }
03131 
03132    if (!pds.exten)
03133       pds.exten = defaultrdest;
03134 
03135    if (create_addr(pds.peer, c, &sin, &cai)) {
03136       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
03137       return -1;
03138    }
03139 
03140    if (!pds.username && !ast_strlen_zero(cai.username))
03141       pds.username = cai.username;
03142    if (!pds.password && !ast_strlen_zero(cai.secret))
03143       pds.password = cai.secret;
03144    if (!pds.key && !ast_strlen_zero(cai.outkey))
03145       pds.key = cai.outkey;
03146    if (!pds.context && !ast_strlen_zero(cai.peercontext))
03147       pds.context = cai.peercontext;
03148 
03149    /* Keep track of the context for outgoing calls too */
03150    ast_copy_string(c->context, cai.context, sizeof(c->context));
03151 
03152    if (pds.port)
03153       sin.sin_port = htons(atoi(pds.port));
03154 
03155    l = c->cid.cid_num;
03156    n = c->cid.cid_name;
03157 
03158    /* Now build request */ 
03159    memset(&ied, 0, sizeof(ied));
03160 
03161    /* On new call, first IE MUST be IAX version of caller */
03162    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
03163    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
03164    if (pds.options && strchr(pds.options, 'a')) {
03165       /* Request auto answer */
03166       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
03167    }
03168 
03169    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
03170 
03171    if (l) {
03172       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
03173       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03174    } else {
03175       if (n)
03176          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03177       else
03178          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
03179    }
03180 
03181    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
03182    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
03183 
03184    if (n)
03185       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
03186    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
03187       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
03188 
03189    if (!ast_strlen_zero(c->language))
03190       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
03191    if (!ast_strlen_zero(c->cid.cid_dnid))
03192       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
03193    if (!ast_strlen_zero(c->cid.cid_rdnis))
03194       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
03195 
03196    if (pds.context)
03197       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
03198 
03199    if (pds.username)
03200       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
03201 
03202    if (cai.encmethods)
03203       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
03204 
03205    ast_mutex_lock(&iaxsl[callno]);
03206 
03207    if (!ast_strlen_zero(c->context))
03208       ast_string_field_set(iaxs[callno], context, c->context);
03209 
03210    if (pds.username)
03211       ast_string_field_set(iaxs[callno], username, pds.username);
03212 
03213    iaxs[callno]->encmethods = cai.encmethods;
03214 
03215    iaxs[callno]->adsi = cai.adsi;
03216    
03217    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
03218    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
03219 
03220    if (pds.key)
03221       ast_string_field_set(iaxs[callno], outkey, pds.key);
03222    if (pds.password)
03223       ast_string_field_set(iaxs[callno], secret, pds.password);
03224 
03225    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
03226    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
03227    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
03228    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
03229 
03230    if (iaxs[callno]->maxtime) {
03231       /* Initialize pingtime and auto-congest time */
03232       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
03233       iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
03234    } else if (autokill) {
03235       iaxs[callno]->pingtime = autokill / 2;
03236       iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
03237    }
03238 
03239    /* send the command using the appropriate socket for this peer */
03240    iaxs[callno]->sockfd = cai.sockfd;
03241 
03242    /* Transmit the string in a "NEW" request */
03243    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
03244 
03245    ast_mutex_unlock(&iaxsl[callno]);
03246    ast_setstate(c, AST_STATE_RINGING);
03247    
03248    return 0;
03249 }

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

10300 {
10301    int res = 0;
10302    struct iax2_dpcache *dp;
10303 #if 0
10304    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10305 #endif
10306    if ((priority != 1) && (priority != 2))
10307       return 0;
10308    ast_mutex_lock(&dpcache_lock);
10309    dp = find_cache(chan, data, context, exten, priority);
10310    if (dp) {
10311       if (dp->flags & CACHE_FLAG_CANEXIST)
10312          res= 1;
10313    }
10314    ast_mutex_unlock(&dpcache_lock);
10315    if (!dp) {
10316       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10317    }
10318    return res;
10319 }

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

Definition at line 3017 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03018 {
03019    time_t t;
03020    struct tm tm;
03021    unsigned int tmp;
03022    time(&t);
03023    if (!ast_strlen_zero(tz))
03024       ast_localtime(&t, &tm, tz);
03025    else
03026       ast_localtime(&t, &tm, NULL);
03027    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03028    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03029    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03030    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03031    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03032    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03033    return tmp;
03034 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1951 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), ast_set_flag, ast_string_field_free_memory, ast_variables_destroy(), iax2_registry::callno, chan_iax2_pvt::callno, iax_frame::callno, jb_frame::data, free, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, iaxq, iaxs, iaxsl, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, ast_channel::lock, LOG_NOTICE, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, update_max_trunk(), and chan_iax2_pvt::vars.

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

01952 {
01953    struct chan_iax2_pvt *pvt;
01954    struct iax_frame *cur;
01955    struct ast_channel *owner;
01956 
01957 retry:
01958    pvt = iaxs[callno];
01959    gettimeofday(&lastused[callno], NULL);
01960    
01961    owner = pvt ? pvt->owner : NULL;
01962 
01963    if (owner) {
01964       if (ast_mutex_trylock(&owner->lock)) {
01965          ast_log(LOG_NOTICE, "Avoiding IAX destroy deadlock\n");
01966          ast_mutex_unlock(&iaxsl[callno]);
01967          usleep(1);
01968          ast_mutex_lock(&iaxsl[callno]);
01969          goto retry;
01970       }
01971    }
01972    if (!owner)
01973       iaxs[callno] = NULL;
01974    if (pvt) {
01975       if (!owner)
01976          pvt->owner = NULL;
01977       iax2_destroy_helper(pvt);
01978 
01979       /* Already gone */
01980       ast_set_flag(pvt, IAX_ALREADYGONE); 
01981 
01982       if (owner) {
01983          /* If there's an owner, prod it to give up */
01984          /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup()
01985           * because we already hold the owner channel lock. */
01986          ast_queue_hangup(owner);
01987       }
01988 
01989       AST_LIST_LOCK(&iaxq.queue);
01990       AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
01991          /* Cancel any pending transmissions */
01992          if (cur->callno == pvt->callno) 
01993             cur->retries = -1;
01994       }
01995       AST_LIST_UNLOCK(&iaxq.queue);
01996 
01997       if (pvt->reg)
01998          pvt->reg->callno = 0;
01999       if (!owner) {
02000          jb_frame frame;
02001          if (pvt->vars) {
02002              ast_variables_destroy(pvt->vars);
02003              pvt->vars = NULL;
02004          }
02005 
02006          while (jb_getall(pvt->jb, &frame) == JB_OK)
02007             iax2_frame_free(frame.data);
02008          jb_destroy(pvt->jb);
02009          /* gotta free up the stringfields */
02010          ast_string_field_free_memory(pvt);
02011          free(pvt);
02012       }
02013    }
02014    if (owner) {
02015       ast_mutex_unlock(&owner->lock);
02016    }
02017    if (callno & 0x4000)
02018       update_max_trunk();
02019 }

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1900 of file chan_iax2.c.

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

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

01901 {
01902    /* Decrement AUTHREQ count if needed */
01903    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01904       struct iax2_user *user;
01905       struct iax2_user tmp_user = {
01906          .name = pvt->username,
01907       };
01908 
01909       user = ao2_find(users, &tmp_user, OBJ_POINTER);
01910       if (user) {
01911          ast_atomic_fetchadd_int(&user->curauthreq, -1);
01912          user_unref(user); 
01913       }
01914 
01915       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01916    }
01917    /* No more pings or lagrq's */
01918    AST_SCHED_DEL(sched, pvt->pingid);
01919    AST_SCHED_DEL(sched, pvt->lagid);
01920    AST_SCHED_DEL(sched, pvt->autoid);
01921    AST_SCHED_DEL(sched, pvt->authid);
01922    AST_SCHED_DEL(sched, pvt->initid);
01923    AST_SCHED_DEL(sched, pvt->jbid);
01924 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 10486 of file chan_iax2.c.

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

10487 {
10488    struct parsed_dial_string pds;
10489    char *tmp = ast_strdupa(data);
10490    struct iax2_peer *p;
10491    int res = AST_DEVICE_INVALID;
10492 
10493    memset(&pds, 0, sizeof(pds));
10494    parse_dial_string(tmp, &pds);
10495 
10496    if (ast_strlen_zero(pds.peer)) {
10497       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10498       return res;
10499    }
10500    
10501    if (option_debug > 2)
10502       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10503 
10504    /* SLD: FIXME: second call to find_peer during registration */
10505    if (!(p = find_peer(pds.peer, 1)))
10506       return res;
10507 
10508    res = AST_DEVICE_UNAVAILABLE;
10509    if (option_debug > 2) 
10510       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10511          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10512    
10513    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10514        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10515       /* Peer is registered, or have default IP address
10516          and a valid registration */
10517       if (p->historicms == 0 || p->historicms <= p->maxms)
10518          /* let the core figure out whether it is in use or not */
10519          res = AST_DEVICE_UNKNOWN;  
10520    }
10521 
10522    peer_unref(p);
10523 
10524    return res;
10525 }

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

Definition at line 2633 of file chan_iax2.c.

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

02634 {
02635    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02636 }

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

Definition at line 2638 of file chan_iax2.c.

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

02639 {
02640    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02641 }

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

Definition at line 4796 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04797 {
04798    if (argc < 2 || argc > 3)
04799       return RESULT_SHOWUSAGE;
04800    iaxdebug = 1;
04801    ast_cli(fd, "IAX2 Debugging Enabled\n");
04802    return RESULT_SUCCESS;
04803 }

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

Definition at line 4814 of file chan_iax2.c.

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

04815 {
04816    if (argc < 3 || argc > 4)
04817       return RESULT_SHOWUSAGE;
04818    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04819    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04820    return RESULT_SUCCESS;
04821 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8464 of file chan_iax2.c.

References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno(), iax2_destroy(), iax2_do_register_s(), iax2_sched_add(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_WARNING, NEW_FORCE, option_debug, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), and iax2_registry::username.

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

08465 {
08466    struct iax_ie_data ied;
08467    if (option_debug && iaxdebug)
08468       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08469 
08470    if (reg->dnsmgr && 
08471        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08472       /* Maybe the IP has changed, force DNS refresh */
08473       ast_dnsmgr_refresh(reg->dnsmgr);
08474    }
08475    
08476    /*
08477     * if IP has Changed, free allocated call to create a new one with new IP
08478     * call has the pointer to IP and must be updated to the new one
08479     */
08480    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08481       ast_mutex_lock(&iaxsl[reg->callno]);
08482       iax2_destroy(reg->callno);
08483       ast_mutex_unlock(&iaxsl[reg->callno]);
08484       reg->callno = 0;
08485    }
08486    if (!reg->addr.sin_addr.s_addr) {
08487       if (option_debug && iaxdebug)
08488          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08489       /* Setup the next registration attempt */
08490       AST_SCHED_DEL(sched, reg->expire);
08491       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08492       return -1;
08493    }
08494 
08495    if (!reg->callno) {
08496       if (option_debug)
08497          ast_log(LOG_DEBUG, "Allocate call number\n");
08498       reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE, defaultsockfd);
08499       if (reg->callno < 1) {
08500          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08501          return -1;
08502       } else if (option_debug)
08503          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08504       iaxs[reg->callno]->reg = reg;
08505    }
08506    /* Schedule the next registration attempt */
08507    AST_SCHED_DEL(sched, reg->expire);
08508    /* Setup the next registration a little early */
08509    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08510    /* Send the request */
08511    memset(&ied, 0, sizeof(ied));
08512    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08513    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08514    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08515    reg->regstate = REG_STATE_REGSENT;
08516    return 0;
08517 }

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

Definition at line 5597 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05598 {
05599 #ifdef SCHED_MULTITHREADED
05600    if (schedule_action(__iax2_do_register_s, data))
05601 #endif      
05602       __iax2_do_register_s(data);
05603    return 0;
05604 }

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

Definition at line 4805 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04806 {
04807    if (argc < 3 || argc > 4)
04808       return RESULT_SHOWUSAGE;
04809    iaxtrunkdebug = 1;
04810    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04811    return RESULT_SUCCESS;
04812 }

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

Definition at line 6282 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

06283 {
06284    struct iax_ie_data ied;
06285    /* Auto-hangup with 30 seconds of inactivity */
06286    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06287    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06288    memset(&ied, 0, sizeof(ied));
06289    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06290    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06291    dp->flags |= CACHE_FLAG_TRANSMITTED;
06292 }

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

10346 {
10347    char odata[256];
10348    char req[256];
10349    char *ncontext;
10350    struct iax2_dpcache *dp;
10351    struct ast_app *dial;
10352 #if 0
10353    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);
10354 #endif
10355    if (priority == 2) {
10356       /* Indicate status, can be overridden in dialplan */
10357       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10358       if (dialstatus) {
10359          dial = pbx_findapp(dialstatus);
10360          if (dial) 
10361             pbx_exec(chan, dial, "");
10362       }
10363       return -1;
10364    } else if (priority != 1)
10365       return -1;
10366    ast_mutex_lock(&dpcache_lock);
10367    dp = find_cache(chan, data, context, exten, priority);
10368    if (dp) {
10369       if (dp->flags & CACHE_FLAG_EXISTS) {
10370          ast_copy_string(odata, data, sizeof(odata));
10371          ncontext = strchr(odata, '/');
10372          if (ncontext) {
10373             *ncontext = '\0';
10374             ncontext++;
10375             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10376          } else {
10377             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10378          }
10379          if (option_verbose > 2)
10380             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10381       } else {
10382          ast_mutex_unlock(&dpcache_lock);
10383          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10384          return -1;
10385       }
10386    }
10387    ast_mutex_unlock(&dpcache_lock);
10388    dial = pbx_findapp("Dial");
10389    if (dial) {
10390       return pbx_exec(chan, dial, req);
10391    } else {
10392       ast_log(LOG_WARNING, "No dial application registered\n");
10393    }
10394    return -1;
10395 }

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

10277 {
10278    struct iax2_dpcache *dp;
10279    int res = 0;
10280 #if 0
10281    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10282 #endif
10283    if ((priority != 1) && (priority != 2))
10284       return 0;
10285    ast_mutex_lock(&dpcache_lock);
10286    dp = find_cache(chan, data, context, exten, priority);
10287    if (dp) {
10288       if (dp->flags & CACHE_FLAG_EXISTS)
10289          res= 1;
10290    }
10291    ast_mutex_unlock(&dpcache_lock);
10292    if (!dp) {
10293       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10294    }
10295    return res;
10296 }

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

Definition at line 2660 of file chan_iax2.c.

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

02661 {
02662    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02663    ast_mutex_lock(&iaxsl[callno]);
02664    if (iaxs[callno])
02665       iaxs[callno]->owner = newchan;
02666    else
02667       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02668    ast_mutex_unlock(&iaxsl[callno]);
02669    return 0;
02670 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1422 of file chan_iax2.c.

References AST_SCHED_DEL, iax_frame_free(), iax_frame::retrans, and sched.

Referenced by __attempt_transmit(), __do_deliver(), __get_from_jb(), complete_transfer(), iax2_destroy(), and schedule_delivery().

01423 {
01424    AST_SCHED_DEL(sched, fr->retrans);
01425    iax_frame_free(fr);
01426 }

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

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

01155 {
01156    struct iax2_peer *peer = NULL;
01157    int res = 0;
01158    struct ao2_iterator i;
01159 
01160    i = ao2_iterator_init(peers, 0);
01161    while ((peer = ao2_iterator_next(&i))) {
01162       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01163           (peer->addr.sin_port == sin.sin_port)) {
01164          ast_copy_string(host, peer->name, len);
01165          peer_unref(peer);
01166          res = 1;
01167          break;
01168       }
01169       peer_unref(peer);
01170    }
01171 
01172    if (!peer) {
01173       peer = realtime_peer(NULL, &sin);
01174       if (peer) {
01175          ast_copy_string(host, peer->name, len);
01176          peer_unref(peer);
01177          res = 1;
01178       }
01179    }
01180 
01181    return res;
01182 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03574 {
03575    struct iax2_peer *peer;
03576    int res = 0;
03577    struct ao2_iterator i;
03578 
03579    i = ao2_iterator_init(peers, 0);
03580    while ((peer = ao2_iterator_next(&i))) {
03581       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03582           (peer->addr.sin_port == sin.sin_port)) {
03583          res = ast_test_flag(peer, IAX_TRUNK);
03584          peer_unref(peer);
03585          break;
03586       }
03587       peer_unref(peer);
03588    }
03589 
03590    return res;
03591 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3251 of file chan_iax2.c.

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

03252 {
03253    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03254    int alreadygone;
03255    struct iax_ie_data ied;
03256    memset(&ied, 0, sizeof(ied));
03257    ast_mutex_lock(&iaxsl[callno]);
03258    if (callno && iaxs[callno]) {
03259       if (option_debug)
03260          ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
03261       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03262       /* Send the hangup unless we have had a transmission error or are already gone */
03263       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03264       if (!iaxs[callno]->error && !alreadygone) {
03265          send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
03266          if (!iaxs[callno]) {
03267             ast_mutex_unlock(&iaxsl[callno]);
03268             return 0;
03269          }
03270       }
03271       /* Explicitly predestroy it */
03272       iax2_predestroy(callno);
03273       /* If we were already gone to begin with, destroy us now */
03274       if (alreadygone && iaxs[callno]) {
03275          if (option_debug)
03276             ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03277          iax2_destroy(callno);
03278       }
03279    }
03280    ast_mutex_unlock(&iaxsl[callno]);
03281    if (option_verbose > 2) 
03282       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03283    return 0;
03284 }

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

Definition at line 3519 of file chan_iax2.c.

References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, option_debug, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.

03520 {
03521    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03522    struct chan_iax2_pvt *pvt;
03523    int res = 0;
03524 
03525    if (option_debug && iaxdebug)
03526       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03527 
03528    ast_mutex_lock(&iaxsl[callno]);
03529    pvt = iaxs[callno];
03530 
03531    switch (condition) {
03532    case AST_CONTROL_HOLD:
03533       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03534          ast_moh_start(c, data, pvt->mohinterpret);
03535          goto done;
03536       }
03537       break;
03538    case AST_CONTROL_UNHOLD:
03539       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03540          ast_moh_stop(c);
03541          goto done;
03542       }
03543    }
03544 
03545    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03546 
03547 done:
03548    ast_mutex_unlock(&iaxsl[callno]);
03549 
03550    return res;
03551 }

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

10323 {
10324    int res = 0;
10325    struct iax2_dpcache *dp;
10326 #if 0
10327    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10328 #endif
10329    if ((priority != 1) && (priority != 2))
10330       return 0;
10331    ast_mutex_lock(&dpcache_lock);
10332    dp = find_cache(chan, data, context, exten, priority);
10333    if (dp) {
10334       if (dp->flags & CACHE_FLAG_MATCHMORE)
10335          res= 1;
10336    }
10337    ast_mutex_unlock(&dpcache_lock);
10338    if (!dp) {
10339       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10340    }
10341    return res;
10342 }

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

Definition at line 4823 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04824 {
04825    if (argc < 3 || argc > 4)
04826       return RESULT_SHOWUSAGE;
04827    iaxdebug = 0;
04828    ast_cli(fd, "IAX2 Debugging Disabled\n");
04829    return RESULT_SUCCESS;
04830 }

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

Definition at line 4841 of file chan_iax2.c.

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

04842 {
04843    if (argc < 4 || argc > 5)
04844       return RESULT_SHOWUSAGE;
04845    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04846    jb_debug_output("\n");
04847    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04848    return RESULT_SUCCESS;
04849 }

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

Definition at line 4832 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04833 {
04834    if (argc < 4 || argc > 5)
04835       return RESULT_SHOWUSAGE;
04836    iaxtrunkdebug = 0;
04837    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
04838    return RESULT_SUCCESS;
04839 }

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

Definition at line 8660 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08661 {
08662    struct iax2_peer *peer = (struct iax2_peer *)data;
08663    peer->pokeexpire = -1;
08664 #ifdef SCHED_MULTITHREADED
08665    if (schedule_action(__iax2_poke_noanswer, data))
08666 #endif      
08667       __iax2_poke_noanswer(data);
08668    peer_unref(peer);
08669    return 0;
08670 }

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

Definition at line 8681 of file chan_iax2.c.

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

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

08682 {
08683    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
08684       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
08685         immediately after clearing things out */
08686       peer->lastms = 0;
08687       peer->historicms = 0;
08688       peer->pokeexpire = -1;
08689       peer->callno = 0;
08690       return 0;
08691    }
08692    if (peer->callno > 0) {
08693       ast_log(LOG_NOTICE, "Still have a callno...\n");
08694       ast_mutex_lock(&iaxsl[peer->callno]);
08695       iax2_destroy(peer->callno);
08696       ast_mutex_unlock(&iaxsl[peer->callno]);
08697    }
08698    if (heldcall)
08699       ast_mutex_unlock(&iaxsl[heldcall]);
08700    peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd);
08701    if (heldcall)
08702       ast_mutex_lock(&iaxsl[heldcall]);
08703    if (peer->callno < 1) {
08704       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08705       return -1;
08706    }
08707 
08708    /* Speed up retransmission times for this qualify call */
08709    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08710    iaxs[peer->callno]->peerpoke = peer;
08711    
08712    /* Remove any pending pokeexpire task */
08713    if (peer->pokeexpire > -1) {
08714       if (!ast_sched_del(sched, peer->pokeexpire)) {
08715          peer->pokeexpire = -1;
08716          peer_unref(peer);
08717       }
08718    }
08719 
08720    /* Queue up a new task to handle no reply */
08721    /* If the host is already unreachable then use the unreachable interval instead */
08722    if (peer->lastms < 0) {
08723       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
08724    } else
08725       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
08726 
08727    if (peer->pokeexpire == -1)
08728       peer_unref(peer);
08729 
08730    /* And send the poke */
08731    send_command(iaxs[peer->callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08732 
08733    return 0;
08734 }

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

Definition at line 8672 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08673 {
08674    struct iax2_peer *peer = obj;
08675 
08676    iax2_poke_peer(peer, 0);
08677 
08678    return 0;
08679 }

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

Definition at line 6322 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06323 {
06324    struct iax2_peer *peer = (struct iax2_peer *)data;
06325    peer->pokeexpire = -1;
06326 #ifdef SCHED_MULTITHREADED
06327    if (schedule_action(__iax2_poke_peer_s, data))
06328 #endif      
06329       __iax2_poke_peer_s(data);
06330    return 0;
06331 }

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

01931 {
01932    struct ast_channel *c;
01933    struct chan_iax2_pvt *pvt = iaxs[callno];
01934 
01935    if (!pvt)
01936       return -1;
01937    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
01938       iax2_destroy_helper(pvt);
01939       ast_set_flag(pvt, IAX_ALREADYGONE); 
01940    }
01941    c = pvt->owner;
01942    if (c) {
01943       c->tech_pvt = NULL;
01944       iax2_queue_hangup(callno);
01945       pvt->owner = NULL;
01946       ast_module_unref(ast_module_info->self);
01947    }
01948    return 0;
01949 }

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

Definition at line 8339 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

08340 {
08341    struct iax2_thread *thread = data;
08342    struct timeval tv;
08343    struct timespec ts;
08344    int put_into_idle = 0;
08345 
08346    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
08347    pthread_cleanup_push(iax2_process_thread_cleanup, data);
08348    for(;;) {
08349       /* Wait for something to signal us to be awake */
08350       ast_mutex_lock(&thread->lock);
08351 
08352       /* Flag that we're ready to accept signals */
08353       thread->ready_for_signal = 1;
08354       
08355       /* Put into idle list if applicable */
08356       if (put_into_idle)
08357          insert_idle_thread(thread);
08358 
08359       if (thread->type == IAX_TYPE_DYNAMIC) {
08360          struct iax2_thread *t = NULL;
08361          /* Wait to be signalled or time out */
08362          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08363          ts.tv_sec = tv.tv_sec;
08364          ts.tv_nsec = tv.tv_usec * 1000;
08365          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
08366             /* This thread was never put back into the available dynamic
08367              * thread list, so just go away. */
08368             if (!put_into_idle) {
08369                ast_mutex_unlock(&thread->lock);
08370                break;
08371             }
08372             AST_LIST_LOCK(&dynamic_list);
08373             /* Account for the case where this thread is acquired *right* after a timeout */
08374             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
08375                iaxdynamicthreadcount--;
08376             AST_LIST_UNLOCK(&dynamic_list);
08377             if (t) {
08378                /* This dynamic thread timed out waiting for a task and was
08379                 * not acquired immediately after the timeout, 
08380                 * so it's time to go away. */
08381                ast_mutex_unlock(&thread->lock);
08382                break;
08383             }
08384             /* Someone grabbed our thread *right* after we timed out.
08385              * Wait for them to set us up with something to do and signal
08386              * us to continue. */
08387             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08388             ts.tv_sec = tv.tv_sec;
08389             ts.tv_nsec = tv.tv_usec * 1000;
08390             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
08391             {
08392                ast_mutex_unlock(&thread->lock);
08393                break;
08394             }
08395          }
08396       } else {
08397          ast_cond_wait(&thread->cond, &thread->lock);
08398       }
08399 
08400       /* Go back into our respective list */
08401       put_into_idle = 1;
08402 
08403       ast_mutex_unlock(&thread->lock);
08404 
08405       if (thread->iostate == IAX_IOSTATE_IDLE)
08406          continue;
08407 
08408       /* Add ourselves to the active list now */
08409       AST_LIST_LOCK(&active_list);
08410       AST_LIST_INSERT_HEAD(&active_list, thread, list);
08411       AST_LIST_UNLOCK(&active_list);
08412 
08413       /* See what we need to do */
08414       switch(thread->iostate) {
08415       case IAX_IOSTATE_READY:
08416          thread->actions++;
08417          thread->iostate = IAX_IOSTATE_PROCESSING;
08418          socket_process(thread);
08419          handle_deferred_full_frames(thread);
08420          break;
08421       case IAX_IOSTATE_SCHEDREADY:
08422          thread->actions++;
08423          thread->iostate = IAX_IOSTATE_PROCESSING;
08424 #ifdef SCHED_MULTITHREADED
08425          thread->schedfunc(thread->scheddata);
08426 #endif      
08427          break;
08428       }
08429       time(&thread->checktime);
08430       thread->iostate = IAX_IOSTATE_IDLE;
08431 #ifdef DEBUG_SCHED_MULTITHREAD
08432       thread->curfunc[0]='\0';
08433 #endif      
08434 
08435       /* Now... remove ourselves from the active list, and return to the idle list */
08436       AST_LIST_LOCK(&active_list);
08437       AST_LIST_REMOVE(&active_list, thread, list);
08438       AST_LIST_UNLOCK(&active_list);
08439 
08440       /* Make sure another frame didn't sneak in there after we thought we were done. */
08441       handle_deferred_full_frames(thread);
08442    }
08443 
08444    /*!\note For some reason, idle threads are exiting without being removed
08445     * from an idle list, which is causing memory corruption.  Forcibly remove
08446     * it from the list, if it's there.
08447     */
08448    AST_LIST_LOCK(&idle_list);
08449    AST_LIST_REMOVE(&idle_list, thread, list);
08450    AST_LIST_UNLOCK(&idle_list);
08451 
08452    AST_LIST_LOCK(&dynamic_list);
08453    AST_LIST_REMOVE(&dynamic_list, thread, list);
08454    AST_LIST_UNLOCK(&dynamic_list);
08455 
08456    /* I am exiting here on my own volition, I need to clean up my own data structures
08457    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
08458    */
08459    pthread_cleanup_pop(1);
08460 
08461    return NULL;
08462 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8330 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08331 {
08332    struct iax2_thread *thread = data;
08333    ast_mutex_destroy(&thread->lock);
08334    ast_cond_destroy(&thread->cond);
08335    free(thread);
08336    ast_atomic_dec_and_test(&iaxactivethreadcount);
08337 }

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

Definition at line 8617 of file chan_iax2.c.

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

08618 {
08619    int force = 0;
08620    int res;
08621    if (argc < 4)
08622       return RESULT_SHOWUSAGE;
08623    if ((argc > 4)) {
08624       if (!strcasecmp(argv[4], "forced"))
08625          force = 1;
08626       else
08627          return RESULT_SHOWUSAGE;
08628    }
08629    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08630    if (res < 0)
08631       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08632    else if (res < 1)
08633       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08634    else
08635       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08636    return RESULT_SUCCESS;
08637 }

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

Definition at line 8519 of file chan_iax2.c.

References iax_prov_complete_template().

08520 {
08521    if (pos != 3)
08522       return NULL;
08523    return iax_prov_complete_template(line, word, pos, state);
08524 }

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

Definition at line 8526 of file chan_iax2.c.

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

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

08527 {
08528    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08529       is found for template */
08530    struct iax_ie_data provdata;
08531    struct iax_ie_data ied;
08532    unsigned int sig;
08533    struct sockaddr_in sin;
08534    int callno;
08535    struct create_addr_info cai;
08536 
08537    memset(&cai, 0, sizeof(cai));
08538 
08539    if (option_debug)
08540       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08541 
08542    if (iax_provision_build(&provdata, &sig, template, force)) {
08543       if (option_debug)
08544          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08545       return 0;
08546    }
08547 
08548    if (end) {
08549       memcpy(&sin, end, sizeof(sin));
08550       cai.sockfd = sockfd;
08551    } else if (create_addr(dest, NULL, &sin, &cai))
08552       return -1;
08553 
08554    /* Build the rest of the message */
08555    memset(&ied, 0, sizeof(ied));
08556    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08557 
08558    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
08559    if (!callno)
08560       return -1;
08561 
08562    ast_mutex_lock(&iaxsl[callno]);
08563    if (iaxs[callno]) {
08564       /* Schedule autodestruct in case they don't ever give us anything back */
08565       AST_SCHED_DEL(sched, iaxs[callno]->autoid);
08566       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08567       ast_set_flag(iaxs[callno], IAX_PROVISION);
08568       /* Got a call number now, so go ahead and send the provisioning information */
08569       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08570    }
08571    ast_mutex_unlock(&iaxsl[callno]);
08572 
08573    return 1;
08574 }

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

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

02125 {
02126    struct iax2_peer *peer;
02127 
02128    if (argc != 4)
02129         return RESULT_SHOWUSAGE;
02130    if (!strcmp(argv[3],"all")) {
02131       reload_config();
02132       ast_cli(fd, "OK cache is flushed.\n");
02133    } else if ((peer = find_peer(argv[3], 0))) {
02134       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02135          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02136          expire_registry(peer_ref(peer));
02137          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02138       } else {
02139          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02140       }
02141       peer_unref(peer);
02142    } else {
02143       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02144    }
02145    
02146    return RESULT_SUCCESS;
02147 }

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

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

Referenced by socket_process().

01506 {
01507    for (;;) {
01508       if (iaxs[callno] && iaxs[callno]->owner) {
01509          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01510             /* Avoid deadlock by pausing and trying again */
01511             ast_mutex_unlock(&iaxsl[callno]);
01512             usleep(1);
01513             ast_mutex_lock(&iaxsl[callno]);
01514          } else {
01515             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01516             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01517             break;
01518          }
01519       } else
01520          break;
01521    }
01522    return 0;
01523 }

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

References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), f, iaxs, and iaxsl.

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

01439 {
01440    for (;;) {
01441       if (iaxs[callno] && iaxs[callno]->owner) {
01442          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01443             /* Avoid deadlock by pausing and trying again */
01444             ast_mutex_unlock(&iaxsl[callno]);
01445             usleep(1);
01446             ast_mutex_lock(&iaxsl[callno]);
01447          } else {
01448             ast_queue_frame(iaxs[callno]->owner, f);
01449             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01450             break;
01451          }
01452       } else
01453          break;
01454    }
01455    return 0;
01456 }

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

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

Referenced by iax2_predestroy().

01472 {
01473    for (;;) {
01474       if (iaxs[callno] && iaxs[callno]->owner) {
01475          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01476             /* Avoid deadlock by pausing and trying again */
01477             ast_mutex_unlock(&iaxsl[callno]);
01478             usleep(1);
01479             ast_mutex_lock(&iaxsl[callno]);
01480          } else {
01481             ast_queue_hangup(iaxs[callno]->owner);
01482             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01483             break;
01484          }
01485       } else
01486          break;
01487    }
01488    return 0;
01489 }

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

Definition at line 3312 of file chan_iax2.c.

References ast_log(), ast_null_frame, and LOG_NOTICE.

03313 {
03314    ast_log(LOG_NOTICE, "I should never be called!\n");
03315    return &ast_null_frame;
03316 }

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

Definition at line 5804 of file chan_iax2.c.

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

Referenced by set_config().

05805 {
05806    struct iax2_registry *reg;
05807    char copy[256];
05808    char *username, *hostname, *secret;
05809    char *porta;
05810    char *stringp=NULL;
05811    
05812    if (!value)
05813       return -1;
05814    ast_copy_string(copy, value, sizeof(copy));
05815    stringp=copy;
05816    username = strsep(&stringp, "@");
05817    hostname = strsep(&stringp, "@");
05818    if (!hostname) {
05819       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
05820       return -1;
05821    }
05822    stringp=username;
05823    username = strsep(&stringp, ":");
05824    secret = strsep(&stringp, ":");
05825    stringp=hostname;
05826    hostname = strsep(&stringp, ":");
05827    porta = strsep(&stringp, ":");
05828    
05829    if (porta && !atoi(porta)) {
05830       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
05831       return -1;
05832    }
05833    if (!(reg = ast_calloc(1, sizeof(*reg))))
05834       return -1;
05835    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
05836       free(reg);
05837       return -1;
05838    }
05839    ast_copy_string(reg->username, username, sizeof(reg->username));
05840    if (secret)
05841       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
05842    reg->expire = -1;
05843    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
05844    reg->addr.sin_family = AF_INET;
05845    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
05846    AST_LIST_LOCK(&registrations);
05847    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
05848    AST_LIST_UNLOCK(&registrations);
05849    
05850    return 0;
05851 }

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

Definition at line 10044 of file chan_iax2.c.

References reload_config().

10045 {
10046    return reload_config();
10047 }

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

Definition at line 8746 of file chan_iax2.c.

References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_translator_best_choice(), create_addr(), find_callno(), fmt, globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), ast_channel::readformat, and ast_channel::writeformat.

08747 {
08748    int callno;
08749    int res;
08750    int fmt, native;
08751    struct sockaddr_in sin;
08752    struct ast_channel *c;
08753    struct parsed_dial_string pds;
08754    struct create_addr_info cai;
08755    char *tmpstr;
08756 
08757    memset(&pds, 0, sizeof(pds));
08758    tmpstr = ast_strdupa(data);
08759    parse_dial_string(tmpstr, &pds);
08760 
08761    if (ast_strlen_zero(pds.peer)) {
08762       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
08763       return NULL;
08764    }
08765           
08766    memset(&cai, 0, sizeof(cai));
08767    cai.capability = iax2_capability;
08768 
08769    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08770    
08771    /* Populate our address from the given */
08772    if (create_addr(pds.peer, NULL, &sin, &cai)) {
08773       *cause = AST_CAUSE_UNREGISTERED;
08774       return NULL;
08775    }
08776 
08777    if (pds.port)
08778       sin.sin_port = htons(atoi(pds.port));
08779 
08780    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
08781    if (callno < 1) {
08782       ast_log(LOG_WARNING, "Unable to create call\n");
08783       *cause = AST_CAUSE_CONGESTION;
08784       return NULL;
08785    }
08786 
08787    ast_mutex_lock(&iaxsl[callno]);
08788 
08789    /* If this is a trunk, update it now */
08790    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08791    if (ast_test_flag(&cai, IAX_TRUNK)) {
08792       int new_callno;
08793       if ((new_callno = make_trunk(callno, 1)) != -1)
08794          callno = new_callno;
08795    }
08796    iaxs[callno]->maxtime = cai.maxtime;
08797    if (cai.found)
08798       ast_string_field_set(iaxs[callno], host, pds.peer);
08799 
08800    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08801 
08802    ast_mutex_unlock(&iaxsl[callno]);
08803 
08804    if (c) {
08805       /* Choose a format we can live with */
08806       if (c->nativeformats & format) 
08807          c->nativeformats &= format;
08808       else {
08809          native = c->nativeformats;
08810          fmt = format;
08811          res = ast_translator_best_choice(&fmt, &native);
08812          if (res < 0) {
08813             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
08814                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
08815             ast_hangup(c);
08816             return NULL;
08817          }
08818          c->nativeformats = native;
08819       }
08820       c->readformat = ast_best_codec(c->nativeformats);
08821       c->writeformat = c->readformat;
08822    }
08823 
08824    return c;
08825 }

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

Definition at line 969 of file chan_iax2.c.

References ast_sched_add(), and signal_condition().

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

00970 {
00971    int res;
00972 
00973    res = ast_sched_add(con, when, callback, data);
00974    signal_condition(&sched_lock, &sched_cond);
00975 
00976    return res;
00977 }

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

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

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

04135 {
04136    /* Queue a packet for delivery on a given private structure.  Use "ts" for
04137       timestamp, or calculate if ts is 0.  Send immediately without retransmission
04138       or delayed, with retransmission */
04139    struct ast_iax2_full_hdr *fh;
04140    struct ast_iax2_mini_hdr *mh;
04141    struct ast_iax2_video_hdr *vh;
04142    struct {
04143       struct iax_frame fr2;
04144       unsigned char buffer[4096];
04145    } frb;
04146    struct iax_frame *fr;
04147    int res;
04148    int sendmini=0;
04149    unsigned int lastsent;
04150    unsigned int fts;
04151 
04152    frb.fr2.afdatalen = sizeof(frb.buffer);
04153 
04154    if (!pvt) {
04155       ast_log(LOG_WARNING, "No private structure for packet?\n");
04156       return -1;
04157    }
04158    
04159    lastsent = pvt->lastsent;
04160 
04161    /* Calculate actual timestamp */
04162    fts = calc_timestamp(pvt, ts, f);
04163 
04164    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
04165     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
04166     * increment the "predicted timestamps" for voice, if we're predecting */
04167    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
04168        return 0;
04169 
04170 
04171    if ((ast_test_flag(pvt, IAX_TRUNK) || 
04172          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
04173          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
04174       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
04175        (f->frametype == AST_FRAME_VOICE) 
04176       /* is a voice frame */ &&
04177       (f->subclass == pvt->svoiceformat) 
04178       /* is the same type */ ) {
04179          /* Force immediate rather than delayed transmission */
04180          now = 1;
04181          /* Mark that mini-style frame is appropriate */
04182          sendmini = 1;
04183    }
04184    if ( f->frametype == AST_FRAME_VIDEO ) {
04185       /*
04186        * If the lower 15 bits of the timestamp roll over, or if
04187        * the video format changed then send a full frame.
04188        * Otherwise send a mini video frame
04189        */
04190       if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
04191           ((f->subclass & ~0x1) == pvt->svideoformat)
04192          ) {
04193          now = 1;
04194          sendmini = 1;
04195       } else {
04196          now = 0;
04197          sendmini = 0;
04198       }
04199       pvt->lastvsent = fts;
04200    }
04201    /* Allocate an iax_frame */
04202    if (now) {
04203       fr = &frb.fr2;
04204    } else
04205       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));
04206    if (!fr) {
04207       ast_log(LOG_WARNING, "Out of memory\n");
04208       return -1;
04209    }
04210    /* Copy our prospective frame into our immediate or retransmitted wrapper */
04211    iax_frame_wrap(fr, f);
04212 
04213    fr->ts = fts;
04214    fr->callno = pvt->callno;
04215    fr->transfer = transfer;
04216    fr->final = final;
04217    if (!sendmini) {
04218       /* We need a full frame */
04219       if (seqno > -1)
04220          fr->oseqno = seqno;
04221       else
04222          fr->oseqno = pvt->oseqno++;
04223       fr->iseqno = pvt->iseqno;
04224       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
04225       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
04226       fh->ts = htonl(fr->ts);
04227       fh->oseqno = fr->oseqno;
04228       if (transfer) {
04229          fh->iseqno = 0;
04230       } else
04231          fh->iseqno = fr->iseqno;
04232       /* Keep track of the last thing we've acknowledged */
04233       if (!transfer)
04234          pvt->aseqno = fr->iseqno;
04235       fh->type = fr->af.frametype & 0xFF;
04236       if (fr->af.frametype == AST_FRAME_VIDEO)
04237          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
04238       else
04239          fh->csub = compress_subclass(fr->af.subclass);
04240       if (transfer) {
04241          fr->dcallno = pvt->transfercallno;
04242       } else
04243          fr->dcallno = pvt->peercallno;
04244       fh->dcallno = htons(fr->dcallno);
04245       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
04246       fr->data = fh;
04247       fr->retries = 0;
04248       /* Retry after 2x the ping time has passed */
04249       fr->retrytime = pvt->pingtime * 2;
04250       if (fr->retrytime < MIN_RETRY_TIME)
04251          fr->retrytime = MIN_RETRY_TIME;
04252       if (fr->retrytime > MAX_RETRY_TIME)
04253          fr->retrytime = MAX_RETRY_TIME;
04254       /* Acks' don't get retried */
04255       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
04256          fr->retries = -1;
04257       else if (f->frametype == AST_FRAME_VOICE)
04258          pvt->svoiceformat = f->subclass;
04259       else if (f->frametype == AST_FRAME_VIDEO)
04260          pvt->svideoformat = f->subclass & ~0x1;
04261       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04262          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04263             if (iaxdebug) {
04264                if (fr->transfer)
04265                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04266                else
04267                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04268             }
04269             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
04270          } else
04271             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04272       }
04273    
04274       if (now) {
04275          res = send_packet(fr);
04276       } else
04277          res = iax2_transmit(fr);
04278    } else {
04279       if (ast_test_flag(pvt, IAX_TRUNK)) {
04280          iax2_trunk_queue(pvt, fr);
04281          res = 0;
04282       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
04283          /* Video frame have no sequence number */
04284          fr->oseqno = -1;
04285          fr->iseqno = -1;
04286          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
04287          vh->zeros = 0;
04288          vh->callno = htons(0x8000 | fr->callno);
04289          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
04290          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
04291          fr->data = vh;
04292          fr->retries = -1;
04293          res = send_packet(fr);        
04294       } else {
04295          /* Mini-frames have no sequence number */
04296          fr->oseqno = -1;
04297          fr->iseqno = -1;
04298          /* Mini frame will do */
04299          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
04300          mh->callno = htons(fr->callno);
04301          mh->ts = htons(fr->ts & 0xFFFF);
04302          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
04303          fr->data = mh;
04304          fr->retries = -1;
04305          if (pvt->transferring == TRANSFER_MEDIAPASS)
04306             fr->transfer = 1;
04307          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04308             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04309                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
04310             } else
04311                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04312          }
04313          res = send_packet(fr);
04314       }
04315    }
04316    return res;
04317 }

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

Definition at line 2655 of file chan_iax2.c.

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

02656 {
02657    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02658 }

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

Definition at line 2650 of file chan_iax2.c.

References AST_FRAME_IMAGE, ast_frame::data, ast_frame::datalen, PTR_TO_CALLNO, send_command_locked(), ast_frame::subclass, and ast_channel::tech_pvt.

02651 {
02652    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02653 }

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

Definition at line 2643 of file chan_iax2.c.

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

02644 {
02645    
02646    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02647       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02648 }

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

Definition at line 3286 of file chan_iax2.c.

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

03287 {
03288    struct ast_option_header *h;
03289    int res;
03290 
03291    switch (option) {
03292    case AST_OPTION_TXGAIN:
03293    case AST_OPTION_RXGAIN:
03294       /* these two cannot be sent, because they require a result */
03295       errno = ENOSYS;
03296       return -1;
03297    default:
03298       if (!(h = ast_malloc(datalen + sizeof(*h))))
03299          return -1;
03300 
03301       h->flag = AST_OPTION_FLAG_REQUEST;
03302       h->option = htons(option);
03303       memcpy(h->data, data, datalen);
03304       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03305                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03306                  datalen + sizeof(*h), -1);
03307       free(h);
03308       return res;
03309    }
03310 }

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

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

02329 {
02330    struct iax2_dpcache *dp;
02331    char tmp[1024], *pc;
02332    int s;
02333    int x,y;
02334    struct timeval tv;
02335    gettimeofday(&tv, NULL);
02336    ast_mutex_lock(&dpcache_lock);
02337    dp = dpcache;
02338    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02339    while(dp) {
02340       s = dp->expiry.tv_sec - tv.tv_sec;
02341       tmp[0] = '\0';
02342       if (dp->flags & CACHE_FLAG_EXISTS)
02343          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02344       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02345          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02346       if (dp->flags & CACHE_FLAG_CANEXIST)
02347          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02348       if (dp->flags & CACHE_FLAG_PENDING)
02349          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02350       if (dp->flags & CACHE_FLAG_TIMEOUT)
02351          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02352       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02353          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02354       if (dp->flags & CACHE_FLAG_MATCHMORE)
02355          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02356       if (dp->flags & CACHE_FLAG_UNKNOWN)
02357          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02358       /* Trim trailing pipe */
02359       if (!ast_strlen_zero(tmp))
02360          tmp[strlen(tmp) - 1] = '\0';
02361       else
02362          ast_copy_string(tmp, "(none)", sizeof(tmp));
02363       y=0;
02364       pc = strchr(dp->peercontext, '@');
02365       if (!pc)
02366          pc = dp->peercontext;
02367       else
02368          pc++;
02369       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02370          if (dp->waiters[x] > -1)
02371             y++;
02372       if (s > 0)
02373          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02374       else
02375          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02376       dp = dp->next;
02377    }
02378    ast_mutex_unlock(&dpcache_lock);
02379    return RESULT_SUCCESS;
02380 }

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

Definition at line 4661 of file chan_iax2.c.

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

04662 {
04663 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04664 #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"
04665 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04666    int x;
04667    int numchans = 0;
04668 
04669    if (argc != 3)
04670       return RESULT_SHOWUSAGE;
04671    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04672    for (x=0;x<IAX_MAX_CALLS;x++) {
04673       ast_mutex_lock(&iaxsl[x]);
04674       if (iaxs[x]) {
04675          int lag, jitter, localdelay;
04676          jb_info jbinfo;
04677          
04678          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04679             jb_getinfo(iaxs[x]->jb, &jbinfo);
04680             jitter = jbinfo.jitter;
04681             localdelay = jbinfo.current - jbinfo.min;
04682          } else {
04683             jitter = -1;
04684             localdelay = 0;
04685          }
04686          lag = iaxs[x]->remote_rr.delay;
04687          ast_cli(fd, FORMAT,
04688             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04689             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04690             S_OR(iaxs[x]->username, "(None)"),
04691             iaxs[x]->callno, iaxs[x]->peercallno,
04692             iaxs[x]->oseqno, iaxs[x]->iseqno,
04693             lag,
04694             jitter,
04695             localdelay,
04696             ast_getformatname(iaxs[x]->voiceformat) );
04697          numchans++;
04698       }
04699       ast_mutex_unlock(&iaxsl[x]);
04700    }
04701    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04702    return RESULT_SUCCESS;
04703 #undef FORMAT
04704 #undef FORMAT2
04705 #undef FORMATB
04706 }

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

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

04573 {
04574 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04575 #if !defined(__FreeBSD__)
04576 #define FORMAT "%-15.15s  %-15d %-15d\n"
04577 #else /* __FreeBSD__ */
04578 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04579 #endif /* __FreeBSD__ */
04580    struct iax_firmware *cur;
04581    if ((argc != 3) && (argc != 4))
04582       return RESULT_SHOWUSAGE;
04583    ast_mutex_lock(&waresl.lock);
04584    
04585    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04586    for (cur = waresl.wares;cur;cur = cur->next) {
04587       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04588          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04589             (int)ntohl(cur->fwh->datalen));
04590    }
04591    ast_mutex_unlock(&waresl.lock);
04592    return RESULT_SUCCESS;
04593 #undef FORMAT
04594 #undef FORMAT2
04595 }

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

Definition at line 4784 of file chan_iax2.c.

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

04785 {
04786    int numchans = 0;
04787    if (argc != 3)
04788       return RESULT_SHOWUSAGE;
04789    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04790    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04791    numchans = ast_cli_netstats(NULL, fd, 1);
04792    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04793    return RESULT_SUCCESS;
04794 }

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

Show one peer in detail.

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

02219 {
02220    char status[30];
02221    char cbuf[256];
02222    struct iax2_peer *peer;
02223    char codec_buf[512];
02224    int x = 0, codec = 0, load_realtime = 0;
02225 
02226    if (argc < 4)
02227       return RESULT_SHOWUSAGE;
02228 
02229    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02230 
02231    peer = find_peer(argv[3], load_realtime);
02232    if (peer) {
02233       ast_cli(fd,"\n\n");
02234       ast_cli(fd, "  * Name       : %s\n", peer->name);
02235       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02236       ast_cli(fd, "  Context      : %s\n", peer->context);
02237       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02238       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02239       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02240       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02241       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02242       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));
02243       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02244       ast_cli(fd, "  Username     : %s\n", peer->username);
02245       ast_cli(fd, "  Codecs       : ");
02246       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02247       ast_cli(fd, "%s\n", codec_buf);
02248 
02249       ast_cli(fd, "  Codec Order  : (");
02250       for(x = 0; x < 32 ; x++) {
02251          codec = ast_codec_pref_index(&peer->prefs,x);
02252          if(!codec)
02253             break;
02254          ast_cli(fd, "%s", ast_getformatname(codec));
02255          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02256             ast_cli(fd, "|");
02257       }
02258 
02259       if (!x)
02260          ast_cli(fd, "none");
02261       ast_cli(fd, ")\n");
02262 
02263       ast_cli(fd, "  Status       : ");
02264       peer_status(peer, status, sizeof(status));   
02265       ast_cli(fd, "%s\n",status);
02266       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02267       ast_cli(fd,"\n");
02268       peer_unref(peer);
02269    } else {
02270       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02271       ast_cli(fd,"\n");
02272    }
02273 
02274    return RESULT_SUCCESS;
02275 }

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

Definition at line 4561 of file chan_iax2.c.

References __iax2_show_peers().

04562 {
04563    return __iax2_show_peers(0, fd, NULL, argc, argv);
04564 }

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

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

04634 {
04635 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04636 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04637    struct iax2_registry *reg = NULL;
04638 
04639    char host[80];
04640    char perceived[80];
04641    if (argc != 3)
04642       return RESULT_SHOWUSAGE;
04643    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04644    AST_LIST_LOCK(&registrations);
04645    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04646       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04647       if (reg->us.sin_addr.s_addr) 
04648          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04649       else
04650          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04651       ast_cli(fd, FORMAT, host, 
04652                (reg->dnsmgr) ? "Y" : "N", 
04653                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04654    }
04655    AST_LIST_UNLOCK(&registrations);
04656    return RESULT_SUCCESS;
04657 #undef FORMAT
04658 #undef FORMAT2
04659 }

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

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

02303 {
02304    struct iax_frame *cur;
02305    int cnt = 0, dead=0, final=0;
02306 
02307    if (argc != 3)
02308       return RESULT_SHOWUSAGE;
02309 
02310    AST_LIST_LOCK(&iaxq.queue);
02311    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02312       if (cur->retries < 0)
02313          dead++;
02314       if (cur->final)
02315          final++;
02316       cnt++;
02317    }
02318    AST_LIST_UNLOCK(&iaxq.queue);
02319 
02320    ast_cli(fd, "    IAX Statistics\n");
02321    ast_cli(fd, "---------------------\n");
02322    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02323    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02324    
02325    return RESULT_SUCCESS;
02326 }

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

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

04503 {
04504    struct iax2_thread *thread = NULL;
04505    time_t t;
04506    int threadcount = 0, dynamiccount = 0;
04507    char type;
04508 
04509    if (argc != 3)
04510       return RESULT_SHOWUSAGE;
04511       
04512    ast_cli(fd, "IAX2 Thread Information\n");
04513    time(&t);
04514    ast_cli(fd, "Idle Threads:\n");
04515    AST_LIST_LOCK(&idle_list);
04516    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04517 #ifdef DEBUG_SCHED_MULTITHREAD
04518       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04519          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04520 #else
04521       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04522          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04523 #endif
04524       threadcount++;
04525    }
04526    AST_LIST_UNLOCK(&idle_list);
04527    ast_cli(fd, "Active Threads:\n");
04528    AST_LIST_LOCK(&active_list);
04529    AST_LIST_TRAVERSE(&active_list, thread, list) {
04530       if (thread->type == IAX_TYPE_DYNAMIC)
04531          type = 'D';
04532       else
04533          type = 'P';
04534 #ifdef DEBUG_SCHED_MULTITHREAD
04535       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04536          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04537 #else
04538       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04539          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04540 #endif
04541       threadcount++;
04542    }
04543    AST_LIST_UNLOCK(&active_list);
04544    ast_cli(fd, "Dynamic Threads:\n");
04545         AST_LIST_LOCK(&dynamic_list);
04546         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04547 #ifdef DEBUG_SCHED_MULTITHREAD
04548                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04549                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04550 #else
04551                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04552                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04553 #endif
04554       dynamiccount++;
04555         }
04556         AST_LIST_UNLOCK(&dynamic_list);
04557    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04558    return RESULT_SUCCESS;
04559 }

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

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

04320 {
04321    regex_t regexbuf;
04322    int havepattern = 0;
04323 
04324 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04325 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04326 
04327    struct iax2_user *user = NULL;
04328    char auth[90];
04329    char *pstr = "";
04330    struct ao2_iterator i;
04331 
04332    switch (argc) {
04333    case 5:
04334       if (!strcasecmp(argv[3], "like")) {
04335          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04336             return RESULT_SHOWUSAGE;
04337          havepattern = 1;
04338       } else
04339          return RESULT_SHOWUSAGE;
04340    case 3:
04341       break;
04342    default:
04343       return RESULT_SHOWUSAGE;
04344    }
04345 
04346    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04347    i = ao2_iterator_init(users, 0);
04348    for (user = ao2_iterator_next(&i); user; 
04349       user_unref(user), user = ao2_iterator_next(&i)) {
04350       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04351          continue;
04352       
04353       if (!ast_strlen_zero(user->secret)) {
04354          ast_copy_string(auth,user->secret,sizeof(auth));
04355       } else if (!ast_strlen_zero(user->inkeys)) {
04356          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04357       } else
04358          ast_copy_string(auth, "-no secret-", sizeof(auth));
04359       
04360       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04361          pstr = "REQ Only";
04362       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04363          pstr = "Disabled";
04364       else
04365          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04366       
04367       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04368          user->contexts ? user->contexts->context : context,
04369          user->ha ? "Yes" : "No", pstr);
04370    }
04371 
04372    if (havepattern)
04373       regfree(&regexbuf);
04374 
04375    return RESULT_SUCCESS;
04376 #undef FORMAT
04377 #undef FORMAT2
04378 }

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

Definition at line 3318 of file chan_iax2.c.

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

03319 {
03320    int res;
03321    struct iax_ie_data ied0;
03322    struct iax_ie_data ied1;
03323    unsigned int transferid = (unsigned int)ast_random();
03324    memset(&ied0, 0, sizeof(ied0));
03325    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03326    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03327    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03328 
03329    memset(&ied1, 0, sizeof(ied1));
03330    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03331    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03332    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03333    
03334    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03335    if (res)
03336       return -1;
03337    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03338    if (res)
03339       return -1;
03340    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03341    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03342    return 0;
03343 }

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

Definition at line 2149 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02150 {
02151        if (argc != 4)
02152                return RESULT_SHOWUSAGE;
02153 
02154        test_losspct = atoi(argv[3]);
02155 
02156        return RESULT_SUCCESS;
02157 }

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

Definition at line 3553 of file chan_iax2.c.

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

03554 {
03555    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03556    struct iax_ie_data ied;
03557    char tmp[256], *context;
03558    ast_copy_string(tmp, dest, sizeof(tmp));
03559    context = strchr(tmp, '@');
03560    if (context) {
03561       *context = '\0';
03562       context++;
03563    }
03564    memset(&ied, 0, sizeof(ied));
03565    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03566    if (context)
03567       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03568    if (option_debug)
03569       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03570    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03571 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

02615 {
02616    /* Lock the queue and place this packet at the end */
02617    /* By setting this to 0, the network thread will send it for us, and
02618       queue retransmission if necessary */
02619    fr->sentyet = 0;
02620    AST_LIST_LOCK(&iaxq.queue);
02621    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02622    iaxq.count++;
02623    AST_LIST_UNLOCK(&iaxq.queue);
02624    /* Wake up the network and scheduler thread */
02625    if (netthreadid != AST_PTHREADT_NULL)
02626       pthread_kill(netthreadid, SIGURG);
02627    signal_condition(&sched_lock, &sched_cond);
02628    return 0;
02629 }

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

Definition at line 6377 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06378 {
06379    /* Drop when trunk is about 5 seconds idle */
06380    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06381       return 1;
06382    return 0;
06383 }

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

Definition at line 3908 of file chan_iax2.c.

References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, DEFAULT_TRUNKDATA, f, find_tpeer(), globalflags, IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, MAX_TRUNKDATA, ast_iax2_meta_trunk_mini::mini, option_debug, chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.

Referenced by iax2_send().

03909 {
03910    struct ast_frame *f;
03911    struct iax2_trunk_peer *tpeer;
03912    void *tmp, *ptr;
03913    struct ast_iax2_meta_trunk_entry *met;
03914    struct ast_iax2_meta_trunk_mini *mtm;
03915 
03916    f = &fr->af;
03917    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
03918    if (tpeer) {
03919       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
03920          /* Need to reallocate space */
03921          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
03922             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
03923                ast_mutex_unlock(&tpeer->lock);
03924                return -1;
03925             }
03926             
03927             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
03928             tpeer->trunkdata = tmp;
03929             if (option_debug)
03930                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);
03931          } else {
03932             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));
03933             ast_mutex_unlock(&tpeer->lock);
03934             return -1;
03935          }
03936       }
03937 
03938       /* Append to meta frame */
03939       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
03940       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
03941          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
03942          mtm->len = htons(f->datalen);
03943          mtm->mini.callno = htons(pvt->callno);
03944          mtm->mini.ts = htons(0xffff & fr->ts);
03945          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
03946          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
03947       } else {
03948          met = (struct ast_iax2_meta_trunk_entry *)ptr;
03949          /* Store call number and length in meta header */
03950          met->callno = htons(pvt->callno);
03951          met->len = htons(f->datalen);
03952          /* Advance pointers/decrease length past trunk entry header */
03953          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
03954          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
03955       }
03956       /* Copy actual trunk data */
03957       memcpy(ptr, f->data, f->datalen);
03958       tpeer->trunkdatalen += f->datalen;
03959 
03960       tpeer->calls++;
03961       ast_mutex_unlock(&tpeer->lock);
03962    }
03963    return 0;
03964 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6294 of file chan_iax2.c.

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

Referenced by socket_process().

06295 {
06296    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06297 }

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

Definition at line 4851 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(), f, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.

04852 {
04853    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04854    int res = -1;
04855    ast_mutex_lock(&iaxsl[callno]);
04856    if (iaxs[callno]) {
04857    /* If there's an outstanding error, return failure now */
04858       if (!iaxs[callno]->error) {
04859          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
04860             res = 0;
04861             /* Don't waste bandwidth sending null frames */
04862          else if (f->frametype == AST_FRAME_NULL)
04863             res = 0;
04864          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
04865             res = 0;
04866          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
04867             res = 0;
04868          else
04869          /* Simple, just queue for transmission */
04870             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
04871       } else {
04872          if (option_debug)
04873             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
04874       }
04875    }
04876    /* If it's already gone, just return */
04877    ast_mutex_unlock(&iaxsl[callno]);
04878    return res;
04879 }

static int iax_check_version ( char *  dev  )  [static]

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

01680 {
01681    int res = 0;
01682    struct iax_firmware *cur;
01683    if (!ast_strlen_zero(dev)) {
01684       ast_mutex_lock(&waresl.lock);
01685       cur = waresl.wares;
01686       while(cur) {
01687          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01688             res = ntohs(cur->fwh->version);
01689             break;
01690          }
01691          cur = cur->next;
01692       }
01693       ast_mutex_unlock(&waresl.lock);
01694    }
01695    return res;
01696 }

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

Definition at line 765 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 771 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

01699 {
01700    int res = -1;
01701    unsigned int bs = desc & 0xff;
01702    unsigned int start = (desc >> 8) & 0xffffff;
01703    unsigned int bytes;
01704    struct iax_firmware *cur;
01705    if (!ast_strlen_zero((char *)dev) && bs) {
01706       start *= bs;
01707       ast_mutex_lock(&waresl.lock);
01708       cur = waresl.wares;
01709       while(cur) {
01710          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01711             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01712             if (start < ntohl(cur->fwh->datalen)) {
01713                bytes = ntohl(cur->fwh->datalen) - start;
01714                if (bytes > bs)
01715                   bytes = bs;
01716                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01717             } else {
01718                bytes = 0;
01719                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01720             }
01721             if (bytes == bs)
01722                res = 0;
01723             else
01724                res = 1;
01725             break;
01726          }
01727          cur = cur->next;
01728       }
01729       ast_mutex_unlock(&waresl.lock);
01730    }
01731    return res;
01732 }

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

Definition at line 6565 of file chan_iax2.c.

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

Referenced by socket_process().

06566 {
06567    struct iax_dual *d;
06568    struct ast_channel *chan1m, *chan2m;
06569    pthread_t th;
06570    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06571    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06572    if (chan2m && chan1m) {
06573       /* Make formats okay */
06574       chan1m->readformat = chan1->readformat;
06575       chan1m->writeformat = chan1->writeformat;
06576       ast_channel_masquerade(chan1m, chan1);
06577       /* Setup the extensions and such */
06578       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06579       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06580       chan1m->priority = chan1->priority;
06581       
06582       /* We make a clone of the peer channel too, so we can play
06583          back the announcement */
06584       /* Make formats okay */
06585       chan2m->readformat = chan2->readformat;
06586       chan2m->writeformat = chan2->writeformat;
06587       ast_channel_masquerade(chan2m, chan2);
06588       /* Setup the extensions and such */
06589       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06590       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06591       chan2m->priority = chan2->priority;
06592       if (ast_do_masquerade(chan2m)) {
06593          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06594          ast_hangup(chan2m);
06595          return -1;
06596       }
06597    } else {
06598       if (chan1m)
06599          ast_hangup(chan1m);
06600       if (chan2m)
06601          ast_hangup(chan2m);
06602       return -1;
06603    }
06604    if ((d = ast_calloc(1, sizeof(*d)))) {
06605       pthread_attr_t attr;
06606 
06607       pthread_attr_init(&attr);
06608       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06609 
06610       d->chan1 = chan1m;
06611       d->chan2 = chan2m;
06612       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06613          pthread_attr_destroy(&attr);
06614          return 0;
06615       }
06616       pthread_attr_destroy(&attr);
06617       free(d);
06618    }
06619    return -1;
06620 }

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

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

06546 {
06547    struct ast_channel *chan1, *chan2;
06548    struct iax_dual *d;
06549    struct ast_frame *f;
06550    int ext;
06551    int res;
06552    d = stuff;
06553    chan1 = d->chan1;
06554    chan2 = d->chan2;
06555    free(d);
06556    f = ast_read(chan1);
06557    if (f)
06558       ast_frfree(f);
06559    res = ast_park_call(chan1, chan2, 0, &ext);
06560    ast_hangup(chan2);
06561    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06562    return NULL;
06563 }

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

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

01223 {
01224    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01225    if (new) {
01226       size_t afdatalen = new->afdatalen;
01227       memcpy(new, fr, sizeof(*new));
01228       iax_frame_wrap(new, &fr->af);
01229       new->afdatalen = afdatalen;
01230       new->data = NULL;
01231       new->datalen = 0;
01232       new->direction = DIRECTION_INGRESS;
01233       new->retrans = -1;
01234    }
01235    return new;
01236 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 877 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, IAX_TYPE_DYNAMIC, and thread.

Referenced by iax2_process_thread().

00878 {
00879    if (thread->type == IAX_TYPE_DYNAMIC) {
00880       AST_LIST_LOCK(&dynamic_list);
00881       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
00882       AST_LIST_UNLOCK(&dynamic_list);
00883    } else {
00884       AST_LIST_LOCK(&idle_list);
00885       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
00886       AST_LIST_UNLOCK(&idle_list);
00887    }
00888 
00889    return;
00890 }

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

Definition at line 800 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 776 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 788 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 10859 of file chan_iax2.c.

References __unload_module(), ao2_callback(), ao2_container_alloc(), ao2_ref(), 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_provision_reload(), iax_set_error(), iax_set_output(), iaxpeer_function, iaxq, iaxs, iaxsl, io, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, netsock, option_verbose, outsock, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, reload_firmware(), sched, sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.

10860 {
10861    char *config = "iax.conf";
10862    int res = 0;
10863    int x;
10864    struct iax2_registry *reg = NULL;
10865 
10866    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
10867    if (!peers)
10868       return AST_MODULE_LOAD_FAILURE;
10869    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
10870    if (!users) {
10871       ao2_ref(peers, -1);
10872       return AST_MODULE_LOAD_FAILURE;
10873    }
10874 
10875    ast_custom_function_register(&iaxpeer_function);
10876 
10877    iax_set_output(iax_debug_output);
10878    iax_set_error(iax_error_output);
10879    jb_setoutput(jb_error_output, jb_warning_output, NULL);
10880    
10881 #ifdef HAVE_ZAPTEL
10882 #ifdef ZT_TIMERACK
10883    timingfd = open("/dev/zap/timer", O_RDWR);
10884    if (timingfd < 0)
10885 #endif
10886       timingfd = open("/dev/zap/pseudo", O_RDWR);
10887    if (timingfd < 0) 
10888       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
10889 #endif      
10890 
10891    memset(iaxs, 0, sizeof(iaxs));
10892 
10893    for (x=0;x<IAX_MAX_CALLS;x++)
10894       ast_mutex_init(&iaxsl[x]);
10895    
10896    ast_cond_init(&sched_cond, NULL);
10897 
10898    io = io_context_create();
10899    sched = sched_context_create();
10900    
10901    if (!io || !sched) {
10902       ast_log(LOG_ERROR, "Out of memory\n");
10903       return -1;
10904    }
10905 
10906    netsock = ast_netsock_list_alloc();
10907    if (!netsock) {
10908       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
10909       return -1;
10910    }
10911    ast_netsock_init(netsock);
10912 
10913    outsock = ast_netsock_list_alloc();
10914    if (!outsock) {
10915       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10916       return -1;
10917    }
10918    ast_netsock_init(outsock);
10919 
10920    ast_mutex_init(&waresl.lock);
10921 
10922    AST_LIST_HEAD_INIT(&iaxq.queue);
10923    
10924    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10925 
10926    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
10927    
10928    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
10929    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
10930 
10931    if(set_config(config, 0) == -1)
10932       return AST_MODULE_LOAD_DECLINE;
10933 
10934    if (ast_channel_register(&iax2_tech)) {
10935       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
10936       __unload_module();
10937       return -1;
10938    }
10939 
10940    if (ast_register_switch(&iax2_switch)) 
10941       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
10942 
10943    res = start_network_thread();
10944    if (!res) {
10945       if (option_verbose > 1) 
10946          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
10947    } else {
10948       ast_log(LOG_ERROR, "Unable to start network thread\n");
10949       ast_netsock_release(netsock);
10950       ast_netsock_release(outsock);
10951    }
10952 
10953    AST_LIST_LOCK(&registrations);
10954    AST_LIST_TRAVERSE(&registrations, reg, entry)
10955       iax2_do_register(reg);
10956    AST_LIST_UNLOCK(&registrations); 
10957 
10958    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
10959    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
10960 
10961    reload_firmware(0);
10962    iax_provision_reload();
10963    return res;
10964 }

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

Definition at line 3345 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03346 {
03347    ast_mutex_lock(&iaxsl[callno0]);
03348    while (ast_mutex_trylock(&iaxsl[callno1])) {
03349       ast_mutex_unlock(&iaxsl[callno0]);
03350       usleep(10);
03351       ast_mutex_lock(&iaxsl[callno0]);
03352    }
03353 }

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

Definition at line 1290 of file chan_iax2.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, chan_iax2_pvt::callno, iax2_sched_add(), iaxs, iaxsl, chan_iax2_pvt::lagid, LOG_WARNING, MIN_REUSE_TIME, chan_iax2_pvt::pingid, sched, send_lagrq(), send_ping(), and TRUNK_CALL_START.

Referenced by iax2_request(), and socket_process().

01291 {
01292    int x;
01293    int res= 0;
01294    struct timeval now;
01295    if (iaxs[callno]->oseqno) {
01296       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01297       return -1;
01298    }
01299    if (callno & TRUNK_CALL_START) {
01300       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01301       return -1;
01302    }
01303    gettimeofday(&now, NULL);
01304    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01305       ast_mutex_lock(&iaxsl[x]);
01306       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01307          iaxs[x] = iaxs[callno];
01308          iaxs[x]->callno = x;
01309          iaxs[callno] = NULL;
01310          /* Update the two timers that should have been started */
01311          AST_SCHED_DEL(sched, iaxs[x]->pingid);
01312          AST_SCHED_DEL(sched, iaxs[x]->lagid);
01313          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01314          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01315          if (locked)
01316             ast_mutex_unlock(&iaxsl[callno]);
01317          res = x;
01318          if (!locked)
01319             ast_mutex_unlock(&iaxsl[x]);
01320          break;
01321       }
01322       ast_mutex_unlock(&iaxsl[x]);
01323    }
01324    if (x >= IAX_MAX_CALLS - 1) {
01325       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01326       return -1;
01327    }
01328    if (option_debug)
01329       ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
01330    /* We move this call from a non-trunked to a trunked call */
01331    update_max_trunk();
01332    update_max_nontrunk();
01333    return res;
01334 }

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

Definition at line 4565 of file chan_iax2.c.

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

Referenced by load_module().

04566 {
04567    ast_cli_netstats(s, -1, 0);
04568    astman_append(s, "\r\n");
04569    return RESULT_SUCCESS;
04570 }

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

Definition at line 4598 of file chan_iax2.c.

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

Referenced by load_module().

04599 {
04600    char *a[] = { "iax2", "show", "users" };
04601    int ret;
04602    const char *id = astman_get_header(m,"ActionID");
04603 
04604    if (!ast_strlen_zero(id))
04605       astman_append(s, "ActionID: %s\r\n",id);
04606    ret = __iax2_show_peers(1, -1, s, 3, a );
04607    astman_append(s, "\r\n\r\n" );
04608    return ret;
04609 } /* /JDG */

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

Definition at line 1242 of file chan_iax2.c.

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

Referenced by ao2_callback(), ast_parse_device_state(), find_callno(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), pbx_find_extension(), realtime_switch_common(), and softhangup_exec().

01243 {
01244    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01245       (cur->addr.sin_port == sin->sin_port)) {
01246       /* This is the main host */
01247       if ((cur->peercallno == callno) ||
01248          ((dcallno == cur->callno) && !cur->peercallno)) {
01249          /* That's us.  Be sure we keep track of the peer call number */
01250          return 1;
01251       }
01252    }
01253    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01254        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01255       /* We're transferring */
01256       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01257          return 1;
01258    }
01259    return 0;
01260 }

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

Definition at line 3972 of file chan_iax2.c.

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

Referenced by decode_frame().

03973 {
03974 #if 0
03975    /* Debug with "fake encryption" */
03976    int x;
03977    if (len % 16)
03978       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03979    for (x=0;x<len;x++)
03980       dst[x] = src[x] ^ 0xff;
03981 #else 
03982    unsigned char lastblock[16] = { 0 };
03983    int x;
03984    while(len > 0) {
03985       aes_decrypt(src, dst, dcx);
03986       for (x=0;x<16;x++)
03987          dst[x] ^= lastblock[x];
03988       memcpy(lastblock, src, sizeof(lastblock));
03989       dst += 16;
03990       src += 16;
03991       len -= 16;
03992    }
03993 #endif
03994 }

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

Definition at line 3996 of file chan_iax2.c.

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

Referenced by encrypt_frame().

03997 {
03998 #if 0
03999    /* Debug with "fake encryption" */
04000    int x;
04001    if (len % 16)
04002       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04003    for (x=0;x<len;x++)
04004       dst[x] = src[x] ^ 0xff;
04005 #else
04006    unsigned char curblock[16] = { 0 };
04007    int x;
04008    while(len > 0) {
04009       for (x=0;x<16;x++)
04010          curblock[x] ^= src[x];
04011       aes_encrypt(curblock, dst, ecx);
04012       memcpy(curblock, dst, sizeof(curblock)); 
04013       dst += 16;
04014       src += 16;
04015       len -= 16;
04016    }
04017 #endif
04018 }

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

Definition at line 5176 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05177 {
05178    /* Select exactly one common encryption if there are any */
05179    p->encmethods &= enc;
05180    if (p->encmethods) {
05181       if (p->encmethods & IAX_ENCRYPT_AES128)
05182          p->encmethods = IAX_ENCRYPT_AES128;
05183       else
05184          p->encmethods = 0;
05185    }
05186 }

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

Definition at line 8855 of file chan_iax2.c.

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

Referenced by start_network_thread().

08856 {
08857    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
08858       from the network, and queue them for delivery to the channels */
08859    int res, count, wakeup;
08860    struct iax_frame *f;
08861 
08862    if (timingfd > -1)
08863       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
08864    
08865    for(;;) {
08866       pthread_testcancel();
08867 
08868       /* Go through the queue, sending messages which have not yet been
08869          sent, and scheduling retransmissions if appropriate */
08870       AST_LIST_LOCK(&iaxq.queue);
08871       count = 0;
08872       wakeup = -1;
08873       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
08874          if (f->sentyet)
08875             continue;
08876          
08877          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
08878          if (ast_mutex_trylock(&iaxsl[f->callno])) {
08879             wakeup = 1;
08880             continue;
08881          }
08882 
08883          f->sentyet++;
08884 
08885          if (iaxs[f->callno]) {
08886             send_packet(f);
08887             count++;
08888          } 
08889 
08890          ast_mutex_unlock(&iaxsl[f->callno]);
08891 
08892          if (f->retries < 0) {
08893             /* This is not supposed to be retransmitted */
08894             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
08895             iaxq.count--;
08896             /* Free the iax frame */
08897             iax_frame_free(f);
08898          } else {
08899             /* We need reliable delivery.  Schedule a retransmission */
08900             f->retries++;
08901             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
08902          }
08903       }
08904       AST_LIST_TRAVERSE_SAFE_END
08905       AST_LIST_UNLOCK(&iaxq.queue);
08906 
08907       pthread_testcancel();
08908 
08909       if (option_debug && count >= 20)
08910          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
08911 
08912       /* Now do the IO, and run scheduled tasks */
08913       res = ast_io_wait(io, wakeup);
08914       if (res >= 0) {
08915          if (option_debug && res >= 20)
08916             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
08917       }
08918    }
08919    return NULL;
08920 }

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

Definition at line 1184 of file chan_iax2.c.

References ast_calloc, ast_string_field_init, ast_string_field_set, exten, free, jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, prefs, and jb_conf::resync_threshold.

Referenced by find_callno().

01185 {
01186    struct chan_iax2_pvt *tmp;
01187    jb_conf jbconf;
01188 
01189    if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01190       return NULL;
01191 
01192    if (ast_string_field_init(tmp, 32)) {
01193       free(tmp);
01194       tmp = NULL;
01195       return NULL;
01196    }
01197       
01198    tmp->prefs = prefs;
01199    tmp->callno = 0;
01200    tmp->peercallno = 0;
01201    tmp->transfercallno = 0;
01202    tmp->bridgecallno = 0;
01203    tmp->pingid = -1;
01204    tmp->lagid = -1;
01205    tmp->autoid = -1;
01206    tmp->authid = -1;
01207    tmp->initid = -1;
01208 
01209    ast_string_field_set(tmp,exten, "s");
01210    ast_string_field_set(tmp,host, host);
01211 
01212    tmp->jb = jb_new();
01213    tmp->jbid = -1;
01214    jbconf.max_jitterbuf = maxjitterbuffer;
01215    jbconf.resync_threshold = resyncthreshold;
01216    jbconf.max_contig_interp = maxjitterinterps;
01217    jb_setconf(tmp->jb,&jbconf);
01218 
01219    return tmp;
01220 }

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

03066 {
03067    if (ast_strlen_zero(data))
03068       return;
03069 
03070    pds->peer = strsep(&data, "/");
03071    pds->exten = strsep(&data, "/");
03072    pds->options = data;
03073 
03074    if (pds->exten) {
03075       data = pds->exten;
03076       pds->exten = strsep(&data, "@");
03077       pds->context = data;
03078    }
03079 
03080    if (strchr(pds->peer, '@')) {
03081       data = pds->peer;
03082       pds->username = strsep(&data, "@");
03083       pds->peer = data;
03084    }
03085 
03086    if (pds->username) {
03087       data = pds->username;
03088       pds->username = strsep(&data, ":");
03089       pds->password = data;
03090    }
03091 
03092    data = pds->peer;
03093    pds->peer = strsep(&data, ":");
03094    pds->port = data;
03095 
03096    /* check for a key name wrapped in [] in the secret position, if found,
03097       move it to the key field instead
03098    */
03099    if (pds->password && (pds->password[0] == '[')) {
03100       pds->key = ast_strip_quoted(pds->password, "[", "]");
03101       pds->password = NULL;
03102    }
03103 }

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

Referenced by load_module().

01084 {
01085    struct iax2_peer *peer = obj, *peer2 = arg;
01086 
01087    return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
01088 }

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

Definition at line 9553 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09554 {
09555    struct iax2_peer *peer = obj;
09556 
09557    ast_set_flag(peer, IAX_DELME);
09558 
09559    return 0;
09560 }

static void peer_destructor ( void *  obj  )  [static]

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

09079 {
09080    struct iax2_peer *peer = obj;
09081 
09082    ast_free_ha(peer->ha);
09083 
09084    if (peer->callno > 0) {
09085       ast_mutex_lock(&iaxsl[peer->callno]);
09086       iax2_destroy(peer->callno);
09087       ast_mutex_unlock(&iaxsl[peer->callno]);
09088    }
09089 
09090    register_peer_exten(peer, 0);
09091 
09092    if (peer->dnsmgr)
09093       ast_dnsmgr_release(peer->dnsmgr);
09094 
09095    ast_string_field_free_memory(peer);
09096 }

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

References ast_str_hash().

Referenced by load_module().

01074 {
01075    const struct iax2_peer *peer = obj;
01076 
01077    return ast_str_hash(peer->name);
01078 }

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

Definition at line 1130 of file chan_iax2.c.

References ao2_ref().

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

01131 {
01132    ao2_ref(peer, +1);
01133    return peer;
01134 }

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

Definition at line 10848 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

10849 {
10850    struct iax2_peer *peer = obj;
10851 
10852    if (peer->sockfd < 0)
10853       peer->sockfd = defaultsockfd;
10854 
10855    return 0;
10856 }

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

References ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, io, LOG_WARNING, netsock, option_debug, outsock, socket_read(), iax2_peer::sockfd, and strsep().

Referenced by build_peer().

09006 {
09007    struct sockaddr_in sin;
09008    int nonlocal = 1;
09009    int port = IAX_DEFAULT_PORTNO;
09010    int sockfd = defaultsockfd;
09011    char *tmp;
09012    char *addr;
09013    char *portstr;
09014 
09015    if (!(tmp = ast_strdupa(srcaddr)))
09016       return -1;
09017 
09018    addr = strsep(&tmp, ":");
09019    portstr = tmp;
09020 
09021    if (portstr) {
09022       port = atoi(portstr);
09023       if (port < 1)
09024          port = IAX_DEFAULT_PORTNO;
09025    }
09026    
09027    if (!ast_get_ip(&sin, addr)) {
09028       struct ast_netsock *sock;
09029       int res;
09030 
09031       sin.sin_port = 0;
09032       sin.sin_family = AF_INET;
09033       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
09034       if (res == 0) {
09035          /* ip address valid. */
09036          sin.sin_port = htons(port);
09037          if (!(sock = ast_netsock_find(netsock, &sin)))
09038             sock = ast_netsock_find(outsock, &sin);
09039          if (sock) {
09040             sockfd = ast_netsock_sockfd(sock);
09041             nonlocal = 0;
09042          } else {
09043             unsigned int orig_saddr = sin.sin_addr.s_addr;
09044             /* INADDR_ANY matches anyway! */
09045             sin.sin_addr.s_addr = INADDR_ANY;
09046             if (ast_netsock_find(netsock, &sin)) {
09047                sin.sin_addr.s_addr = orig_saddr;
09048                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09049                if (sock) {
09050                   sockfd = ast_netsock_sockfd(sock);
09051                   ast_netsock_unref(sock);
09052                   nonlocal = 0;
09053                } else {
09054                   nonlocal = 2;
09055                }
09056             }
09057          }
09058       }
09059    }
09060       
09061    peer->sockfd = sockfd;
09062 
09063    if (nonlocal == 1) {
09064       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09065          srcaddr, peer->name);
09066       return -1;
09067         } else if (nonlocal == 2) {
09068       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09069          srcaddr, peer->name);
09070          return -1;
09071    } else {
09072       if (option_debug)
09073          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09074       return 0;
09075    }
09076 }

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

peer_status: Report Peer status in character string

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

02196 {
02197    int res = 0;
02198    if (peer->maxms) {
02199       if (peer->lastms < 0) {
02200          ast_copy_string(status, "UNREACHABLE", statuslen);
02201       } else if (peer->lastms > peer->maxms) {
02202          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02203          res = 1;
02204       } else if (peer->lastms) {
02205          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02206          res = 1;
02207       } else {
02208          ast_copy_string(status, "UNKNOWN", statuslen);
02209       }
02210    } else { 
02211       ast_copy_string(status, "Unmonitored", statuslen);
02212       res = -1;
02213    }
02214    return res;
02215 }

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

Definition at line 1136 of file chan_iax2.c.

References ao2_ref().

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

01137 {
01138    ao2_ref(peer, -1);
01139    return NULL;
01140 }

static void poke_all_peers ( void   )  [static]

Definition at line 10012 of file chan_iax2.c.

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

Referenced by reload_config().

10013 {
10014    struct ao2_iterator i;
10015    struct iax2_peer *peer;
10016 
10017    i = ao2_iterator_init(peers, 0);
10018    while ((peer = ao2_iterator_next(&i))) {
10019       iax2_poke_peer(peer, 0);
10020       peer_unref(peer);
10021    }
10022 }

static void prune_peers ( void   )  [static]

Definition at line 9611 of file chan_iax2.c.

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

09612 {
09613    struct iax2_peer *peer;
09614    struct ao2_iterator i;
09615 
09616    i = ao2_iterator_init(peers, 0);
09617    while ((peer = ao2_iterator_next(&i))) {
09618       if (ast_test_flag(peer, IAX_DELME))
09619          unlink_peer(peer);
09620       peer_unref(peer);
09621    }
09622 }

static void prune_users ( void   )  [static]

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

09598 {
09599    struct iax2_user *user;
09600    struct ao2_iterator i;
09601 
09602    i = ao2_iterator_init(users, 0);
09603    while ((user = ao2_iterator_next(&i))) {
09604       if (ast_test_flag(user, IAX_DELME))
09605          ao2_unlink(users, user);
09606       user_unref(user);
09607    }
09608 }

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

Definition at line 5158 of file chan_iax2.c.

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

Referenced by socket_process().

05159 {
05160    struct ast_iax2_full_hdr fh;
05161    fh.scallno = htons(src | IAX_FLAG_FULL);
05162    fh.dcallno = htons(dst);
05163    fh.ts = 0;
05164    fh.oseqno = 0;
05165    fh.iseqno = 0;
05166    fh.type = AST_FRAME_IAX;
05167    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05168    if (iaxdebug)
05169        iax_showframe(NULL, &fh, 0, sin, 0);
05170    if (option_debug)
05171       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05172          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05173    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05174 }

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

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

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

Definition at line 2676 of file chan_iax2.c.

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

02677 {
02678    struct ast_variable *var = NULL;
02679    struct ast_variable *tmp;
02680    struct iax2_peer *peer=NULL;
02681    time_t regseconds = 0, nowtime;
02682    int dynamic=0;
02683 
02684    if (peername) {
02685       var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL);
02686       if (!var && sin)
02687          var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02688    } else if (sin) {
02689       char porta[25];
02690       sprintf(porta, "%d", ntohs(sin->sin_port));
02691       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02692       if (var) {
02693          /* We'll need the peer name in order to build the structure! */
02694          for (tmp = var; tmp; tmp = tmp->next) {
02695             if (!strcasecmp(tmp->name, "name"))
02696                peername = tmp->value;
02697          }
02698       }
02699    }
02700    if (!var && peername) { /* Last ditch effort */
02701       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
02702       /*!\note
02703        * If this one loaded something, then we need to ensure that the host
02704        * field matched.  The only reason why we can't have this as a criteria
02705        * is because we only have the IP address and the host field might be
02706        * set as a name (and the reverse PTR might not match).
02707        */
02708       if (var && sin) {
02709          for (tmp = var; tmp; tmp = tmp->next) {
02710             if (!strcasecmp(tmp->name, "host")) {
02711                struct ast_hostent ahp;
02712                struct hostent *hp;
02713                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02714                   /* No match */
02715                   ast_variables_destroy(var);
02716                   var = NULL;
02717                }
02718                break;
02719             }
02720          }
02721       }
02722    }
02723    if (!var)
02724       return NULL;
02725 
02726    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
02727    
02728    if (!peer) {
02729       ast_variables_destroy(var);
02730       return NULL;
02731    }
02732 
02733    for (tmp = var; tmp; tmp = tmp->next) {
02734       /* Make sure it's not a user only... */
02735       if (!strcasecmp(tmp->name, "type")) {
02736          if (strcasecmp(tmp->value, "friend") &&
02737              strcasecmp(tmp->value, "peer")) {
02738             /* Whoops, we weren't supposed to exist! */
02739             peer = peer_unref(peer);
02740             break;
02741          } 
02742       } else if (!strcasecmp(tmp->name, "regseconds")) {
02743          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
02744       } else if (!strcasecmp(tmp->name, "ipaddr")) {
02745          inet_aton(tmp->value, &(peer->addr.sin_addr));
02746       } else if (!strcasecmp(tmp->name, "port")) {
02747          peer->addr.sin_port = htons(atoi(tmp->value));
02748       } else if (!strcasecmp(tmp->name, "host")) {
02749          if (!strcasecmp(tmp->value, "dynamic"))
02750             dynamic = 1;
02751       }
02752    }
02753 
02754    ast_variables_destroy(var);
02755 
02756    if (!peer)
02757       return NULL;
02758 
02759    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02760       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
02761       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
02762          if (peer->expire > -1) {
02763             if (!ast_sched_del(sched, peer->expire)) {
02764                peer->expire = -1;
02765                peer_unref(peer);
02766             }
02767          }
02768          peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
02769          if (peer->expire == -1)
02770             peer_unref(peer);
02771       }
02772       ao2_link(peers, peer);
02773       if (ast_test_flag(peer, IAX_DYNAMIC))
02774          reg_source_db(peer);
02775    } else {
02776       ast_set_flag(peer, IAX_TEMPONLY);   
02777    }
02778 
02779    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
02780       time(&nowtime);
02781       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
02782          memset(&peer->addr, 0, sizeof(peer->addr));
02783          realtime_update_peer(peer->name, &peer->addr, 0);
02784          if (option_debug)
02785             ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
02786                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02787       }
02788       else {
02789          if (option_debug)
02790             ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
02791                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02792       }
02793    }
02794 
02795    return peer;
02796 }

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

Definition at line 2869 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02870 {
02871    char port[10];
02872    char regseconds[20];
02873    
02874    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
02875    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
02876    ast_update_realtime("iaxpeers", "name", peername, 
02877       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
02878       "regseconds", regseconds, NULL);
02879 }

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

Definition at line 2798 of file chan_iax2.c.

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

02799 {
02800    struct ast_variable *var;
02801    struct ast_variable *tmp;
02802    struct iax2_user *user=NULL;
02803 
02804    var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL);
02805    if (!var)
02806       var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02807    if (!var && sin) {
02808       char porta[6];
02809       snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port));
02810       var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02811       if (!var)
02812          var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02813    }
02814    if (!var) { /* Last ditch effort */
02815       var = ast_load_realtime("iaxusers", "name", username, NULL);
02816       /*!\note
02817        * If this one loaded something, then we need to ensure that the host
02818        * field matched.  The only reason why we can't have this as a criteria
02819        * is because we only have the IP address and the host field might be
02820        * set as a name (and the reverse PTR might not match).
02821        */
02822       if (var) {
02823          for (tmp = var; tmp; tmp = tmp->next) {
02824             if (!strcasecmp(tmp->name, "host")) {
02825                struct ast_hostent ahp;
02826                struct hostent *hp;
02827                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02828                   /* No match */
02829                   ast_variables_destroy(var);
02830                   var = NULL;
02831                }
02832                break;
02833             }
02834          }
02835       }
02836    }
02837    if (!var)
02838       return NULL;
02839 
02840    tmp = var;
02841    while(tmp) {
02842       /* Make sure it's not a peer only... */
02843       if (!strcasecmp(tmp->name, "type")) {
02844          if (strcasecmp(tmp->value, "friend") &&
02845              strcasecmp(tmp->value, "user")) {
02846             return NULL;
02847          } 
02848       }
02849       tmp = tmp->next;
02850    }
02851 
02852    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
02853 
02854    ast_variables_destroy(var);
02855 
02856    if (!user)
02857       return NULL;
02858 
02859    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02860       ast_set_flag(user, IAX_RTCACHEFRIENDS);
02861       ao2_link(users, user);
02862    } else {
02863       ast_set_flag(user, IAX_TEMPONLY);   
02864    }
02865 
02866    return user;
02867 }

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 5933 of file chan_iax2.c.

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

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

05934 {
05935    char data[80];
05936    struct in_addr in;
05937    char *c, *d;
05938    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
05939       c = strchr(data, ':');
05940       if (c) {
05941          *c = '\0';
05942          c++;
05943          if (inet_aton(data, &in)) {
05944             d = strchr(c, ':');
05945             if (d) {
05946                *d = '\0';
05947                d++;
05948                if (option_verbose > 2)
05949                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
05950                   ast_inet_ntoa(in), atoi(c), atoi(d));
05951                iax2_poke_peer(p, 0);
05952                p->expiry = atoi(d);
05953                memset(&p->addr, 0, sizeof(p->addr));
05954                p->addr.sin_family = AF_INET;
05955                p->addr.sin_addr = in;
05956                p->addr.sin_port = htons(atoi(c));
05957                if (p->expire > -1) {
05958                   if (!ast_sched_del(sched, p->expire)) {
05959                      p->expire = -1;
05960                      peer_unref(p);
05961                   }
05962                }
05963                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05964                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
05965                if (p->expire == -1)
05966                   peer_unref(p);
05967                if (iax2_regfunk)
05968                   iax2_regfunk(p->name, 1);
05969                register_peer_exten(p, 1);
05970             }              
05971                
05972          }
05973       }
05974    }
05975 }

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

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

05854 {
05855    char multi[256];
05856    char *stringp, *ext;
05857    if (!ast_strlen_zero(regcontext)) {
05858       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
05859       stringp = multi;
05860       while((ext = strsep(&stringp, "&"))) {
05861          if (onoff) {
05862             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
05863                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
05864                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
05865          } else
05866             ast_context_remove_extension(regcontext, ext, 1, NULL);
05867       }
05868    }
05869 }

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

Verify inbound registration.

Definition at line 5322 of file chan_iax2.c.

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

Referenced by handle_request_register(), and socket_process().

05323 {
05324    char requeststr[256] = "";
05325    char peer[256] = "";
05326    char md5secret[256] = "";
05327    char rsasecret[256] = "";
05328    char secret[256] = "";
05329    struct iax2_peer *p = NULL;
05330    struct ast_key *key;
05331    char *keyn;
05332    int x;
05333    int expire = 0;
05334    int res = -1;
05335 
05336    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
05337    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05338    if (ies->username)
05339       ast_copy_string(peer, ies->username, sizeof(peer));
05340    if (ies->password)
05341       ast_copy_string(secret, ies->password, sizeof(secret));
05342    if (ies->md5_result)
05343       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05344    if (ies->rsa_result)
05345       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05346    if (ies->refresh)
05347       expire = ies->refresh;
05348 
05349    if (ast_strlen_zero(peer)) {
05350       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05351       return -1;
05352    }
05353 
05354    /* SLD: first call to lookup peer during registration */
05355    ast_mutex_unlock(&iaxsl[callno]);
05356    p = find_peer(peer, 1);
05357    ast_mutex_lock(&iaxsl[callno]);
05358    if (!p || !iaxs[callno]) {
05359       if (authdebug && !p)
05360          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05361       goto return_unref;
05362    }
05363 
05364    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05365       if (authdebug)
05366          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05367       goto return_unref;
05368    }
05369 
05370    if (!ast_apply_ha(p->ha, sin)) {
05371       if (authdebug)
05372          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05373       goto return_unref;
05374    }
05375    if (!inaddrcmp(&p->addr, sin))
05376       ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
05377    ast_string_field_set(iaxs[callno], secret, p->secret);
05378    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05379    /* Check secret against what we have on file */
05380    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05381       if (!ast_strlen_zero(p->inkeys)) {
05382          char tmpkeys[256];
05383          char *stringp=NULL;
05384          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05385          stringp=tmpkeys;
05386          keyn = strsep(&stringp, ":");
05387          while(keyn) {
05388             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05389             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05390                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05391                break;
05392             } else if (!key) 
05393                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05394             keyn = strsep(&stringp, ":");
05395          }
05396          if (!keyn) {
05397             if (authdebug)
05398                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05399             goto return_unref;
05400          }
05401       } else {
05402          if (authdebug)
05403             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05404          goto return_unref;
05405       }
05406    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05407       struct MD5Context md5;
05408       unsigned char digest[16];
05409       char *tmppw, *stringp;
05410       
05411       tmppw = ast_strdupa(p->secret);
05412       stringp = tmppw;
05413       while((tmppw = strsep(&stringp, ";"))) {
05414          MD5Init(&md5);
05415          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05416          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05417          MD5Final(digest, &md5);
05418          for (x=0;x<16;x++)
05419             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05420          if (!strcasecmp(requeststr, md5secret)) 
05421             break;
05422       }
05423       if (tmppw) {
05424          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05425       } else {
05426          if (authdebug)
05427             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05428          goto return_unref;
05429       }
05430    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05431       /* They've provided a plain text password and we support that */
05432       if (strcmp(secret, p->secret)) {
05433          if (authdebug)
05434             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05435          goto return_unref;
05436       } else
05437          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05438    } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) {
05439       if (authdebug)
05440          ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
05441       goto return_unref;
05442    }
05443    ast_string_field_set(iaxs[callno], peer, peer);
05444    /* Choose lowest expiry number */
05445    if (expire && (expire < iaxs[callno]->expiry)) 
05446       iaxs[callno]->expiry = expire;
05447 
05448    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05449 
05450    res = 0;
05451 
05452 return_unref:
05453    if (p)
05454       peer_unref(p);
05455 
05456    return res;
05457 }

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6112 of file chan_iax2.c.

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

Referenced by socket_process().

06113 {
06114    struct iax_ie_data ied;
06115    struct iax2_peer *p;
06116    char challenge[10];
06117    const char *peer_name;
06118    int res = -1;
06119 
06120    peer_name = ast_strdupa(iaxs[callno]->peer);
06121 
06122    /* SLD: third call to find_peer in registration */
06123    ast_mutex_unlock(&iaxsl[callno]);
06124    p = find_peer(peer_name, 1);
06125    ast_mutex_lock(&iaxsl[callno]);
06126    if (!iaxs[callno])
06127       goto return_unref;
06128    if (!p) {
06129       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06130       goto return_unref;
06131    }
06132    
06133    memset(&ied, 0, sizeof(ied));
06134    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06135    if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06136       /* Build the challenge */
06137       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06138       ast_string_field_set(iaxs[callno], challenge, challenge);
06139       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06140    }
06141    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06142 
06143    res = 0;
06144 
06145 return_unref:
06146    peer_unref(p);
06147 
06148    return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
06149 }

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

Definition at line 6151 of file chan_iax2.c.

References iax2_registry::addr, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, ies, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_AUTHSENT, iax2_registry::regstate, iax2_registry::secret, send_command(), and iax2_registry::username.

Referenced by socket_process().

06152 {
06153    struct iax2_registry *reg;
06154    /* Start pessimistic */
06155    struct iax_ie_data ied;
06156    char peer[256] = "";
06157    char challenge[256] = "";
06158    int res;
06159    int authmethods = 0;
06160    if (ies->authmethods)
06161       authmethods = ies->authmethods;
06162    if (ies->username)
06163       ast_copy_string(peer, ies->username, sizeof(peer));
06164    if (ies->challenge)
06165       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06166    memset(&ied, 0, sizeof(ied));
06167    reg = iaxs[callno]->reg;
06168    if (reg) {
06169          if (inaddrcmp(&reg->addr, sin)) {
06170             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06171             return -1;
06172          }
06173          if (ast_strlen_zero(reg->secret)) {
06174             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06175             reg->regstate = REG_STATE_NOAUTH;
06176             return -1;
06177          }
06178          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06179          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06180          if (reg->secret[0] == '[') {
06181             char tmpkey[256];
06182             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06183             tmpkey[strlen(tmpkey) - 1] = '\0';
06184             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
06185          } else
06186             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
06187          if (!res) {
06188             reg->regstate = REG_STATE_AUTHSENT;
06189             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06190          } else
06191             return -1;
06192          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06193    } else   
06194       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06195    return -1;
06196 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4611 of file chan_iax2.c.

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

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

04612 {
04613    switch(regstate) {
04614    case REG_STATE_UNREGISTERED:
04615       return "Unregistered";
04616    case REG_STATE_REGSENT:
04617       return "Request Sent";
04618    case REG_STATE_AUTHSENT:
04619       return "Auth. Sent";
04620    case REG_STATE_REGISTERED:
04621       return "Registered";
04622    case REG_STATE_REJECTED:
04623       return "Rejected";
04624    case REG_STATE_TIMEOUT:
04625       return "Timeout";
04626    case REG_STATE_NOAUTH:
04627       return "No Authentication";
04628    default:
04629       return "Unknown";
04630    }
04631 }

static int reload ( void   )  [static]

Definition at line 10049 of file chan_iax2.c.

References reload_config().

10050 {
10051    return reload_config();
10052 }

static int reload_config ( void   )  [static]

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

10024 {
10025    char *config = "iax.conf";
10026    struct iax2_registry *reg;
10027 
10028    if (set_config(config, 1) > 0) {
10029       prune_peers();
10030       prune_users();
10031       AST_LIST_LOCK(&registrations);
10032       AST_LIST_TRAVERSE(&registrations, reg, entry)
10033          iax2_do_register(reg);
10034       AST_LIST_UNLOCK(&registrations);
10035       /* Qualify hosts, too */
10036       poke_all_peers();
10037    }
10038    reload_firmware(0);
10039    iax_provision_reload();
10040 
10041    return 0;
10042 }

static void reload_firmware ( int  unload  )  [static]

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

01736 {
01737    struct iax_firmware *cur, *curl, *curp;
01738    DIR *fwd;
01739    struct dirent *de;
01740    char dir[256];
01741    char fn[256];
01742    /* Mark all as dead */
01743    ast_mutex_lock(&waresl.lock);
01744    cur = waresl.wares;
01745    while(cur) {
01746       cur->dead = 1;
01747       cur = cur->next;
01748    }
01749 
01750    /* Now that we've freed them, load the new ones */
01751    if (!unload) {
01752       snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
01753       fwd = opendir(dir);
01754       if (fwd) {
01755          while((de = readdir(fwd))) {
01756             if (de->d_name[0] != '.') {
01757                snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
01758                if (!try_firmware(fn)) {
01759                   if (option_verbose > 1)
01760                      ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
01761                }
01762             }
01763          }
01764          closedir(fwd);
01765       } else 
01766          ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
01767    }
01768 
01769    /* Clean up leftovers */
01770    cur = waresl.wares;
01771    curp = NULL;
01772    while(cur) {
01773       curl = cur;
01774       cur = cur->next;
01775       if (curl->dead) {
01776          if (curp) {
01777             curp->next = cur;
01778          } else {
01779             waresl.wares = cur;
01780          }
01781          destroy_firmware(curl);
01782       } else {
01783          curp = cur;
01784       }
01785    }
01786    ast_mutex_unlock(&waresl.lock);
01787 }

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

Definition at line 6655 of file chan_iax2.c.

References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iaxs, ies, iax_rr::jitter, iax_rr::losscnt, iax_rr::losspct, iax_rr::ooo, iax_rr::packets, and chan_iax2_pvt::remote_rr.

Referenced by socket_process().

06656 {
06657    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06658    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06659    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06660    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06661    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06662    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06663    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06664 }

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

Definition at line 8827 of file chan_iax2.c.

References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), option_debug, and sched.

Referenced by start_network_thread().

08828 {
08829    int count;
08830    int res;
08831    struct timeval tv;
08832    struct timespec ts;
08833 
08834    for (;;) {
08835       res = ast_sched_wait(sched);
08836       if ((res > 1000) || (res < 0))
08837          res = 1000;
08838       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
08839       ts.tv_sec = tv.tv_sec;
08840       ts.tv_nsec = tv.tv_usec * 1000;
08841 
08842       pthread_testcancel();
08843       ast_mutex_lock(&sched_lock);
08844       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
08845       ast_mutex_unlock(&sched_lock);
08846       pthread_testcancel();
08847 
08848       count = ast_sched_runq(sched);
08849       if (option_debug && count >= 20)
08850          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
08851    }
08852    return NULL;
08853 }

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 2529 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, sched, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

02530 {
02531    int type, len;
02532    int ret;
02533    int needfree = 0;
02534    struct ast_channel *owner = NULL;
02535    struct ast_channel *bridge = NULL;
02536    
02537    /* Attempt to recover wrapped timestamps */
02538    unwrap_timestamp(fr);
02539 
02540    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02541    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02542       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02543    else {
02544 #if 0
02545       if (option_debug)
02546          ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02547 #endif
02548       fr->af.delivery = ast_tv(0,0);
02549    }
02550 
02551    type = JB_TYPE_CONTROL;
02552    len = 0;
02553 
02554    if(fr->af.frametype == AST_FRAME_VOICE) {
02555       type = JB_TYPE_VOICE;
02556       len = ast_codec_get_samples(&fr->af) / 8;
02557    } else if(fr->af.frametype == AST_FRAME_CNG) {
02558       type = JB_TYPE_SILENCE;
02559    }
02560 
02561    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02562       if (tsout)
02563          *tsout = fr->ts;
02564       __do_deliver(fr);
02565       return -1;
02566    }
02567 
02568    if ((owner = iaxs[fr->callno]->owner))
02569       bridge = ast_bridged_channel(owner);
02570 
02571    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02572     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02573    if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
02574       jb_frame frame;
02575 
02576       /* deliver any frames in the jb */
02577       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
02578          __do_deliver(frame.data);
02579          /* __do_deliver() can make the call disappear */
02580          if (!iaxs[fr->callno])
02581             return -1;
02582       }
02583 
02584       jb_reset(iaxs[fr->callno]->jb);
02585 
02586       AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
02587 
02588       /* deliver this frame now */
02589       if (tsout)
02590          *tsout = fr->ts;
02591       __do_deliver(fr);
02592       return -1;
02593    }
02594 
02595    /* insert into jitterbuffer */
02596    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02597    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02598          calc_rxstamp(iaxs[fr->callno],fr->ts));
02599    if (ret == JB_DROP) {
02600       needfree++;
02601    } else if (ret == JB_SCHED) {
02602       update_jbsched(iaxs[fr->callno]);
02603    }
02604    if (tsout)
02605       *tsout = fr->ts;
02606    if (needfree) {
02607       /* Free our iax frame */
02608       iax2_frame_free(fr);
02609       return -1;
02610    }
02611    return 0;
02612 }

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

Definition at line 4895 of file chan_iax2.c.

References __send_command().

Referenced by __attempt_transmit(), __send_lagrq(), __send_ping(), authenticate_reply(), authenticate_request(), cache_get_callno_locked(), dp_lookup(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_indicate(), iax2_poke_peer(), iax2_provision(), iax2_start_transfer(), registry_authrequest(), registry_rerequest(), send_command_locked(), and socket_process().

04896 {
04897    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
04898 }

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

04915 {
04916    int call_num = i->callno;
04917    /* It is assumed that the callno has already been locked */
04918    iax2_predestroy(i->callno);
04919    if (!iaxs[call_num])
04920       return -1;
04921    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
04922 }

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

Definition at line 4924 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

04925 {
04926    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
04927 }

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

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

04901 {
04902    int res;
04903    ast_mutex_lock(&iaxsl[callno]);
04904    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
04905    ast_mutex_unlock(&iaxsl[callno]);
04906    return res;
04907 }

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

Definition at line 4929 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

04930 {
04931    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
04932 }

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

Definition at line 1027 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

01028 {
01029 #ifdef SCHED_MULTITHREADED
01030    if (schedule_action(__send_lagrq, data))
01031 #endif      
01032       __send_lagrq(data);
01033    return 0;
01034 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 1860 of file chan_iax2.c.

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

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

01861 {
01862    int res;
01863    int callno;
01864 
01865    if( f == NULL ) {
01866        ast_log(LOG_ERROR, "send_packet( NULL )\n");
01867        ast_backtrace();
01868        return -1;
01869    }
01870    
01871    callno = f->callno;
01872 
01873    /* Don't send if there was an error, but return error instead */
01874    if (!callno || !iaxs[callno] || iaxs[callno]->error)
01875        return -1;
01876    
01877    /* Called with iaxsl held */
01878    if (option_debug > 2 && iaxdebug)
01879       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));
01880    if (f->transfer) {
01881       if (iaxdebug)
01882          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
01883       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
01884                sizeof(iaxs[callno]->transfer));
01885    } else {
01886       if (iaxdebug)
01887          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
01888       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
01889                sizeof(iaxs[callno]->addr));
01890    }
01891    if (res < 0) {
01892       if (option_debug && iaxdebug)
01893          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01894       handle_error();
01895    } else
01896       res = 0;
01897    return res;
01898 }

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

Definition at line 992 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

00993 {
00994 #ifdef SCHED_MULTITHREADED
00995    if (schedule_action(__send_ping, data))
00996 #endif      
00997       __send_ping(data);
00998    return 0;
00999 }

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

Definition at line 6333 of file chan_iax2.c.

References iax2_trunk_peer::addr, iax_frame::afdata, ast_inet_ntoa(), ast_log(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, globalflags, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_hdr::metacmd, option_debug, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.

Referenced by timing_read().

06334 {
06335    int res = 0;
06336    struct iax_frame *fr;
06337    struct ast_iax2_meta_hdr *meta;
06338    struct ast_iax2_meta_trunk_hdr *mth;
06339    int calls = 0;
06340    
06341    /* Point to frame */
06342    fr = (struct iax_frame *)tpeer->trunkdata;
06343    /* Point to meta data */
06344    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06345    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06346    if (tpeer->trunkdatalen) {
06347       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06348       meta->zeros = 0;
06349       meta->metacmd = IAX_META_TRUNK;
06350       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06351          meta->cmddata = IAX_META_TRUNK_MINI;
06352       else
06353          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06354       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06355       /* And the rest of the ast_iax2 header */
06356       fr->direction = DIRECTION_OUTGRESS;
06357       fr->retrans = -1;
06358       fr->transfer = 0;
06359       /* Any appropriate call will do */
06360       fr->data = fr->afdata;
06361       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06362       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06363       calls = tpeer->calls;
06364 #if 0
06365       if (option_debug)
06366          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));
06367 #endif      
06368       /* Reset transmit trunk side data */
06369       tpeer->trunkdatalen = 0;
06370       tpeer->calls = 0;
06371    }
06372    if (res < 0)
06373       return res;
06374    return calls;
06375 }

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

Load configuration.

Definition at line 9655 of file chan_iax2.c.

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

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

09656 {
09657    struct ast_config *cfg, *ucfg;
09658    int capability=iax2_capability;
09659    struct ast_variable *v;
09660    char *cat;
09661    const char *utype;
09662    const char *tosval;
09663    int format;
09664    int portno = IAX_DEFAULT_PORTNO;
09665    int  x;
09666    struct iax2_user *user;
09667    struct iax2_peer *peer;
09668    struct ast_netsock *ns;
09669 #if 0
09670    static unsigned short int last_port=0;
09671 #endif
09672 
09673    cfg = ast_config_load(config_file);
09674    
09675    if (!cfg) {
09676       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
09677       return -1;
09678    }
09679 
09680    if (reload) {
09681       set_config_destroy();
09682    }
09683 
09684    /* Reset global codec prefs */   
09685    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
09686    
09687    /* Reset Global Flags */
09688    memset(&globalflags, 0, sizeof(globalflags));
09689    ast_set_flag(&globalflags, IAX_RTUPDATE);
09690 
09691 #ifdef SO_NO_CHECK
09692    nochecksums = 0;
09693 #endif
09694 
09695    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09696    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
09697 
09698    maxauthreq = 3;
09699 
09700    v = ast_variable_browse(cfg, "general");
09701 
09702    /* Seed initial tos value */
09703    tosval = ast_variable_retrieve(cfg, "general", "tos");
09704    if (tosval) {
09705       if (ast_str2tos(tosval, &tos))
09706          ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n");
09707    }
09708    while(v) {
09709       if (!strcasecmp(v->name, "bindport")){ 
09710          if (reload)
09711             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
09712          else
09713             portno = atoi(v->value);
09714       } else if (!strcasecmp(v->name, "pingtime")) 
09715          ping_time = atoi(v->value);
09716       else if (!strcasecmp(v->name, "iaxthreadcount")) {
09717          if (reload) {
09718             if (atoi(v->value) != iaxthreadcount)
09719                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
09720          } else {
09721             iaxthreadcount = atoi(v->value);
09722             if (iaxthreadcount < 1) {
09723                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
09724                iaxthreadcount = 1;
09725             } else if (iaxthreadcount > 256) {
09726                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
09727                iaxthreadcount = 256;
09728             }
09729          }
09730       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
09731          if (reload) {
09732             AST_LIST_LOCK(&dynamic_list);
09733             iaxmaxthreadcount = atoi(v->value);
09734             AST_LIST_UNLOCK(&dynamic_list);
09735          } else {
09736             iaxmaxthreadcount = atoi(v->value);
09737             if (iaxmaxthreadcount < 0) {
09738                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
09739                iaxmaxthreadcount = 0;
09740             } else if (iaxmaxthreadcount > 256) {
09741                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
09742                iaxmaxthreadcount = 256;
09743             }
09744          }
09745       } else if (!strcasecmp(v->name, "nochecksums")) {
09746 #ifdef SO_NO_CHECK
09747          if (ast_true(v->value))
09748             nochecksums = 1;
09749          else
09750             nochecksums = 0;
09751 #else
09752          if (ast_true(v->value))
09753             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
09754 #endif
09755       }
09756       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
09757          maxjitterbuffer = atoi(v->value);
09758       else if (!strcasecmp(v->name, "resyncthreshold")) 
09759          resyncthreshold = atoi(v->value);
09760       else if (!strcasecmp(v->name, "maxjitterinterps")) 
09761          maxjitterinterps = atoi(v->value);
09762       else if (!strcasecmp(v->name, "lagrqtime")) 
09763          lagrq_time = atoi(v->value);
09764       else if (!strcasecmp(v->name, "maxregexpire")) 
09765          max_reg_expire = atoi(v->value);
09766       else if (!strcasecmp(v->name, "minregexpire")) 
09767          min_reg_expire = atoi(v->value);
09768       else if (!strcasecmp(v->name, "bindaddr")) {
09769          if (reload) {
09770             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
09771          } else {
09772             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) {
09773                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
09774             } else {
09775                if (option_verbose > 1) {
09776                   if (strchr(v->value, ':'))
09777                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value);
09778                   else
09779                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno);
09780                }
09781                if (defaultsockfd < 0) 
09782                   defaultsockfd = ast_netsock_sockfd(ns);
09783                ast_netsock_unref(ns);
09784             }
09785          }
09786       } else if (!strcasecmp(v->name, "authdebug"))
09787          authdebug = ast_true(v->value);
09788       else if (!strcasecmp(v->name, "encryption"))
09789          iax2_encryption = get_encrypt_methods(v->value);
09790       else if (!strcasecmp(v->name, "notransfer")) {
09791          ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09792          ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09793          ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER);   
09794       } else if (!strcasecmp(v->name, "transfer")) {
09795          if (!strcasecmp(v->value, "mediaonly")) {
09796             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
09797          } else if (ast_true(v->value)) {
09798             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09799          } else 
09800             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09801       } else if (!strcasecmp(v->name, "codecpriority")) {
09802          if(!strcasecmp(v->value, "caller"))
09803             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
09804          else if(!strcasecmp(v->value, "disabled"))
09805             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09806          else if(!strcasecmp(v->value, "reqonly")) {
09807             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
09808             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
09809          }
09810       } else if (!strcasecmp(v->name, "jitterbuffer"))
09811          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
09812       else if (!strcasecmp(v->name, "forcejitterbuffer"))
09813          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
09814       else if (!strcasecmp(v->name, "delayreject"))
09815          delayreject = ast_true(v->value);
09816       else if (!strcasecmp(v->name, "rtcachefriends"))
09817          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
09818       else if (!strcasecmp(v->name, "rtignoreregexpire"))
09819          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
09820       else if (!strcasecmp(v->name, "rtupdate"))
09821          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
09822       else if (!strcasecmp(v->name, "trunktimestamps"))
09823          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
09824       else if (!strcasecmp(v->name, "rtautoclear")) {
09825          int i = atoi(v->value);
09826          if(i > 0)
09827             global_rtautoclear = i;
09828          else
09829             i = 0;
09830          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
09831       } else if (!strcasecmp(v->name, "trunkfreq")) {
09832          trunkfreq = atoi(v->value);
09833          if (trunkfreq < 10)
09834             trunkfreq = 10;
09835       } else if (!strcasecmp(v->name, "autokill")) {
09836          if (sscanf(v->value, "%d", &x) == 1) {
09837             if (x >= 0)
09838                autokill = x;
09839             else
09840                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
09841          } else if (ast_true(v->value)) {
09842             autokill = DEFAULT_MAXMS;
09843          } else {
09844             autokill = 0;
09845          }
09846       } else if (!strcasecmp(v->name, "bandwidth")) {
09847          if (!strcasecmp(v->value, "low")) {
09848             capability = IAX_CAPABILITY_LOWBANDWIDTH;
09849          } else if (!strcasecmp(v->value, "medium")) {
09850             capability = IAX_CAPABILITY_MEDBANDWIDTH;
09851          } else if (!strcasecmp(v->value, "high")) {
09852             capability = IAX_CAPABILITY_FULLBANDWIDTH;
09853          } else
09854             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
09855       } else if (!strcasecmp(v->name, "allow")) {
09856          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
09857       } else if (!strcasecmp(v->name, "disallow")) {
09858          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
09859       } else if (!strcasecmp(v->name, "register")) {
09860          iax2_register(v->value, v->lineno);
09861       } else if (!strcasecmp(v->name, "iaxcompat")) {
09862          iaxcompat = ast_true(v->value);
09863       } else if (!strcasecmp(v->name, "regcontext")) {
09864          ast_copy_string(regcontext, v->value, sizeof(regcontext));
09865          /* Create context if it doesn't exist already */
09866          if (!ast_context_find(regcontext))
09867             ast_context_create(NULL, regcontext, "IAX2");
09868       } else if (!strcasecmp(v->name, "tos")) {
09869          if (ast_str2tos(v->value, &tos))
09870             ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno);
09871       } else if (!strcasecmp(v->name, "accountcode")) {
09872          ast_copy_string(accountcode, v->value, sizeof(accountcode));
09873       } else if (!strcasecmp(v->name, "mohinterpret")) {
09874          ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret));
09875       } else if (!strcasecmp(v->name, "mohsuggest")) {
09876          ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest));
09877       } else if (!strcasecmp(v->name, "amaflags")) {
09878          format = ast_cdr_amaflags2int(v->value);
09879          if (format < 0) {
09880             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09881          } else {
09882             amaflags = format;
09883          }
09884       } else if (!strcasecmp(v->name, "language")) {
09885          ast_copy_string(language, v->value, sizeof(language));
09886       } else if (!strcasecmp(v->name, "maxauthreq")) {
09887          maxauthreq = atoi(v->value);
09888          if (maxauthreq < 0)
09889             maxauthreq = 0;
09890       } else if (!strcasecmp(v->name, "adsi")) {
09891          adsi = ast_true(v->value);
09892       } /*else if (strcasecmp(v->name,"type")) */
09893       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09894       v = v->next;
09895    }
09896    
09897    if (defaultsockfd < 0) {
09898       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) {
09899          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
09900       } else {
09901          if (option_verbose > 1)
09902             ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
09903          defaultsockfd = ast_netsock_sockfd(ns);
09904          ast_netsock_unref(ns);
09905       }
09906    }
09907    if (reload) {
09908       ast_netsock_release(outsock);
09909       outsock = ast_netsock_list_alloc();
09910       if (!outsock) {
09911          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
09912          return -1;
09913       }
09914       ast_netsock_init(outsock);
09915    }
09916 
09917    if (min_reg_expire > max_reg_expire) {
09918       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
09919          min_reg_expire, max_reg_expire, max_reg_expire);
09920       min_reg_expire = max_reg_expire;
09921    }
09922    iax2_capability = capability;
09923    
09924    ucfg = ast_config_load("users.conf");
09925    if (ucfg) {
09926       struct ast_variable *gen;
09927       int genhasiax;
09928       int genregisteriax;
09929       const char *hasiax, *registeriax;
09930       
09931       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
09932       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
09933       gen = ast_variable_browse(ucfg, "general");
09934       cat = ast_category_browse(ucfg, NULL);
09935       while (cat) {
09936          if (strcasecmp(cat, "general")) {
09937             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
09938             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
09939             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
09940                /* Start with general parameters, then specific parameters, user and peer */
09941                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
09942                if (user) {
09943                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09944                   user = user_unref(user);
09945                }
09946                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
09947                if (peer) {
09948                   if (ast_test_flag(peer, IAX_DYNAMIC))
09949                      reg_source_db(peer);
09950                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09951                   peer = peer_unref(peer);
09952                }
09953             }
09954             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
09955                char tmp[256];
09956                const char *host = ast_variable_retrieve(ucfg, cat, "host");
09957                const char *username = ast_variable_retrieve(ucfg, cat, "username");
09958                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
09959                if (!host)
09960                   host = ast_variable_retrieve(ucfg, "general", "host");
09961                if (!username)
09962                   username = ast_variable_retrieve(ucfg, "general", "username");
09963                if (!secret)
09964                   secret = ast_variable_retrieve(ucfg, "general", "secret");
09965                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
09966                   if (!ast_strlen_zero(secret))
09967                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
09968                   else
09969                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
09970                   iax2_register(tmp, 0);
09971                }
09972             }
09973          }
09974          cat = ast_category_browse(ucfg, cat);
09975       }
09976       ast_config_destroy(ucfg);
09977    }
09978    
09979    cat = ast_category_browse(cfg, NULL);
09980    while(cat) {
09981       if (strcasecmp(cat, "general")) {
09982          utype = ast_variable_retrieve(cfg, cat, "type");
09983          if (utype) {
09984             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
09985                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
09986                if (user) {
09987                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09988                   user = user_unref(user);
09989                }
09990             }
09991             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
09992                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
09993                if (peer) {
09994                   if (ast_test_flag(peer, IAX_DYNAMIC))
09995                      reg_source_db(peer);
09996                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
09997                   peer = peer_unref(peer);
09998                }
09999             } else if (strcasecmp(utype, "user")) {
10000                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
10001             }
10002          } else
10003             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
10004       }
10005       cat = ast_category_browse(cfg, cat);
10006    }
10007    ast_config_destroy(cfg);
10008    set_timing();
10009    return 1;
10010 }

static void set_config_destroy ( void   )  [static]

Definition at line 9639 of file chan_iax2.c.

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

Referenced by set_config().

09640 {
09641    strcpy(accountcode, "");
09642    strcpy(language, "");
09643    strcpy(mohinterpret, "default");
09644    strcpy(mohsuggest, "");
09645    amaflags = 0;
09646    delayreject = 0;
09647    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09648    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09649    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09650    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09651    delete_users();
09652 }

static void set_timing ( void   )  [static]

Definition at line 9624 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09625 {
09626 #ifdef HAVE_ZAPTEL
09627    int bs = trunkfreq * 8;
09628    if (timingfd > -1) {
09629       if (
09630 #ifdef ZT_TIMERACK
09631          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09632 #endif         
09633          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09634          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09635    }
09636 #endif
09637 }

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

Definition at line 758 of file chan_iax2.c.

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

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

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

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6807 of file chan_iax2.c.

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

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

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

Definition at line 6729 of file chan_iax2.c.

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

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

06730 {
06731    struct iax2_thread *thread;
06732    socklen_t len;
06733    time_t t;
06734    static time_t last_errtime = 0;
06735    struct ast_iax2_full_hdr *fh;
06736 
06737    if (!(thread = find_idle_thread())) {
06738       time(&t);
06739       if (t != last_errtime && option_debug)
06740          ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n");
06741       last_errtime = t;
06742       usleep(1);
06743       return 1;
06744    }
06745 
06746    len = sizeof(thread->iosin);
06747    thread->iofd = fd;
06748    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06749    thread->buf_size = sizeof(thread->readbuf);
06750    thread->buf = thread->readbuf;
06751    if (thread->buf_len < 0) {
06752       if (errno != ECONNREFUSED && errno != EAGAIN)
06753          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06754       handle_error();
06755       thread->iostate = IAX_IOSTATE_IDLE;
06756       signal_condition(&thread->lock, &thread->cond);
06757       return 1;
06758    }
06759    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06760       thread->iostate = IAX_IOSTATE_IDLE;
06761       signal_condition(&thread->lock, &thread->cond);
06762       return 1;
06763    }
06764    
06765    /* Determine if this frame is a full frame; if so, and any thread is currently
06766       processing a full frame for the same callno from this peer, then drop this
06767       frame (and the peer will retransmit it) */
06768    fh = (struct ast_iax2_full_hdr *) thread->buf;
06769    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06770       struct iax2_thread *cur = NULL;
06771       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06772       
06773       AST_LIST_LOCK(&active_list);
06774       AST_LIST_TRAVERSE(&active_list, cur, list) {
06775          if ((cur->ffinfo.callno == callno) &&
06776              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06777             break;
06778       }
06779       if (cur) {
06780          /* we found another thread processing a full frame for this call,
06781             so queue it up for processing later. */
06782          defer_full_frame(thread, cur);
06783          AST_LIST_UNLOCK(&active_list);
06784          thread->iostate = IAX_IOSTATE_IDLE;
06785          signal_condition(&thread->lock, &thread->cond);
06786          return 1;
06787       } else {
06788          /* this thread is going to process this frame, so mark it */
06789          thread->ffinfo.callno = callno;
06790          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
06791          thread->ffinfo.type = fh->type;
06792          thread->ffinfo.csub = fh->csub;
06793       }
06794       AST_LIST_UNLOCK(&active_list);
06795    }
06796    
06797    /* Mark as ready and send on its way */
06798    thread->iostate = IAX_IOSTATE_READY;
06799 #ifdef DEBUG_SCHED_MULTITHREAD
06800    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06801 #endif
06802    signal_condition(&thread->lock, &thread->cond);
06803 
06804    return 1;
06805 }

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

Definition at line 6516 of file chan_iax2.c.

References ast_calloc, ast_log(), ast_pthread_create, ast_strdup, dp_lookup_thread(), and LOG_WARNING.

Referenced by socket_process().

06517 {
06518    pthread_t newthread;
06519    struct dpreq_data *dpr;
06520    pthread_attr_t attr;
06521    
06522    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06523       return;
06524 
06525    pthread_attr_init(&attr);
06526    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06527 
06528    dpr->callno = callno;
06529    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06530    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06531    if (callerid)
06532       dpr->callerid = ast_strdup(callerid);
06533    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06534       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06535    }
06536 
06537    pthread_attr_destroy(&attr);
06538 }

static int start_network_thread ( void   )  [static]

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

08923 {
08924    pthread_attr_t attr;
08925    int threadcount = 0;
08926    int x;
08927    for (x = 0; x < iaxthreadcount; x++) {
08928       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
08929       if (thread) {
08930          thread->type = IAX_TYPE_POOL;
08931          thread->threadnum = ++threadcount;
08932          ast_mutex_init(&thread->lock);
08933          ast_cond_init(&thread->cond, NULL);
08934          pthread_attr_init(&attr);
08935          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
08936          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
08937             ast_log(LOG_WARNING, "Failed to create new thread!\n");
08938             free(thread);
08939             thread = NULL;
08940          }
08941          AST_LIST_LOCK(&idle_list);
08942          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
08943          AST_LIST_UNLOCK(&idle_list);
08944       }
08945    }
08946    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
08947    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
08948    if (option_verbose > 1)
08949       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
08950    return 0;
08951 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6198 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06199 {
06200    iax2_destroy_helper(iaxs[callno]);
06201 }

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

Definition at line 6385 of file chan_iax2.c.

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

Referenced by network_thread().

06386 {
06387    char buf[1024];
06388    int res;
06389    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06390    int processed = 0;
06391    int totalcalls = 0;
06392 #ifdef ZT_TIMERACK
06393    int x = 1;
06394 #endif
06395    struct timeval now;
06396    if (iaxtrunkdebug)
06397       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06398    gettimeofday(&now, NULL);
06399    if (events & AST_IO_PRI) {
06400 #ifdef ZT_TIMERACK
06401       /* Great, this is a timing interface, just call the ioctl */
06402       if (ioctl(fd, ZT_TIMERACK, &x)) {
06403          ast_log(LOG_WARNING, "Unable to acknowledge zap timer. IAX trunking will fail!\n");
06404          usleep(1);
06405          return -1;
06406       }
06407 #endif      
06408    } else {
06409       /* Read and ignore from the pseudo channel for timing */
06410       res = read(fd, buf, sizeof(buf));
06411       if (res < 1) {
06412          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06413          return 1;
06414       }
06415    }
06416    /* For each peer that supports trunking... */
06417    ast_mutex_lock(&tpeerlock);
06418    tpeer = tpeers;
06419    while(tpeer) {
06420       processed++;
06421       res = 0;
06422       ast_mutex_lock(&tpeer->lock);
06423       /* We can drop a single tpeer per pass.  That makes all this logic
06424          substantially easier */
06425       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06426          /* Take it out of the list, but don't free it yet, because it
06427             could be in use */
06428          if (prev)
06429             prev->next = tpeer->next;
06430          else
06431             tpeers = tpeer->next;
06432          drop = tpeer;
06433       } else {
06434          res = send_trunk(tpeer, &now);
06435          if (iaxtrunkdebug)
06436             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);
06437       }     
06438       totalcalls += res;   
06439       res = 0;
06440       ast_mutex_unlock(&tpeer->lock);
06441       prev = tpeer;
06442       tpeer = tpeer->next;
06443    }
06444    ast_mutex_unlock(&tpeerlock);
06445    if (drop) {
06446       ast_mutex_lock(&drop->lock);
06447       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06448          because by the time they could get tpeerlock, we've already grabbed it */
06449       if (option_debug)
06450          ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06451       if (drop->trunkdata) {
06452          free(drop->trunkdata);
06453          drop->trunkdata = NULL;
06454       }
06455       ast_mutex_unlock(&drop->lock);
06456       ast_mutex_destroy(&drop->lock);
06457       free(drop);
06458       
06459    }
06460    if (iaxtrunkdebug)
06461       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06462    iaxtrunkdebug =0;
06463    return 1;
06464 }

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

Definition at line 1846 of file chan_iax2.c.

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

Referenced by send_trunk().

01847 {
01848    int res;
01849    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
01850                sizeof(*sin));
01851    if (res < 0) {
01852       if (option_debug)
01853          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01854       handle_error();
01855    } else
01856       res = 0;
01857    return res;
01858 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1534 of file chan_iax2.c.

References ast_calloc, ast_log(), ast_random(), ast_strlen_zero(), MD5Context::buf, ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, errno, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, len, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.

Referenced by reload_firmware().

01535 {
01536    struct stat stbuf;
01537    struct iax_firmware *cur;
01538    int ifd;
01539    int fd;
01540    int res;
01541    
01542    struct ast_iax2_firmware_header *fwh, fwh2;
01543    struct MD5Context md5;
01544    unsigned char sum[16];
01545    unsigned char buf[1024];
01546    int len, chunk;
01547    char *s2;
01548    char *last;
01549    s2 = alloca(strlen(s) + 100);
01550    if (!s2) {
01551       ast_log(LOG_WARNING, "Alloca failed!\n");
01552       return -1;
01553    }
01554    last = strrchr(s, '/');
01555    if (last)
01556       last++;
01557    else
01558       last = s;
01559    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01560    res = stat(s, &stbuf);
01561    if (res < 0) {
01562       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01563       return -1;
01564    }
01565    /* Make sure it's not a directory */
01566    if (S_ISDIR(stbuf.st_mode))
01567       return -1;
01568    ifd = open(s, O_RDONLY);
01569    if (ifd < 0) {
01570       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01571       return -1;
01572    }
01573    fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600);
01574    if (fd < 0) {
01575       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
01576       close(ifd);
01577       return -1;
01578    }
01579    /* Unlink our newly created file */
01580    unlink(s2);
01581    
01582    /* Now copy the firmware into it */
01583    len = stbuf.st_size;
01584    while(len) {
01585       chunk = len;
01586       if (chunk > sizeof(buf))
01587          chunk = sizeof(buf);
01588       res = read(ifd, buf, chunk);
01589       if (res != chunk) {
01590          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01591          close(ifd);
01592          close(fd);
01593          return -1;
01594       }
01595       res = write(fd, buf, chunk);
01596       if (res != chunk) {
01597          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01598          close(ifd);
01599          close(fd);
01600          return -1;
01601       }
01602       len -= chunk;
01603    }
01604    close(ifd);
01605    /* Return to the beginning */
01606    lseek(fd, 0, SEEK_SET);
01607    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
01608       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
01609       close(fd);
01610       return -1;
01611    }
01612    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
01613       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
01614       close(fd);
01615       return -1;
01616    }
01617    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
01618       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
01619       close(fd);
01620       return -1;
01621    }
01622    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
01623       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
01624       close(fd);
01625       return -1;
01626    }
01627    fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
01628    if (fwh == (void *) -1) {
01629       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
01630       close(fd);
01631       return -1;
01632    }
01633    MD5Init(&md5);
01634    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
01635    MD5Final(sum, &md5);
01636    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
01637       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
01638       munmap((void*)fwh, stbuf.st_size);
01639       close(fd);
01640       return -1;
01641    }
01642    cur = waresl.wares;
01643    while(cur) {
01644       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
01645          /* Found a candidate */
01646          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
01647             /* The version we have on loaded is older, load this one instead */
01648             break;
01649          /* This version is no newer than what we have.  Don't worry about it.
01650             We'll consider it a proper load anyhow though */
01651          munmap((void*)fwh, stbuf.st_size);
01652          close(fd);
01653          return 0;
01654       }
01655       cur = cur->next;
01656    }
01657    if (!cur) {
01658       /* Allocate a new one and link it */
01659       if ((cur = ast_calloc(1, sizeof(*cur)))) {
01660          cur->fd = -1;
01661          cur->next = waresl.wares;
01662          waresl.wares = cur;
01663       }
01664    }
01665    if (cur) {
01666       if (cur->fwh) {
01667          munmap((void*)cur->fwh, cur->mmaplen);
01668       }
01669       if (cur->fd > -1)
01670          close(cur->fd);
01671       cur->fwh = fwh;
01672       cur->fd = fd;
01673       cur->mmaplen = stbuf.st_size;
01674       cur->dead = 0;
01675    }
01676    return 0;
01677 }

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

Definition at line 5606 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, ies, LOG_WARNING, send_command_transfer(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.

Referenced by socket_process().

05607 {
05608    int newcall = 0;
05609    char newip[256];
05610    struct iax_ie_data ied;
05611    struct sockaddr_in new;
05612    
05613    
05614    memset(&ied, 0, sizeof(ied));
05615    if (ies->apparent_addr)
05616       bcopy(ies->apparent_addr, &new, sizeof(new));
05617    if (ies->callno)
05618       newcall = ies->callno;
05619    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05620       ast_log(LOG_WARNING, "Invalid transfer request\n");
05621       return -1;
05622    }
05623    pvt->transfercallno = newcall;
05624    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05625    inet_aton(newip, &pvt->transfer.sin_addr);
05626    pvt->transfer.sin_family = AF_INET;
05627    pvt->transferring = TRANSFER_BEGIN;
05628    pvt->transferid = ies->transferid;
05629    if (ies->transferid)
05630       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05631    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05632    return 0; 
05633 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1056 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01057 {
01058    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01059    if (csub & IAX_FLAG_SC_LOG) {
01060       /* special case for 'compressed' -1 */
01061       if (csub == 0xff)
01062          return -1;
01063       else
01064          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01065    }
01066    else
01067       return csub;
01068 }

static void unlink_peer ( struct iax2_peer peer  )  [static]

Definition at line 5872 of file chan_iax2.c.

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

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

05873 {
05874    if (peer->expire > -1) {
05875       if (!ast_sched_del(sched, peer->expire)) {
05876          peer->expire = -1;
05877          peer_unref(peer);
05878       }
05879    }
05880 
05881    if (peer->pokeexpire > -1) {
05882       if (!ast_sched_del(sched, peer->pokeexpire)) {
05883          peer->pokeexpire = -1;
05884          peer_unref(peer);
05885       }
05886    }
05887 
05888    ao2_unlink(peers, peer);
05889 }

static int unload_module ( void   )  [static]

Definition at line 10842 of file chan_iax2.c.

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

10843 {
10844    ast_custom_function_unregister(&iaxpeer_function);
10845    return __unload_module();
10846 }

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

Definition at line 3355 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03356 {
03357    ast_mutex_unlock(&iaxsl[callno1]);
03358    ast_mutex_unlock(&iaxsl[callno0]);
03359 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

02385 {
02386    int x;
02387 
02388    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02389       x = fr->ts - iaxs[fr->callno]->last;
02390       if (x < -50000) {
02391          /* Sudden big jump backwards in timestamp:
02392             What likely happened here is that miniframe timestamp has circled but we haven't
02393             gotten the update from the main packet.  We'll just pretend that we did, and
02394             update the timestamp appropriately. */
02395          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02396          if (option_debug && iaxdebug)
02397             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02398       }
02399       if (x > 50000) {
02400          /* Sudden apparent big jump forwards in timestamp:
02401             What's likely happened is this is an old miniframe belonging to the previous
02402             top-16-bit timestamp that has turned up out of order.
02403             Adjust the timestamp appropriately. */
02404          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02405          if (option_debug && iaxdebug)
02406             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02407       }
02408    }
02409 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2413 of file chan_iax2.c.

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

Referenced by __get_from_jb(), and schedule_delivery().

02414 {
02415    int when;
02416    
02417    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02418    
02419    when = jb_next(pvt->jb) - when;
02420 
02421    AST_SCHED_DEL(sched, pvt->jbid);
02422 
02423    if(when <= 0) {
02424       /* XXX should really just empty until when > 0.. */
02425       when = 1;
02426    }
02427    
02428    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02429 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1276 of file chan_iax2.c.

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

Referenced by find_callno().

01277 {
01278    int max = 1;
01279    int x;
01280    /* XXX Prolly don't need locks here XXX */
01281    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01282       if (iaxs[x])
01283          max = x + 1;
01284    }
01285    maxnontrunkcall = max;
01286    if (option_debug && iaxdebug)
01287       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01288 }

static void update_max_trunk ( void   )  [static]

Definition at line 1262 of file chan_iax2.c.

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

Referenced by iax2_destroy().

01263 {
01264    int max = TRUNK_CALL_START;
01265    int x;
01266    /* XXX Prolly don't need locks here XXX */
01267    for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
01268       if (iaxs[x])
01269          max = x + 1;
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 2021 of file chan_iax2.c.

References ast_iax2_full_hdr::dcallno, f, IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, and chan_iax2_pvt::iseqno.

Referenced by __attempt_transmit().

02022 {
02023    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02024    struct ast_iax2_full_hdr *fh = f->data;
02025    /* Mark this as a retransmission */
02026    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02027    /* Update iseqno */
02028    f->iseqno = iaxs[f->callno]->iseqno;
02029    fh->iseqno = f->iseqno;
02030    return 0;
02031 }

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

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

Referenced by socket_process().

05984 {
05985    /* Called from IAX thread only, with proper iaxsl lock */
05986    struct iax_ie_data ied;
05987    struct iax2_peer *p;
05988    int msgcount;
05989    char data[80];
05990    int version;
05991    const char *peer_name;
05992    int res = -1;
05993 
05994    memset(&ied, 0, sizeof(ied));
05995 
05996    peer_name = ast_strdupa(iaxs[callno]->peer);
05997 
05998    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
05999    ast_mutex_unlock(&iaxsl[callno]);
06000    if (!(p = find_peer(peer_name, 1))) {
06001       ast_mutex_lock(&iaxsl[callno]);
06002       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06003       return -1;
06004    }
06005    ast_mutex_lock(&iaxsl[callno]);
06006    if (!iaxs[callno])
06007       goto return_unref;
06008 
06009    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
06010       if (sin->sin_addr.s_addr) {
06011          time_t nowtime;
06012          time(&nowtime);
06013          realtime_update_peer(peer_name, sin, nowtime);
06014       } else {
06015          realtime_update_peer(peer_name, sin, 0);
06016       }
06017    }
06018    if (inaddrcmp(&p->addr, sin)) {
06019       if (iax2_regfunk)
06020          iax2_regfunk(p->name, 1);
06021       /* Stash the IP address from which they registered */
06022       memcpy(&p->addr, sin, sizeof(p->addr));
06023       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
06024       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
06025          ast_db_put("IAX/Registry", p->name, data);
06026          if  (option_verbose > 2)
06027             ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 
06028                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
06029          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
06030          register_peer_exten(p, 1);
06031          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06032       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
06033          if  (option_verbose > 2)
06034             ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 
06035                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
06036          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
06037          register_peer_exten(p, 0);
06038          ast_db_del("IAX/Registry", p->name);
06039          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06040       }
06041       /* Update the host */
06042       /* Verify that the host is really there */
06043       iax2_poke_peer(p, callno);
06044    }     
06045 
06046    /* Make sure our call still exists, an INVAL at the right point may make it go away */
06047    if (!iaxs[callno]) {
06048       res = 0;
06049       goto return_unref;
06050    }
06051 
06052    /* Store socket fd */
06053    p->sockfd = fd;
06054    /* Setup the expiry */
06055    if (p->expire > -1) {
06056       if (!ast_sched_del(sched, p->expire)) {
06057          p->expire = -1;
06058          peer_unref(p);
06059       }
06060    }
06061    /* treat an unspecified refresh interval as the minimum */
06062    if (!refresh)
06063       refresh = min_reg_expire;
06064    if (refresh > max_reg_expire) {
06065       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06066          p->name, max_reg_expire, refresh);
06067       p->expiry = max_reg_expire;
06068    } else if (refresh < min_reg_expire) {
06069       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06070          p->name, min_reg_expire, refresh);
06071       p->expiry = min_reg_expire;
06072    } else {
06073       p->expiry = refresh;
06074    }
06075    if (p->expiry && sin->sin_addr.s_addr) {
06076       p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06077       if (p->expire == -1)
06078          peer_unref(p);
06079    }
06080    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
06081    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
06082    if (sin->sin_addr.s_addr) {
06083       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
06084       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
06085       if (!ast_strlen_zero(p->mailbox)) {
06086          int new, old;
06087          ast_app_inboxcount(p->mailbox, &new, &old);
06088          if (new > 255)
06089             new = 255;
06090          if (old > 255)
06091             old = 255;
06092          msgcount = (old << 8) | new;
06093          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
06094       }
06095       if (ast_test_flag(p, IAX_HASCALLERID)) {
06096          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
06097          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
06098       }
06099    }
06100    version = iax_check_version(devtype);
06101    if (version) 
06102       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
06103 
06104    res = 0;
06105 
06106 return_unref:
06107    peer_unref(p);
06108 
06109    return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
06110 }

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

Referenced by load_module().

01104 {
01105    struct iax2_user *user = obj, *user2 = arg;
01106 
01107    return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
01108 }

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

Definition at line 9562 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09563 {
09564    struct iax2_user *user = obj;
09565 
09566    ast_set_flag(user, IAX_DELME);
09567 
09568    return 0;
09569 }

static void user_destructor ( void *  obj  )  [static]

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

09327 {
09328    struct iax2_user *user = obj;
09329 
09330    ast_free_ha(user->ha);
09331    free_context(user->contexts);
09332    if(user->vars) {
09333       ast_variables_destroy(user->vars);
09334       user->vars = NULL;
09335    }
09336    ast_string_field_free_memory(user);
09337 }

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

References ast_str_hash().

Referenced by load_module().

01094 {
01095    const struct iax2_user *user = obj;
01096 
01097    return ast_str_hash(user->name);
01098 }

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

Definition at line 1142 of file chan_iax2.c.

References ao2_ref().

01143 {
01144    ao2_ref(user, +1);
01145    return user;
01146 }

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

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

01149 {
01150    ao2_ref(user, -1);
01151    return NULL;
01152 }

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

Definition at line 6299 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, f, iaxq, iaxs, and send_packet().

Referenced by socket_process().

06300 {
06301    struct iax_frame *f;
06302 
06303    AST_LIST_LOCK(&iaxq.queue);
06304    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06305       /* Send a copy immediately */
06306       if ((f->callno == callno) && iaxs[f->callno] &&
06307          ((unsigned char ) (f->oseqno - last) < 128) &&
06308          (f->retries >= 0)) {
06309          send_packet(f);
06310       }
06311    }
06312    AST_LIST_UNLOCK(&iaxq.queue);
06313 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 220 of file chan_iax2.c.

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

int adsi = 0 [static]

Definition at line 224 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

Definition at line 223 of file chan_iax2.c.

Referenced by build_device(), build_gateway(), and pgsql_log().

int authdebug = 1 [static]

Definition at line 160 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 161 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10662 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry cli_iax2_jb_debug_deprecated [static]

Initial value:

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

Definition at line 10642 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_debug_deprecated [static]

Initial value:

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

Definition at line 10647 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_jb_debug_deprecated [static]

Initial value:

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

Definition at line 10657 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_trunk_debug_deprecated [static]

Initial value:

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

Definition at line 10652 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_trunk_debug_deprecated [static]

Initial value:

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

Definition at line 10637 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 10611 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 10603 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 10595 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 177 of file chan_iax2.c.

int delayreject = 0 [static]

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

struct ast_flags globalflags = { 0 } [static]

Definition at line 228 of file chan_iax2.c.

Referenced by __expire_registry(), aji_create_client(), aji_load_config(), build_peer(), build_user(), find_callno(), find_or_create(), find_user(), find_user_realtime(), forward_message(), iax2_request(), iax2_trunk_queue(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), send_trunk(), sendmail(), set_config(), set_config_destroy(), update_registry(), and vm_execmain().

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 206 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 226 of file chan_iax2.c.

enum { ... } iax2_flags

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

Definition at line 179 of file chan_iax2.c.

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

char iax2_reload_usage[] [static]

Initial value:

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

Definition at line 10553 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10527 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

Definition at line 849 of file chan_iax2.c.

Referenced by __unload_module(), ast_iax2_new(), function_iaxpeer(), iax2_bridge(), iax2_prov_app(), and load_module().

char iax2_test_losspct_usage[] [static]

Initial value:

"Usage: iax2 test losspct <percentage>\n"
"       For testing, throws away <percentage> percent of incoming packets\n"

Definition at line 10619 of file chan_iax2.c.

int iaxactivethreadcount = 0 [static]

Definition at line 454 of file chan_iax2.c.

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

int iaxcompat = 0 [static]

Definition at line 162 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 208 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 164 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 166 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 453 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 452 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 10463 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

Referenced by __attempt_transmit(), __unload_module(), complete_transfer(), iax2_destroy(), iax2_show_stats(), iax2_transmit(), load_module(), network_thread(), socket_process(), and vnak_retransmit().

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

Definition at line 813 of file chan_iax2.c.

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

ast_mutex_t iaxsl[IAX_MAX_CALLS] [static]

Definition at line 814 of file chan_iax2.c.

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

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 451 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 210 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 203 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[IAX_MAX_CALLS] [static]

Definition at line 815 of file chan_iax2.c.

int max_reg_expire [static]

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

int maxjitterinterps = 10 [static]

Definition at line 158 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 155 of file chan_iax2.c.

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 154 of file chan_iax2.c.

int min_reg_expire [static]

Definition at line 170 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 221 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 222 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 175 of file chan_iax2.c.

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

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 230 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 10615 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 10607 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 10599 of file chan_iax2.c.

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 176 of file chan_iax2.c.

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

char* papp = "IAX2Provision" [static]

Definition at line 8576 of file chan_iax2.c.

char* pdescrip [static]

Initial value:

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

Definition at line 8578 of file chan_iax2.c.

struct ao2_container* peers [static]

Definition at line 651 of file chan_iax2.c.

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

int ping_time = 21 [static]

Definition at line 152 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

Definition at line 141 of file chan_iax2.c.

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

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10549 of file chan_iax2.c.

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

Definition at line 8577 of file chan_iax2.c.

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 148 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 157 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 204 of file chan_iax2.c.

ast_cond_t sched_cond [static]

Definition at line 233 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 231 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 10541 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 10569 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 10587 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 10573 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 10545 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 10581 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10557 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 10591 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 10537 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 10577 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 10564 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 212 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 173 of file chan_iax2.c.

unsigned int tos = 0 [static]

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

struct ao2_container* users [static]

Definition at line 654 of file chan_iax2.c.

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

struct ast_firmware_list waresl [static]

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


Generated on Mon Mar 31 07:39:30 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1