Mon Jul 14 17:25:09 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   ARRAY_LEN(iaxs) / 2
#define TS_GAP_FOR_JB_RESYNC   5000

Enumerations

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

Functions

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

Variables

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


Detailed Description

Implementation of Inter-Asterisk eXchange Version 2.

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

Definition in file chan_iax2.c.


Define Documentation

#define CACHE_FLAG_CANEXIST   (1 << 2)

Extension can exist

Definition at line 664 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 660 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 674 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 662 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 666 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 668 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

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

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 126 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 114 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 134 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 132 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

Definition at line 199 of file chan_iax2.c.

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

#define DEFAULT_FREQ_OK   60 * 1000

Definition at line 198 of file chan_iax2.c.

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 197 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 130 of file chan_iax2.c.

Referenced by __find_callno(), and complete_transfer().

#define DEFAULT_THREAD_COUNT   10

Definition at line 128 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

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

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 180 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 188 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 193 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 182 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 695 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 697 of file chan_iax2.c.

#define IAX_IOSTATE_READY   1

Definition at line 696 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 698 of file chan_iax2.c.

Referenced by __schedule_action().

#define IAX_TYPE_DYNAMIC   2

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

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 117 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

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

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 442 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 651 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 131 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 439 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

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

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

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

Referenced by socket_process().

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

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

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

Definition at line 982 of file chan_iax2.c.

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

#define TRUNK_CALL_START   ARRAY_LEN(iaxs) / 2

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


Enumeration Type Documentation

anonymous enum

Enumerator:
IAX_STATE_STARTED 
IAX_STATE_AUTHENTICATED 
IAX_STATE_TBD 
IAX_STATE_UNCHANGED 

Definition at line 233 of file chan_iax2.c.

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

anonymous enum

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

Definition at line 245 of file chan_iax2.c.

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


Function Documentation

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

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

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

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

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

06339 {
06340    /* Called from IAX thread only, without iaxs lock */
06341    int callno = (int)(long)(nothing);
06342    struct iax_ie_data ied;
06343    ast_mutex_lock(&iaxsl[callno]);
06344    if (iaxs[callno]) {
06345       memset(&ied, 0, sizeof(ied));
06346       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06347          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06348          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06349       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06350          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06351          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06352       }
06353       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06354    }
06355    ast_mutex_unlock(&iaxsl[callno]);
06356 }

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

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

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

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

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

06388 {
06389    /* Called from IAX thread only, without iaxs lock */
06390    int callno = (int)(long)(nothing);
06391    struct iax_ie_data ied;
06392    ast_mutex_lock(&iaxsl[callno]);
06393    if (iaxs[callno]) {
06394       memset(&ied, 0, sizeof(ied));
06395       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06396       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06397       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06398    }
06399    ast_mutex_unlock(&iaxsl[callno]);
06400 }

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

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

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

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

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

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

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

Definition at line 1514 of file chan_iax2.c.

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

Referenced by find_callno(), and find_callno_locked().

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

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

Definition at line 2545 of file chan_iax2.c.

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

Referenced by get_from_jb().

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

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

Definition at line 5719 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05720 {
05721    struct iax2_registry *reg = (struct iax2_registry *)data;
05722    reg->expire = -1;
05723    iax2_do_register(reg);
05724 }

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

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

08806 {
08807    struct iax2_peer *peer = (struct iax2_peer *)data;
08808    int callno;
08809 
08810    if (peer->lastms > -1) {
08811       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08812       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08813       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08814    }
08815    if ((callno = peer->callno) > 0) {
08816       ast_mutex_lock(&iaxsl[callno]);
08817       iax2_destroy(callno);
08818       ast_mutex_unlock(&iaxsl[callno]);
08819    }
08820    peer->callno = 0;
08821    peer->lastms = -1;
08822    /* Try again quickly */
08823    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08824    if (peer->pokeexpire == -1)
08825       peer_unref(peer);
08826 }

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

Definition at line 6450 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06451 {
06452    struct iax2_peer *peer = (struct iax2_peer *)data;
06453    iax2_poke_peer(peer, 0);
06454    peer_unref(peer);
06455 }

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

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

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

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

Definition at line 957 of file chan_iax2.c.

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

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

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

References f, and iax2_send().

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

05012 {
05013    struct ast_frame f = { 0, };
05014 
05015    f.frametype = type;
05016    f.subclass = command;
05017    f.datalen = datalen;
05018    f.src = __FUNCTION__;
05019    f.data = (void *) data;
05020 
05021    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05022 }

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

Definition at line 1037 of file chan_iax2.c.

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

Referenced by send_lagrq().

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

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

Definition at line 997 of file chan_iax2.c.

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

Referenced by send_ping().

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

static int __unload_module ( void   )  [static]

Definition at line 10930 of file chan_iax2.c.

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

Referenced by load_module(), and unload_module().

10931 {
10932    struct iax2_thread *thread = NULL;
10933    int x;
10934 
10935    /* Make sure threads do not hold shared resources when they are canceled */
10936    
10937    /* Grab the sched lock resource to keep it away from threads about to die */
10938    /* Cancel the network thread, close the net socket */
10939    if (netthreadid != AST_PTHREADT_NULL) {
10940       AST_LIST_LOCK(&iaxq.queue);
10941       ast_mutex_lock(&sched_lock);
10942       pthread_cancel(netthreadid);
10943       ast_cond_signal(&sched_cond);
10944       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10945       AST_LIST_UNLOCK(&iaxq.queue);
10946       pthread_join(netthreadid, NULL);
10947    }
10948    if (schedthreadid != AST_PTHREADT_NULL) {
10949       ast_mutex_lock(&sched_lock);  
10950       pthread_cancel(schedthreadid);
10951       ast_cond_signal(&sched_cond);
10952       ast_mutex_unlock(&sched_lock);   
10953       pthread_join(schedthreadid, NULL);
10954    }
10955    
10956    /* Call for all threads to halt */
10957    AST_LIST_LOCK(&idle_list);
10958    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10959       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10960       pthread_cancel(thread->threadid);
10961    }
10962    AST_LIST_TRAVERSE_SAFE_END
10963    AST_LIST_UNLOCK(&idle_list);
10964 
10965    AST_LIST_LOCK(&active_list);
10966    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10967       AST_LIST_REMOVE_CURRENT(&active_list, list);
10968       pthread_cancel(thread->threadid);
10969    }
10970    AST_LIST_TRAVERSE_SAFE_END
10971    AST_LIST_UNLOCK(&active_list);
10972 
10973    AST_LIST_LOCK(&dynamic_list);
10974         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
10975       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
10976       pthread_cancel(thread->threadid);
10977         }
10978    AST_LIST_TRAVERSE_SAFE_END
10979         AST_LIST_UNLOCK(&dynamic_list);
10980 
10981    AST_LIST_HEAD_DESTROY(&iaxq.queue);
10982 
10983    /* Wait for threads to exit */
10984    while(0 < iaxactivethreadcount)
10985       usleep(10000);
10986    
10987    ast_netsock_release(netsock);
10988    ast_netsock_release(outsock);
10989    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
10990       if (iaxs[x]) {
10991          iax2_destroy(x);
10992       }
10993    }
10994    ast_manager_unregister( "IAXpeers" );
10995    ast_manager_unregister( "IAXnetstats" );
10996    ast_unregister_application(papp);
10997    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10998    ast_unregister_switch(&iax2_switch);
10999    ast_channel_unregister(&iax2_tech);
11000    delete_users();
11001    iax_provision_unload();
11002    sched_context_destroy(sched);
11003    reload_firmware(1);
11004 
11005    ast_mutex_destroy(&waresl.lock);
11006 
11007    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11008       ast_mutex_destroy(&iaxsl[x]);
11009    }
11010 
11011    ao2_ref(peers, -1);
11012    ao2_ref(users, -1);
11013    ao2_ref(iax_peercallno_pvts, -1);
11014 
11015    return 0;
11016 }

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

Definition at line 5063 of file chan_iax2.c.

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

Referenced by check_access().

05064 {
05065    while(con) {
05066       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05067          return -1;
05068       con = con->next;
05069    }
05070    return 0;
05071 }

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

Definition at line 4837 of file chan_iax2.c.

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

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

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

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

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

Referenced by iax2_request(), and socket_process().

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

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

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

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

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

06373 {
06374    /* Schedule sending the authentication failure in one second, to prevent
06375       guessing */
06376    if (iaxs[callno]) {
06377       iaxs[callno]->authfail = failcode;
06378       if (delayreject) {
06379          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06380          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06381       } else
06382          auth_reject((void *)(long)callno);
06383    }
06384    return 0;
06385 }

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

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

06359 {
06360    int callno = (int)(long)(data);
06361    ast_mutex_lock(&iaxsl[callno]);
06362    if (iaxs[callno])
06363       iaxs[callno]->authid = -1;
06364    ast_mutex_unlock(&iaxsl[callno]);
06365 #ifdef SCHED_MULTITHREADED
06366    if (schedule_action(__auth_reject, data))
06367 #endif      
06368       __auth_reject(data);
06369    return 0;
06370 }

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

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

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

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

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

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

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

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

Definition at line 5376 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 3116 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

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

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

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

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

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

Definition at line 9126 of file chan_iax2.c.

References ast_calloc.

Referenced by build_user().

09127 {
09128    struct iax2_context *con;
09129 
09130    if ((con = ast_calloc(1, sizeof(*con))))
09131       ast_copy_string(con->context, context, sizeof(con->context));
09132    
09133    return con;
09134 }

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

Definition at line 4095 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

04096 {
04097    aes_encrypt_key128(digest, ecx);
04098    aes_decrypt_key128(digest, dcx);
04099 }

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

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

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

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

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

Definition at line 10227 of file chan_iax2.c.

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

Referenced by find_cache().

10228 {
10229    struct sockaddr_in sin;
10230    int x;
10231    int callno;
10232    struct iax_ie_data ied;
10233    struct create_addr_info cai;
10234    struct parsed_dial_string pds;
10235    char *tmpstr;
10236 
10237    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
10238       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10239          look up entries for a single context */
10240       if (!ast_mutex_trylock(&iaxsl[x])) {
10241          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10242             return x;
10243          ast_mutex_unlock(&iaxsl[x]);
10244       }
10245    }
10246 
10247    /* No match found, we need to create a new one */
10248 
10249    memset(&cai, 0, sizeof(cai));
10250    memset(&ied, 0, sizeof(ied));
10251    memset(&pds, 0, sizeof(pds));
10252 
10253    tmpstr = ast_strdupa(data);
10254    parse_dial_string(tmpstr, &pds);
10255 
10256    if (ast_strlen_zero(pds.peer)) {
10257       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
10258       return -1;
10259    }
10260 
10261    /* Populate our address from the given */
10262    if (create_addr(pds.peer, NULL, &sin, &cai))
10263       return -1;
10264 
10265    if (option_debug)
10266       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10267          pds.peer, pds.username, pds.password, pds.context);
10268 
10269    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10270    if (callno < 1) {
10271       ast_log(LOG_WARNING, "Unable to create call\n");
10272       return -1;
10273    }
10274 
10275    ast_string_field_set(iaxs[callno], dproot, data);
10276    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10277 
10278    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10279    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10280    /* the string format is slightly different from a standard dial string,
10281       because the context appears in the 'exten' position
10282    */
10283    if (pds.exten)
10284       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10285    if (pds.username)
10286       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10287    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10288    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10289    /* Keep password handy */
10290    if (pds.password)
10291       ast_string_field_set(iaxs[callno], secret, pds.password);
10292    if (pds.key)
10293       ast_string_field_set(iaxs[callno], outkey, pds.key);
10294    /* Start the call going */
10295    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10296 
10297    return callno;
10298 }

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

Definition at line 3963 of file chan_iax2.c.

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

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

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

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

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

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

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

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

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

Definition at line 5074 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 6760 of file chan_iax2.c.

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

Referenced by socket_process().

06761 {
06762    unsigned int ourver;
06763    char rsi[80];
06764    snprintf(rsi, sizeof(rsi), "si-%s", si);
06765    if (iax_provision_version(&ourver, rsi, 1))
06766       return 0;
06767    if (option_debug)
06768       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06769    if (ourver != ver) 
06770       iax2_provision(sin, sockfd, NULL, rsi, 1);
06771    return 0;
06772 }

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

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

Referenced by peer_set_srcaddr().

09153 {
09154    int sd;
09155    int res;
09156    
09157    sd = socket(AF_INET, SOCK_DGRAM, 0);
09158    if (sd < 0) {
09159       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
09160       return -1;
09161    }
09162 
09163    res = bind(sd, sa, salen);
09164    if (res < 0) {
09165       if (option_debug)
09166          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09167       close(sd);
09168       return 1;
09169    }
09170 
09171    close(sd);
09172    return 0;
09173 }

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

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

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

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

Definition at line 2391 of file chan_iax2.c.

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

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

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

Definition at line 5820 of file chan_iax2.c.

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

Referenced by socket_process().

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

static unsigned char compress_subclass ( int  subclass  )  [static]

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

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

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

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

06775 {
06776    jb_info stats;
06777    jb_getinfo(pvt->jb, &stats);
06778    
06779    memset(iep, 0, sizeof(*iep));
06780 
06781    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06782    if(stats.frames_in == 0) stats.frames_in = 1;
06783    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06784    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06785    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06786    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06787    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06788 }

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

Definition at line 3008 of file chan_iax2.c.

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

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

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

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

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

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

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

04236 {
04237    int res=-1;
04238    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04239       /* Search for possible keys, given secrets */
04240       struct MD5Context md5;
04241       unsigned char digest[16];
04242       char *tmppw, *stringp;
04243       
04244       tmppw = ast_strdupa(iaxs[callno]->secret);
04245       stringp = tmppw;
04246       while ((tmppw = strsep(&stringp, ";"))) {
04247          MD5Init(&md5);
04248          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04249          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04250          MD5Final(digest, &md5);
04251          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04252          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04253          if (!res) {
04254             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04255             break;
04256          }
04257       }
04258    } else 
04259       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04260    return res;
04261 }

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

06837 {
06838    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06839    struct ast_iax2_full_hdr *fh, *cur_fh;
06840 
06841    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06842       return;
06843 
06844    pkt_buf->len = from_here->buf_len;
06845    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06846 
06847    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06848    ast_mutex_lock(&to_here->lock);
06849    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06850       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06851       if (fh->oseqno < cur_fh->oseqno) {
06852          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06853          break;
06854       }
06855    }
06856    AST_LIST_TRAVERSE_SAFE_END
06857 
06858    if (!cur_pkt_buf)
06859       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06860    
06861    ast_mutex_unlock(&to_here->lock);
06862 }

static void delete_users ( void   )  [static]

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

09745 {
09746    struct iax2_registry *reg;
09747 
09748    ao2_callback(users, 0, user_delme_cb, NULL);
09749 
09750    AST_LIST_LOCK(&registrations);
09751    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09752       ast_sched_del(sched, reg->expire);
09753       if (reg->callno) {
09754          ast_mutex_lock(&iaxsl[reg->callno]);
09755          if (iaxs[reg->callno]) {
09756             iaxs[reg->callno]->reg = NULL;
09757             iax2_destroy(reg->callno);
09758          }
09759          ast_mutex_unlock(&iaxsl[reg->callno]);
09760       }
09761       if (reg->dnsmgr)
09762          ast_dnsmgr_release(reg->dnsmgr);
09763       free(reg);
09764    }
09765    AST_LIST_UNLOCK(&registrations);
09766 
09767    ao2_callback(peers, 0, peer_delme_cb, NULL);
09768 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1742 of file chan_iax2.c.

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

Referenced by reload_firmware().

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

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

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

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

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

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

06641 {
06642    /* Look up for dpreq */
06643    struct dpreq_data *dpr = data;
06644    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06645    if (dpr->callerid)
06646       free(dpr->callerid);
06647    free(dpr);
06648    return NULL;
06649 }

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

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

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

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

Definition at line 6057 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

06058 {
06059 #ifdef SCHED_MULTITHREADED
06060    if (schedule_action(__expire_registry, data))
06061 #endif      
06062       __expire_registry(data);
06063    return 0;
06064 }

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

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

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

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

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

Definition at line 1642 of file chan_iax2.c.

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

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

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

Definition at line 1647 of file chan_iax2.c.

References __find_callno().

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

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

static struct iax2_thread* find_idle_thread ( void   )  [static]

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

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

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

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

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

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

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

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

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

Definition at line 3819 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03820 {
03821    long ms; /* NOT unsigned */
03822    if (ast_tvzero(iaxs[callno]->rxcore)) {
03823       /* Initialize rxcore time if appropriate */
03824       gettimeofday(&iaxs[callno]->rxcore, NULL);
03825       /* Round to nearest 20ms so traces look pretty */
03826       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03827    }
03828    /* Calculate difference between trunk and channel */
03829    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03830    /* Return as the sum of trunk time and the difference between trunk and real time */
03831    return ms + ts;
03832 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8911 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08912 {
08913    struct iax2_context *conl;
08914    while(con) {
08915       conl = con;
08916       con = con->next;
08917       free(conl);
08918    }
08919 }

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

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

10570 {
10571    struct iax2_peer *peer;
10572    char *peername, *colname;
10573 
10574    peername = ast_strdupa(data);
10575 
10576    /* if our channel, return the IP address of the endpoint of current channel */
10577    if (!strcmp(peername,"CURRENTCHANNEL")) {
10578            unsigned short callno;
10579       if (chan->tech != &iax2_tech)
10580          return -1;
10581       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10582       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10583       return 0;
10584    }
10585 
10586    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10587       *colname++ = '\0';
10588    else if ((colname = strchr(peername, '|')))
10589       *colname++ = '\0';
10590    else
10591       colname = "ip";
10592 
10593    if (!(peer = find_peer(peername, 1)))
10594       return -1;
10595 
10596    if (!strcasecmp(colname, "ip")) {
10597       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10598    } else  if (!strcasecmp(colname, "status")) {
10599       peer_status(peer, buf, len); 
10600    } else  if (!strcasecmp(colname, "mailbox")) {
10601       ast_copy_string(buf, peer->mailbox, len);
10602    } else  if (!strcasecmp(colname, "context")) {
10603       ast_copy_string(buf, peer->context, len);
10604    } else  if (!strcasecmp(colname, "expire")) {
10605       snprintf(buf, len, "%d", peer->expire);
10606    } else  if (!strcasecmp(colname, "dynamic")) {
10607       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10608    } else  if (!strcasecmp(colname, "callerid_name")) {
10609       ast_copy_string(buf, peer->cid_name, len);
10610    } else  if (!strcasecmp(colname, "callerid_num")) {
10611       ast_copy_string(buf, peer->cid_num, len);
10612    } else  if (!strcasecmp(colname, "codecs")) {
10613       ast_getformatname_multiple(buf, len -1, peer->capability);
10614    } else  if (!strncasecmp(colname, "codec[", 6)) {
10615       char *codecnum, *ptr;
10616       int index = 0, codec = 0;
10617       
10618       codecnum = strchr(colname, '[');
10619       *codecnum = '\0';
10620       codecnum++;
10621       if ((ptr = strchr(codecnum, ']'))) {
10622          *ptr = '\0';
10623       }
10624       index = atoi(codecnum);
10625       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10626          ast_copy_string(buf, ast_getformatname(codec), len);
10627       }
10628    }
10629 
10630    peer_unref(peer);
10631 
10632    return 0;
10633 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9136 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09137 {
09138    int methods = 0;
09139    if (strstr(value, "rsa"))
09140       methods |= IAX_AUTH_RSA;
09141    if (strstr(value, "md5"))
09142       methods |= IAX_AUTH_MD5;
09143    if (strstr(value, "plaintext"))
09144       methods |= IAX_AUTH_PLAINTEXT;
09145    return methods;
09146 }

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

Definition at line 1023 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

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

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

Definition at line 2622 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

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

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6806 of file chan_iax2.c.

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

06807 {
06808    struct iax2_pkt_buf *pkt_buf;
06809 
06810    ast_mutex_lock(&thread->lock);
06811 
06812    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06813       ast_mutex_unlock(&thread->lock);
06814 
06815       thread->buf = pkt_buf->buf;
06816       thread->buf_len = pkt_buf->len;
06817       thread->buf_size = pkt_buf->len + 1;
06818       
06819       socket_process(thread);
06820 
06821       thread->buf = NULL;
06822       ast_free(pkt_buf);
06823 
06824       ast_mutex_lock(&thread->lock);
06825    }
06826 
06827    ast_mutex_unlock(&thread->lock);
06828 }

static int handle_error ( void   )  [static]

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

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

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

Acknowledgment received for OUR registration.

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

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

static int iax2_answer ( struct ast_channel c  )  [static]

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

03620 {
03621    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03622    if (option_debug)
03623       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03624    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03625 }

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

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

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

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

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

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

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

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

Definition at line 3125 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

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

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1281 of file chan_iax2.c.

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

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

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1211 of file chan_iax2.c.

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

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

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

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

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

10659 {
10660    struct parsed_dial_string pds;
10661    char *tmp = ast_strdupa(data);
10662    struct iax2_peer *p;
10663    int res = AST_DEVICE_INVALID;
10664 
10665    memset(&pds, 0, sizeof(pds));
10666    parse_dial_string(tmp, &pds);
10667 
10668    if (ast_strlen_zero(pds.peer)) {
10669       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10670       return res;
10671    }
10672    
10673    if (option_debug > 2)
10674       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10675 
10676    /* SLD: FIXME: second call to find_peer during registration */
10677    if (!(p = find_peer(pds.peer, 1)))
10678       return res;
10679 
10680    res = AST_DEVICE_UNAVAILABLE;
10681    if (option_debug > 2) 
10682       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10683          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10684    
10685    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10686        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10687       /* Peer is registered, or have default IP address
10688          and a valid registration */
10689       if (p->historicms == 0 || p->historicms <= p->maxms)
10690          /* let the core figure out whether it is in use or not */
10691          res = AST_DEVICE_UNKNOWN;  
10692    }
10693 
10694    peer_unref(p);
10695 
10696    return res;
10697 }

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

Definition at line 2741 of file chan_iax2.c.

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

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

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

Definition at line 2746 of file chan_iax2.c.

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

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

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

Definition at line 4925 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04926 {
04927    if (argc < 2 || argc > 3)
04928       return RESULT_SHOWUSAGE;
04929    iaxdebug = 1;
04930    ast_cli(fd, "IAX2 Debugging Enabled\n");
04931    return RESULT_SUCCESS;
04932 }

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

Definition at line 4943 of file chan_iax2.c.

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

04944 {
04945    if (argc < 3 || argc > 4)
04946       return RESULT_SHOWUSAGE;
04947    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04948    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04949    return RESULT_SUCCESS;
04950 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8630 of file chan_iax2.c.

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

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

08631 {
08632    struct iax_ie_data ied;
08633    if (option_debug && iaxdebug)
08634       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08635 
08636    if (reg->dnsmgr && 
08637        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08638       /* Maybe the IP has changed, force DNS refresh */
08639       ast_dnsmgr_refresh(reg->dnsmgr);
08640    }
08641    
08642    /*
08643     * if IP has Changed, free allocated call to create a new one with new IP
08644     * call has the pointer to IP and must be updated to the new one
08645     */
08646    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08647       ast_mutex_lock(&iaxsl[reg->callno]);
08648       iax2_destroy(reg->callno);
08649       ast_mutex_unlock(&iaxsl[reg->callno]);
08650       reg->callno = 0;
08651    }
08652    if (!reg->addr.sin_addr.s_addr) {
08653       if (option_debug && iaxdebug)
08654          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08655       /* Setup the next registration attempt */
08656       AST_SCHED_DEL(sched, reg->expire);
08657       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08658       return -1;
08659    }
08660 
08661    if (!reg->callno) {
08662       if (option_debug)
08663          ast_log(LOG_DEBUG, "Allocate call number\n");
08664       reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
08665       if (reg->callno < 1) {
08666          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08667          return -1;
08668       } else if (option_debug)
08669          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08670       iaxs[reg->callno]->reg = reg;
08671       ast_mutex_unlock(&iaxsl[reg->callno]);
08672    }
08673    /* Schedule the next registration attempt */
08674    AST_SCHED_DEL(sched, reg->expire);
08675    /* Setup the next registration a little early */
08676    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08677    /* Send the request */
08678    memset(&ied, 0, sizeof(ied));
08679    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08680    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08681    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08682    reg->regstate = REG_STATE_REGSENT;
08683    return 0;
08684 }

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

Definition at line 5726 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05727 {
05728 #ifdef SCHED_MULTITHREADED
05729    if (schedule_action(__iax2_do_register_s, data))
05730 #endif      
05731       __iax2_do_register_s(data);
05732    return 0;
05733 }

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

Definition at line 4934 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04935 {
04936    if (argc < 3 || argc > 4)
04937       return RESULT_SHOWUSAGE;
04938    iaxtrunkdebug = 1;
04939    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04940    return RESULT_SUCCESS;
04941 }

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

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

06418 {
06419    struct iax_ie_data ied;
06420    /* Auto-hangup with 30 seconds of inactivity */
06421    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06422    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06423    memset(&ied, 0, sizeof(ied));
06424    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06425    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06426    dp->flags |= CACHE_FLAG_TRANSMITTED;
06427 }

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

10518 {
10519    char odata[256];
10520    char req[256];
10521    char *ncontext;
10522    struct iax2_dpcache *dp;
10523    struct ast_app *dial;
10524 #if 0
10525    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);
10526 #endif
10527    if (priority == 2) {
10528       /* Indicate status, can be overridden in dialplan */
10529       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10530       if (dialstatus) {
10531          dial = pbx_findapp(dialstatus);
10532          if (dial) 
10533             pbx_exec(chan, dial, "");
10534       }
10535       return -1;
10536    } else if (priority != 1)
10537       return -1;
10538    ast_mutex_lock(&dpcache_lock);
10539    dp = find_cache(chan, data, context, exten, priority);
10540    if (dp) {
10541       if (dp->flags & CACHE_FLAG_EXISTS) {
10542          ast_copy_string(odata, data, sizeof(odata));
10543          ncontext = strchr(odata, '/');
10544          if (ncontext) {
10545             *ncontext = '\0';
10546             ncontext++;
10547             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10548          } else {
10549             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10550          }
10551          if (option_verbose > 2)
10552             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10553       } else {
10554          ast_mutex_unlock(&dpcache_lock);
10555          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10556          return -1;
10557       }
10558    }
10559    ast_mutex_unlock(&dpcache_lock);
10560    dial = pbx_findapp("Dial");
10561    if (dial) {
10562       return pbx_exec(chan, dial, req);
10563    } else {
10564       ast_log(LOG_WARNING, "No dial application registered\n");
10565    }
10566    return -1;
10567 }

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

10449 {
10450    struct iax2_dpcache *dp;
10451    int res = 0;
10452 #if 0
10453    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10454 #endif
10455    if ((priority != 1) && (priority != 2))
10456       return 0;
10457    ast_mutex_lock(&dpcache_lock);
10458    dp = find_cache(chan, data, context, exten, priority);
10459    if (dp) {
10460       if (dp->flags & CACHE_FLAG_EXISTS)
10461          res= 1;
10462    }
10463    ast_mutex_unlock(&dpcache_lock);
10464    if (!dp) {
10465       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10466    }
10467    return res;
10468 }

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

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

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

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1275 of file chan_iax2.c.

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

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

01276 {
01277    AST_SCHED_DEL(sched, fr->retrans);
01278    iax_frame_free(fr);
01279 }

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

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

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

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03695 {
03696    struct iax2_peer *peer;
03697    int res = 0;
03698    struct ao2_iterator i;
03699 
03700    i = ao2_iterator_init(peers, 0);
03701    while ((peer = ao2_iterator_next(&i))) {
03702       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03703           (peer->addr.sin_port == sin.sin_port)) {
03704          res = ast_test_flag(peer, IAX_TRUNK);
03705          peer_unref(peer);
03706          break;
03707       }
03708       peer_unref(peer);
03709    }
03710 
03711    return res;
03712 }

static int iax2_hangup ( struct ast_channel c  )  [static]

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

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

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

Definition at line 3627 of file chan_iax2.c.

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

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

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

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

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

Definition at line 4952 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04953 {
04954    if (argc < 3 || argc > 4)
04955       return RESULT_SHOWUSAGE;
04956    iaxdebug = 0;
04957    ast_cli(fd, "IAX2 Debugging Disabled\n");
04958    return RESULT_SUCCESS;
04959 }

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

Definition at line 4970 of file chan_iax2.c.

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

04971 {
04972    if (argc < 4 || argc > 5)
04973       return RESULT_SHOWUSAGE;
04974    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04975    jb_debug_output("\n");
04976    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04977    return RESULT_SUCCESS;
04978 }

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

Definition at line 4961 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 8828 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08829 {
08830    struct iax2_peer *peer = (struct iax2_peer *)data;
08831    peer->pokeexpire = -1;
08832 #ifdef SCHED_MULTITHREADED
08833    if (schedule_action(__iax2_poke_noanswer, data))
08834 #endif      
08835       __iax2_poke_noanswer(data);
08836    peer_unref(peer);
08837    return 0;
08838 }

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

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

08850 {
08851    int callno;
08852    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
08853       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
08854         immediately after clearing things out */
08855       peer->lastms = 0;
08856       peer->historicms = 0;
08857       peer->pokeexpire = -1;
08858       peer->callno = 0;
08859       return 0;
08860    }
08861 
08862    /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */
08863    if ((callno = peer->callno) > 0) {
08864       ast_log(LOG_NOTICE, "Still have a callno...\n");
08865       ast_mutex_lock(&iaxsl[callno]);
08866       iax2_destroy(callno);
08867       ast_mutex_unlock(&iaxsl[callno]);
08868    }
08869    if (heldcall)
08870       ast_mutex_unlock(&iaxsl[heldcall]);
08871    callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
08872    if (heldcall)
08873       ast_mutex_lock(&iaxsl[heldcall]);
08874    if (peer->callno < 1) {
08875       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08876       return -1;
08877    }
08878 
08879    /* Speed up retransmission times for this qualify call */
08880    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08881    iaxs[peer->callno]->peerpoke = peer;
08882    
08883    /* Remove any pending pokeexpire task */
08884    if (peer->pokeexpire > -1) {
08885       if (!ast_sched_del(sched, peer->pokeexpire)) {
08886          peer->pokeexpire = -1;
08887          peer_unref(peer);
08888       }
08889    }
08890 
08891    /* Queue up a new task to handle no reply */
08892    /* If the host is already unreachable then use the unreachable interval instead */
08893    if (peer->lastms < 0) {
08894       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
08895    } else
08896       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
08897 
08898    if (peer->pokeexpire == -1)
08899       peer_unref(peer);
08900 
08901    /* And send the poke */
08902    ast_mutex_lock(&iaxsl[callno]);
08903    if (iaxs[callno]) {
08904       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08905    }
08906    ast_mutex_unlock(&iaxsl[callno]);
08907 
08908    return 0;
08909 }

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

Definition at line 8840 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08841 {
08842    struct iax2_peer *peer = obj;
08843 
08844    iax2_poke_peer(peer, 0);
08845 
08846    return 0;
08847 }

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

Definition at line 6457 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06458 {
06459    struct iax2_peer *peer = (struct iax2_peer *)data;
06460    peer->pokeexpire = -1;
06461 #ifdef SCHED_MULTITHREADED
06462    if (schedule_action(__iax2_poke_peer_s, data))
06463 #endif      
06464       __iax2_poke_peer_s(data);
06465    return 0;
06466 }

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

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

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

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

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

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8496 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08497 {
08498    struct iax2_thread *thread = data;
08499    ast_mutex_destroy(&thread->lock);
08500    ast_cond_destroy(&thread->cond);
08501    free(thread);
08502    ast_atomic_dec_and_test(&iaxactivethreadcount);
08503 }

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

Definition at line 8783 of file chan_iax2.c.

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

08784 {
08785    int force = 0;
08786    int res;
08787    if (argc < 4)
08788       return RESULT_SHOWUSAGE;
08789    if ((argc > 4)) {
08790       if (!strcasecmp(argv[4], "forced"))
08791          force = 1;
08792       else
08793          return RESULT_SHOWUSAGE;
08794    }
08795    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08796    if (res < 0)
08797       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08798    else if (res < 1)
08799       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08800    else
08801       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08802    return RESULT_SUCCESS;
08803 }

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

Definition at line 8686 of file chan_iax2.c.

References iax_prov_complete_template().

08687 {
08688    if (pos != 3)
08689       return NULL;
08690    return iax_prov_complete_template(line, word, pos, state);
08691 }

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

Definition at line 8693 of file chan_iax2.c.

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

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

08694 {
08695    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08696       is found for template */
08697    struct iax_ie_data provdata;
08698    struct iax_ie_data ied;
08699    unsigned int sig;
08700    struct sockaddr_in sin;
08701    int callno;
08702    struct create_addr_info cai;
08703 
08704    memset(&cai, 0, sizeof(cai));
08705 
08706    if (option_debug)
08707       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08708 
08709    if (iax_provision_build(&provdata, &sig, template, force)) {
08710       if (option_debug)
08711          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08712       return 0;
08713    }
08714 
08715    if (end) {
08716       memcpy(&sin, end, sizeof(sin));
08717       cai.sockfd = sockfd;
08718    } else if (create_addr(dest, NULL, &sin, &cai))
08719       return -1;
08720 
08721    /* Build the rest of the message */
08722    memset(&ied, 0, sizeof(ied));
08723    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08724 
08725    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08726    if (!callno)
08727       return -1;
08728 
08729    if (iaxs[callno]) {
08730       /* Schedule autodestruct in case they don't ever give us anything back */
08731       AST_SCHED_DEL(sched, iaxs[callno]->autoid);
08732       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08733       ast_set_flag(iaxs[callno], IAX_PROVISION);
08734       /* Got a call number now, so go ahead and send the provisioning information */
08735       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08736    }
08737    ast_mutex_unlock(&iaxsl[callno]);
08738 
08739    return 1;
08740 }

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

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

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

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

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

Referenced by socket_process().

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

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

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

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

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

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

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

Referenced by iax2_predestroy().

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

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

Definition at line 3421 of file chan_iax2.c.

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

03422 {
03423    if (option_verbose > 3)
03424        ast_log(LOG_NOTICE, "I should never be called!\n");
03425    return &ast_null_frame;
03426 }

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

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

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

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

Definition at line 10217 of file chan_iax2.c.

References reload_config().

10218 {
10219    return reload_config();
10220 }

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

Definition at line 8921 of file chan_iax2.c.

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

08922 {
08923    int callno;
08924    int res;
08925    int fmt, native;
08926    struct sockaddr_in sin;
08927    struct ast_channel *c;
08928    struct parsed_dial_string pds;
08929    struct create_addr_info cai;
08930    char *tmpstr;
08931 
08932    memset(&pds, 0, sizeof(pds));
08933    tmpstr = ast_strdupa(data);
08934    parse_dial_string(tmpstr, &pds);
08935 
08936    if (ast_strlen_zero(pds.peer)) {
08937       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
08938       return NULL;
08939    }
08940           
08941    memset(&cai, 0, sizeof(cai));
08942    cai.capability = iax2_capability;
08943 
08944    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08945    
08946    /* Populate our address from the given */
08947    if (create_addr(pds.peer, NULL, &sin, &cai)) {
08948       *cause = AST_CAUSE_UNREGISTERED;
08949       return NULL;
08950    }
08951 
08952    if (pds.port)
08953       sin.sin_port = htons(atoi(pds.port));
08954 
08955    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08956    if (callno < 1) {
08957       ast_log(LOG_WARNING, "Unable to create call\n");
08958       *cause = AST_CAUSE_CONGESTION;
08959       return NULL;
08960    }
08961 
08962    /* If this is a trunk, update it now */
08963    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08964    if (ast_test_flag(&cai, IAX_TRUNK)) {
08965       int new_callno;
08966       if ((new_callno = make_trunk(callno, 1)) != -1)
08967          callno = new_callno;
08968    }
08969    iaxs[callno]->maxtime = cai.maxtime;
08970    if (cai.found)
08971       ast_string_field_set(iaxs[callno], host, pds.peer);
08972 
08973    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08974 
08975    ast_mutex_unlock(&iaxsl[callno]);
08976 
08977    if (c) {
08978       /* Choose a format we can live with */
08979       if (c->nativeformats & format) 
08980          c->nativeformats &= format;
08981       else {
08982          native = c->nativeformats;
08983          fmt = format;
08984          res = ast_translator_best_choice(&fmt, &native);
08985          if (res < 0) {
08986             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
08987                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
08988             ast_hangup(c);
08989             return NULL;
08990          }
08991          c->nativeformats = native;
08992       }
08993       c->readformat = ast_best_codec(c->nativeformats);
08994       c->writeformat = c->readformat;
08995    }
08996 
08997    return c;
08998 }

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

Definition at line 985 of file chan_iax2.c.

References ast_sched_add(), and signal_condition().

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

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

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

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

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

Definition at line 2763 of file chan_iax2.c.

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

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

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

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

02759 {
02760    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02761 }

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

Definition at line 2751 of file chan_iax2.c.

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

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

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

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

03396 {
03397    struct ast_option_header *h;
03398    int res;
03399 
03400    switch (option) {
03401    case AST_OPTION_TXGAIN:
03402    case AST_OPTION_RXGAIN:
03403       /* these two cannot be sent, because they require a result */
03404       errno = ENOSYS;
03405       return -1;
03406    default:
03407       if (!(h = ast_malloc(datalen + sizeof(*h))))
03408          return -1;
03409 
03410       h->flag = AST_OPTION_FLAG_REQUEST;
03411       h->option = htons(option);
03412       memcpy(h->data, data, datalen);
03413       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03414                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03415                  datalen + sizeof(*h), -1);
03416       free(h);
03417       return res;
03418    }
03419 }

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

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

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

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

Definition at line 4790 of file chan_iax2.c.

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

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

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

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

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

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

Definition at line 4913 of file chan_iax2.c.

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

04914 {
04915    int numchans = 0;
04916    if (argc != 3)
04917       return RESULT_SHOWUSAGE;
04918    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04919    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04920    numchans = ast_cli_netstats(NULL, fd, 1);
04921    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04922    return RESULT_SUCCESS;
04923 }

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

Show one peer in detail.

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

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

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

Definition at line 4690 of file chan_iax2.c.

References __iax2_show_peers().

04691 {
04692    return __iax2_show_peers(0, fd, NULL, argc, argv);
04693 }

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

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

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

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

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

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

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

Definition at line 4631 of file chan_iax2.c.

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

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

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

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

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

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

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

03429 {
03430    int res;
03431    struct iax_ie_data ied0;
03432    struct iax_ie_data ied1;
03433    unsigned int transferid = (unsigned int)ast_random();
03434    memset(&ied0, 0, sizeof(ied0));
03435    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03436    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03437    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03438 
03439    memset(&ied1, 0, sizeof(ied1));
03440    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03441    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03442    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03443    
03444    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03445    if (res)
03446       return -1;
03447    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03448    if (res)
03449       return -1;
03450    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03451    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03452    return 0;
03453 }

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

Definition at line 2263 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

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

03675 {
03676    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03677    struct iax_ie_data ied;
03678    char tmp[256], *context;
03679    ast_copy_string(tmp, dest, sizeof(tmp));
03680    context = strchr(tmp, '@');
03681    if (context) {
03682       *context = '\0';
03683       context++;
03684    }
03685    memset(&ied, 0, sizeof(ied));
03686    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03687    if (context)
03688       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03689    if (option_debug)
03690       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03691    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03692 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

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

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

Definition at line 6512 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06513 {
06514    /* Drop when trunk is about 5 seconds idle */
06515    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06516       return 1;
06517    return 0;
06518 }

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

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

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

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6429 of file chan_iax2.c.

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

Referenced by socket_process().

06430 {
06431    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06432 }

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

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

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

static int iax_check_version ( char *  dev  )  [static]

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

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

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

Definition at line 763 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 769 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

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

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

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

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

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

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

06681 {
06682    struct ast_channel *chan1, *chan2;
06683    struct iax_dual *d;
06684    struct ast_frame *f;
06685    int ext;
06686    int res;
06687    d = stuff;
06688    chan1 = d->chan1;
06689    chan2 = d->chan2;
06690    free(d);
06691    f = ast_read(chan1);
06692    if (f)
06693       ast_frfree(f);
06694    res = ast_park_call(chan1, chan2, 0, &ext);
06695    ast_hangup(chan2);
06696    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06697    return NULL;
06698 }

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

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

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

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

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

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

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

Definition at line 798 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 774 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 786 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 11053 of file chan_iax2.c.

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

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

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

Definition at line 3455 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03456 {
03457    ast_mutex_lock(&iaxsl[callno0]);
03458    while (ast_mutex_trylock(&iaxsl[callno1])) {
03459       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03460    }
03461 }

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

Definition at line 1465 of file chan_iax2.c.

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

Referenced by iax2_request(), and socket_process().

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

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

Definition at line 4694 of file chan_iax2.c.

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

Referenced by load_module().

04695 {
04696    ast_cli_netstats(s, -1, 0);
04697    astman_append(s, "\r\n");
04698    return RESULT_SUCCESS;
04699 }

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

Definition at line 4727 of file chan_iax2.c.

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

Referenced by load_module().

04728 {
04729    char *a[] = { "iax2", "show", "users" };
04730    int ret;
04731    const char *id = astman_get_header(m,"ActionID");
04732 
04733    if (!ast_strlen_zero(id))
04734       astman_append(s, "ActionID: %s\r\n",id);
04735    ret = __iax2_show_peers(1, -1, s, 3, a );
04736    astman_append(s, "\r\n\r\n" );
04737    return ret;
04738 } /* /JDG */

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

Definition at line 1431 of file chan_iax2.c.

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

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

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

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

Definition at line 4101 of file chan_iax2.c.

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

Referenced by decode_frame().

04102 {
04103 #if 0
04104    /* Debug with "fake encryption" */
04105    int x;
04106    if (len % 16)
04107       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04108    for (x=0;x<len;x++)
04109       dst[x] = src[x] ^ 0xff;
04110 #else 
04111    unsigned char lastblock[16] = { 0 };
04112    int x;
04113    while(len > 0) {
04114       aes_decrypt(src, dst, dcx);
04115       for (x=0;x<16;x++)
04116          dst[x] ^= lastblock[x];
04117       memcpy(lastblock, src, sizeof(lastblock));
04118       dst += 16;
04119       src += 16;
04120       len -= 16;
04121    }
04122 #endif
04123 }

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

Definition at line 4125 of file chan_iax2.c.

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

Referenced by encrypt_frame().

04126 {
04127 #if 0
04128    /* Debug with "fake encryption" */
04129    int x;
04130    if (len % 16)
04131       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04132    for (x=0;x<len;x++)
04133       dst[x] = src[x] ^ 0xff;
04134 #else
04135    unsigned char curblock[16] = { 0 };
04136    int x;
04137    while(len > 0) {
04138       for (x=0;x<16;x++)
04139          curblock[x] ^= src[x];
04140       aes_encrypt(curblock, dst, ecx);
04141       memcpy(curblock, dst, sizeof(curblock)); 
04142       dst += 16;
04143       src += 16;
04144       len -= 16;
04145    }
04146 #endif
04147 }

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

Definition at line 5305 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05306 {
05307    /* Select exactly one common encryption if there are any */
05308    p->encmethods &= enc;
05309    if (p->encmethods) {
05310       if (p->encmethods & IAX_ENCRYPT_AES128)
05311          p->encmethods = IAX_ENCRYPT_AES128;
05312       else
05313          p->encmethods = 0;
05314    }
05315 }

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

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

09029 {
09030    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
09031       from the network, and queue them for delivery to the channels */
09032    int res, count, wakeup;
09033    struct iax_frame *f;
09034 
09035    if (timingfd > -1)
09036       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
09037    
09038    for(;;) {
09039       pthread_testcancel();
09040 
09041       /* Go through the queue, sending messages which have not yet been
09042          sent, and scheduling retransmissions if appropriate */
09043       AST_LIST_LOCK(&iaxq.queue);
09044       count = 0;
09045       wakeup = -1;
09046       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
09047          if (f->sentyet)
09048             continue;
09049          
09050          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
09051          if (ast_mutex_trylock(&iaxsl[f->callno])) {
09052             wakeup = 1;
09053             continue;
09054          }
09055 
09056          f->sentyet++;
09057 
09058          if (iaxs[f->callno]) {
09059             send_packet(f);
09060             count++;
09061          } 
09062 
09063          ast_mutex_unlock(&iaxsl[f->callno]);
09064 
09065          if (f->retries < 0) {
09066             /* This is not supposed to be retransmitted */
09067             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
09068             iaxq.count--;
09069             /* Free the iax frame */
09070             iax_frame_free(f);
09071          } else {
09072             /* We need reliable delivery.  Schedule a retransmission */
09073             f->retries++;
09074             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
09075          }
09076       }
09077       AST_LIST_TRAVERSE_SAFE_END
09078       AST_LIST_UNLOCK(&iaxq.queue);
09079 
09080       pthread_testcancel();
09081 
09082       if (option_debug && count >= 20)
09083          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
09084 
09085       /* Now do the IO, and run scheduled tasks */
09086       res = ast_io_wait(io, wakeup);
09087       if (res >= 0) {
09088          if (option_debug && res >= 20)
09089             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
09090       }
09091    }
09092    return NULL;
09093 }

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

Definition at line 1372 of file chan_iax2.c.

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

Referenced by __find_callno().

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

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

03174 {
03175    if (ast_strlen_zero(data))
03176       return;
03177 
03178    pds->peer = strsep(&data, "/");
03179    pds->exten = strsep(&data, "/");
03180    pds->options = data;
03181 
03182    if (pds->exten) {
03183       data = pds->exten;
03184       pds->exten = strsep(&data, "@");
03185       pds->context = data;
03186    }
03187 
03188    if (strchr(pds->peer, '@')) {
03189       data = pds->peer;
03190       pds->username = strsep(&data, "@");
03191       pds->peer = data;
03192    }
03193 
03194    if (pds->username) {
03195       data = pds->username;
03196       pds->username = strsep(&data, ":");
03197       pds->password = data;
03198    }
03199 
03200    data = pds->peer;
03201    pds->peer = strsep(&data, ":");
03202    pds->port = data;
03203 
03204    /* check for a key name wrapped in [] in the secret position, if found,
03205       move it to the key field instead
03206    */
03207    if (pds->password && (pds->password[0] == '[')) {
03208       pds->key = ast_strip_quoted(pds->password, "[", "]");
03209       pds->password = NULL;
03210    }
03211 }

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

Referenced by load_module().

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

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

Definition at line 9726 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09727 {
09728    struct iax2_peer *peer = obj;
09729 
09730    ast_set_flag(peer, IAX_DELME);
09731 
09732    return 0;
09733 }

static void peer_destructor ( void *  obj  )  [static]

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

09252 {
09253    struct iax2_peer *peer = obj;
09254 
09255    ast_free_ha(peer->ha);
09256 
09257    if (peer->callno > 0) {
09258       ast_mutex_lock(&iaxsl[peer->callno]);
09259       iax2_destroy(peer->callno);
09260       ast_mutex_unlock(&iaxsl[peer->callno]);
09261    }
09262 
09263    register_peer_exten(peer, 0);
09264 
09265    if (peer->dnsmgr)
09266       ast_dnsmgr_release(peer->dnsmgr);
09267 
09268    ast_string_field_free_memory(peer);
09269 }

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

References ast_str_hash().

Referenced by load_module().

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

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

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

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

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

Definition at line 11024 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

11025 {
11026    struct iax2_peer *peer = obj;
11027 
11028    if (peer->sockfd < 0)
11029       peer->sockfd = defaultsockfd;
11030 
11031    return 0;
11032 }

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

09179 {
09180    struct sockaddr_in sin;
09181    int nonlocal = 1;
09182    int port = IAX_DEFAULT_PORTNO;
09183    int sockfd = defaultsockfd;
09184    char *tmp;
09185    char *addr;
09186    char *portstr;
09187 
09188    if (!(tmp = ast_strdupa(srcaddr)))
09189       return -1;
09190 
09191    addr = strsep(&tmp, ":");
09192    portstr = tmp;
09193 
09194    if (portstr) {
09195       port = atoi(portstr);
09196       if (port < 1)
09197          port = IAX_DEFAULT_PORTNO;
09198    }
09199    
09200    if (!ast_get_ip(&sin, addr)) {
09201       struct ast_netsock *sock;
09202       int res;
09203 
09204       sin.sin_port = 0;
09205       sin.sin_family = AF_INET;
09206       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
09207       if (res == 0) {
09208          /* ip address valid. */
09209          sin.sin_port = htons(port);
09210          if (!(sock = ast_netsock_find(netsock, &sin)))
09211             sock = ast_netsock_find(outsock, &sin);
09212          if (sock) {
09213             sockfd = ast_netsock_sockfd(sock);
09214             nonlocal = 0;
09215          } else {
09216             unsigned int orig_saddr = sin.sin_addr.s_addr;
09217             /* INADDR_ANY matches anyway! */
09218             sin.sin_addr.s_addr = INADDR_ANY;
09219             if (ast_netsock_find(netsock, &sin)) {
09220                sin.sin_addr.s_addr = orig_saddr;
09221                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09222                if (sock) {
09223                   sockfd = ast_netsock_sockfd(sock);
09224                   ast_netsock_unref(sock);
09225                   nonlocal = 0;
09226                } else {
09227                   nonlocal = 2;
09228                }
09229             }
09230          }
09231       }
09232    }
09233       
09234    peer->sockfd = sockfd;
09235 
09236    if (nonlocal == 1) {
09237       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09238          srcaddr, peer->name);
09239       return -1;
09240         } else if (nonlocal == 2) {
09241       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09242          srcaddr, peer->name);
09243          return -1;
09244    } else {
09245       if (option_debug)
09246          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09247       return 0;
09248    }
09249 }

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

peer_status: Report Peer status in character string

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

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

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

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

01164 {
01165    ao2_ref(peer, -1);
01166    return NULL;
01167 }

static void poke_all_peers ( void   )  [static]

Definition at line 10185 of file chan_iax2.c.

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

Referenced by reload_config().

10186 {
10187    struct ao2_iterator i;
10188    struct iax2_peer *peer;
10189 
10190    i = ao2_iterator_init(peers, 0);
10191    while ((peer = ao2_iterator_next(&i))) {
10192       iax2_poke_peer(peer, 0);
10193       peer_unref(peer);
10194    }
10195 }

static void prune_peers ( void   )  [static]

Definition at line 9784 of file chan_iax2.c.

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

09785 {
09786    struct iax2_peer *peer;
09787    struct ao2_iterator i;
09788 
09789    i = ao2_iterator_init(peers, 0);
09790    while ((peer = ao2_iterator_next(&i))) {
09791       if (ast_test_flag(peer, IAX_DELME))
09792          unlink_peer(peer);
09793       peer_unref(peer);
09794    }
09795 }

static void prune_users ( void   )  [static]

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

09771 {
09772    struct iax2_user *user;
09773    struct ao2_iterator i;
09774 
09775    i = ao2_iterator_init(users, 0);
09776    while ((user = ao2_iterator_next(&i))) {
09777       if (ast_test_flag(user, IAX_DELME))
09778          ao2_unlink(users, user);
09779       user_unref(user);
09780    }
09781 }

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

Definition at line 11041 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

11042 {
11043    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
11044 
11045    /* The frames_received field is used to hold whether we're matching
11046     * against a full frame or not ... */
11047 
11048    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
11049       pvt2->frames_received) ? CMP_MATCH : 0;
11050 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1333 of file chan_iax2.c.

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

Referenced by new_iax().

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

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

Definition at line 11034 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

11035 {
11036    const struct chan_iax2_pvt *pvt = obj;
11037 
11038    return pvt->peercallno;
11039 }

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

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

05288 {
05289    struct ast_iax2_full_hdr fh;
05290    fh.scallno = htons(src | IAX_FLAG_FULL);
05291    fh.dcallno = htons(dst);
05292    fh.ts = 0;
05293    fh.oseqno = 0;
05294    fh.iseqno = 0;
05295    fh.type = AST_FRAME_IAX;
05296    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05297    if (iaxdebug)
05298        iax_showframe(NULL, &fh, 0, sin, 0);
05299    if (option_debug)
05300       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05301          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05302    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05303 }

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

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

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

Definition at line 2977 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

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

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

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

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

static void reg_source_db ( struct iax2_peer p  )  [static]

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

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

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

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

05989 {
05990    char multi[256];
05991    char *stringp, *ext;
05992    if (!ast_strlen_zero(regcontext)) {
05993       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
05994       stringp = multi;
05995       while((ext = strsep(&stringp, "&"))) {
05996          if (onoff) {
05997             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
05998                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
05999                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
06000          } else
06001             ast_context_remove_extension(regcontext, ext, 1, NULL);
06002       }
06003    }
06004 }

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

Verify inbound registration.

Definition at line 5451 of file chan_iax2.c.

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

Referenced by handle_request_register(), and socket_process().

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

static int registry_authrequest ( int  callno  )  [static]

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

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

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

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

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

static char* regstate2str ( int  regstate  )  [static]

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

04741 {
04742    switch(regstate) {
04743    case REG_STATE_UNREGISTERED:
04744       return "Unregistered";
04745    case REG_STATE_REGSENT:
04746       return "Request Sent";
04747    case REG_STATE_AUTHSENT:
04748       return "Auth. Sent";
04749    case REG_STATE_REGISTERED:
04750       return "Registered";
04751    case REG_STATE_REJECTED:
04752       return "Rejected";
04753    case REG_STATE_TIMEOUT:
04754       return "Timeout";
04755    case REG_STATE_NOAUTH:
04756       return "No Authentication";
04757    default:
04758       return "Unknown";
04759    }
04760 }

static int reload ( void   )  [static]

Definition at line 10222 of file chan_iax2.c.

References reload_config().

10223 {
10224    return reload_config();
10225 }

static int reload_config ( void   )  [static]

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

10197 {
10198    char *config = "iax.conf";
10199    struct iax2_registry *reg;
10200 
10201    if (set_config(config, 1) > 0) {
10202       prune_peers();
10203       prune_users();
10204       AST_LIST_LOCK(&registrations);
10205       AST_LIST_TRAVERSE(&registrations, reg, entry)
10206          iax2_do_register(reg);
10207       AST_LIST_UNLOCK(&registrations);
10208       /* Qualify hosts, too */
10209       poke_all_peers();
10210    }
10211    reload_firmware(0);
10212    iax_provision_reload();
10213 
10214    return 0;
10215 }

static void reload_firmware ( int  unload  )  [static]

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

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

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1248 of file chan_iax2.c.

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

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

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

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

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

06791 {
06792    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06793    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06794    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06795    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06796    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06797    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06798    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06799 }

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

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

09001 {
09002    int count;
09003    int res;
09004    struct timeval tv;
09005    struct timespec ts;
09006 
09007    for (;;) {
09008       res = ast_sched_wait(sched);
09009       if ((res > 1000) || (res < 0))
09010          res = 1000;
09011       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
09012       ts.tv_sec = tv.tv_sec;
09013       ts.tv_nsec = tv.tv_usec * 1000;
09014 
09015       pthread_testcancel();
09016       ast_mutex_lock(&sched_lock);
09017       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
09018       ast_mutex_unlock(&sched_lock);
09019       pthread_testcancel();
09020 
09021       count = ast_sched_runq(sched);
09022       if (option_debug && count >= 20)
09023          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
09024    }
09025    return NULL;
09026 }

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 2637 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, type, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

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

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

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

05025 {
05026    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
05027 }

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

05044 {
05045    int call_num = i->callno;
05046    /* It is assumed that the callno has already been locked */
05047    iax2_predestroy(i->callno);
05048    if (!iaxs[call_num])
05049       return -1;
05050    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05051 }

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

Definition at line 5053 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05054 {
05055    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05056 }

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

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

05030 {
05031    int res;
05032    ast_mutex_lock(&iaxsl[callno]);
05033    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05034    ast_mutex_unlock(&iaxsl[callno]);
05035    return res;
05036 }

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

Definition at line 5058 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

05059 {
05060    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05061 }

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

Definition at line 1054 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

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

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 2078 of file chan_iax2.c.

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

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

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

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

Definition at line 1014 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

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

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

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

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

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

Load configuration.

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

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

static void set_config_destroy ( void   )  [static]

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

09813 {
09814    strcpy(accountcode, "");
09815    strcpy(language, "");
09816    strcpy(mohinterpret, "default");
09817    strcpy(mohsuggest, "");
09818    amaflags = 0;
09819    delayreject = 0;
09820    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09821    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09822    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09823    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09824    delete_users();
09825 }

static void set_timing ( void   )  [static]

Definition at line 9797 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09798 {
09799 #ifdef HAVE_ZAPTEL
09800    int bs = trunkfreq * 8;
09801    if (timingfd > -1) {
09802       if (
09803 #ifdef ZT_TIMERACK
09804          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09805 #endif         
09806          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09807          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09808    }
09809 #endif
09810 }

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

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

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

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6942 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_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_device_state_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_parking_ext(), ast_sched_del(), AST_SCHED_DEL, ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax2_peer::callno, iax2_dpcache::callno, 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, DEADLOCK_AVOIDANCE, decrypt_frame(), dp_lookup(), EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), find_callno_locked(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, format, chan_iax2_pvt::frames_received, ast_frame::frametype, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_vnak(), IAX_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(), remove_by_peercallno(), 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(), store_by_peercallno(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), iax_frame::ts, ast_iax2_mini_hdr::ts, uncompress_subclass(), update_registry(), VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.

Referenced by handle_deferred_full_frames().

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

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

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

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

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

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

06652 {
06653    pthread_t newthread;
06654    struct dpreq_data *dpr;
06655    pthread_attr_t attr;
06656    
06657    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06658       return;
06659 
06660    pthread_attr_init(&attr);
06661    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06662 
06663    dpr->callno = callno;
06664    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06665    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06666    if (callerid)
06667       dpr->callerid = ast_strdup(callerid);
06668    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06669       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06670    }
06671 
06672    pthread_attr_destroy(&attr);
06673 }

static int start_network_thread ( void   )  [static]

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

09096 {
09097    pthread_attr_t attr;
09098    int threadcount = 0;
09099    int x;
09100    for (x = 0; x < iaxthreadcount; x++) {
09101       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
09102       if (thread) {
09103          thread->type = IAX_TYPE_POOL;
09104          thread->threadnum = ++threadcount;
09105          ast_mutex_init(&thread->lock);
09106          ast_cond_init(&thread->cond, NULL);
09107          pthread_attr_init(&attr);
09108          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
09109          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
09110             ast_log(LOG_WARNING, "Failed to create new thread!\n");
09111             free(thread);
09112             thread = NULL;
09113          }
09114          AST_LIST_LOCK(&idle_list);
09115          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
09116          AST_LIST_UNLOCK(&idle_list);
09117       }
09118    }
09119    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
09120    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
09121    if (option_verbose > 1)
09122       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
09123    return 0;
09124 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6333 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06334 {
06335    iax2_destroy_helper(iaxs[callno]);
06336 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1238 of file chan_iax2.c.

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

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

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

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

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

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

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

Definition at line 2064 of file chan_iax2.c.

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

Referenced by send_trunk().

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

static int try_firmware ( char *  s  )  [static]

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

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

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

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

05736 {
05737    int newcall = 0;
05738    char newip[256];
05739    struct iax_ie_data ied;
05740    struct sockaddr_in new;
05741    
05742    
05743    memset(&ied, 0, sizeof(ied));
05744    if (ies->apparent_addr)
05745       bcopy(ies->apparent_addr, &new, sizeof(new));
05746    if (ies->callno)
05747       newcall = ies->callno;
05748    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05749       ast_log(LOG_WARNING, "Invalid transfer request\n");
05750       return -1;
05751    }
05752    pvt->transfercallno = newcall;
05753    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05754    inet_aton(newip, &pvt->transfer.sin_addr);
05755    pvt->transfer.sin_family = AF_INET;
05756    pvt->transferring = TRANSFER_BEGIN;
05757    pvt->transferid = ies->transferid;
05758    if (ies->transferid)
05759       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05760    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05761    return 0; 
05762 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1083 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

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

static void unlink_peer ( struct iax2_peer peer  )  [static]

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

06008 {
06009    if (peer->expire > -1) {
06010       if (!ast_sched_del(sched, peer->expire)) {
06011          peer->expire = -1;
06012          peer_unref(peer);
06013       }
06014    }
06015 
06016    if (peer->pokeexpire > -1) {
06017       if (!ast_sched_del(sched, peer->pokeexpire)) {
06018          peer->pokeexpire = -1;
06019          peer_unref(peer);
06020       }
06021    }
06022 
06023    ao2_unlink(peers, peer);
06024 }

static int unload_module ( void   )  [static]

Definition at line 11018 of file chan_iax2.c.

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

11019 {
11020    ast_custom_function_unregister(&iaxpeer_function);
11021    return __unload_module();
11022 }

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

Definition at line 3463 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03464 {
03465    ast_mutex_unlock(&iaxsl[callno1]);
03466    ast_mutex_unlock(&iaxsl[callno0]);
03467 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

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

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

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

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

static void update_max_nontrunk ( void   )  [static]

Definition at line 1451 of file chan_iax2.c.

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

Referenced by __find_callno(), and make_trunk().

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

static void update_max_trunk ( void   )  [static]

Definition at line 1258 of file chan_iax2.c.

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

Referenced by iax2_destroy(), and make_trunk().

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

static int update_packet ( struct iax_frame f  )  [static]

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

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

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

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

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

Referenced by load_module().

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

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

Definition at line 9735 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09736 {
09737    struct iax2_user *user = obj;
09738 
09739    ast_set_flag(user, IAX_DELME);
09740 
09741    return 0;
09742 }

static void user_destructor ( void *  obj  )  [static]

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

09500 {
09501    struct iax2_user *user = obj;
09502 
09503    ast_free_ha(user->ha);
09504    free_context(user->contexts);
09505    if(user->vars) {
09506       ast_variables_destroy(user->vars);
09507       user->vars = NULL;
09508    }
09509    ast_string_field_free_memory(user);
09510 }

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

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1169 of file chan_iax2.c.

References ao2_ref().

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

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

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

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

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

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

06435 {
06436    struct iax_frame *f;
06437 
06438    AST_LIST_LOCK(&iaxq.queue);
06439    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06440       /* Send a copy immediately */
06441       if ((f->callno == callno) && iaxs[f->callno] &&
06442          ((unsigned char ) (f->oseqno - last) < 128) &&
06443          (f->retries >= 0)) {
06444          send_packet(f);
06445       }
06446    }
06447    AST_LIST_UNLOCK(&iaxq.queue);
06448 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 218 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(), sip_new(), skinny_new(), tds_log(), wait_for_answer(), and zt_new().

int adsi = 0 [static]

Definition at line 222 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

Definition at line 221 of file chan_iax2.c.

Referenced by build_device(), and build_gateway().

int authdebug = 1 [static]

Definition at line 158 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 159 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10834 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 10814 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 10819 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 10829 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 10824 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 10809 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 10783 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 10775 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 10767 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 175 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 223 of file chan_iax2.c.

struct iax2_dpcache * dpcache [static]

Referenced by find_cache(), and iax2_show_cache().

int global_rtautoclear = 120 [static]

Definition at line 276 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

Definition at line 226 of file chan_iax2.c.

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

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 204 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 224 of file chan_iax2.c.

enum { ... } iax2_flags

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

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

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10699 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

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

struct ao2_container* iax_peercallno_pvts [static]

Another container of iax2_pvt structures.

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

Definition at line 824 of file chan_iax2.c.

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

int iaxactivethreadcount = 0 [static]

Definition at line 452 of file chan_iax2.c.

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

int iaxcompat = 0 [static]

Definition at line 160 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 206 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 162 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 164 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 451 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 450 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 10635 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

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

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

Definition at line 811 of file chan_iax2.c.

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

ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static]

Definition at line 812 of file chan_iax2.c.

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

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 449 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 208 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 201 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 153 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 147 of file chan_iax2.c.

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

Definition at line 813 of file chan_iax2.c.

int max_reg_expire [static]

Definition at line 169 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 151 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 150 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 154 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 156 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 831 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_nontrunk().

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 830 of file chan_iax2.c.

Referenced by __find_callno(), and update_max_trunk().

int min_reg_expire [static]

Definition at line 168 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 219 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 220 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 173 of file chan_iax2.c.

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

char no_debug_jb_usage[] [static]

Initial value:

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

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

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 174 of file chan_iax2.c.

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

char* papp = "IAX2Provision" [static]

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

struct ao2_container* peers [static]

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

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

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

struct sched_context* sched [static]

Definition at line 202 of file chan_iax2.c.

ast_cond_t sched_cond [static]

Definition at line 231 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 229 of file chan_iax2.c.

char show_cache_usage[] [static]

Initial value:

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

Definition at line 10713 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 10741 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 10759 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 10745 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 10717 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 10753 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10729 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 10763 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 10709 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 10749 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 10736 of file chan_iax2.c.

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

Definition at line 143 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 210 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 171 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 166 of file chan_iax2.c.

struct iax2_trunk_peer * tpeers [static]

Referenced by find_tpeer(), and timing_read().

int trunkfreq = 20 [static]

Definition at line 157 of file chan_iax2.c.

struct ao2_container* users [static]

Definition at line 652 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 Jul 14 17:25:10 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1