Sat Apr 12 07:12:35 2008

Asterisk developer's documentation


chan_iax2.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Functions

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

Variables

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


Detailed Description

Implementation of Inter-Asterisk eXchange Version 2.

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

Definition in file chan_iax2.c.


Define Documentation

#define CACHE_FLAG_CANEXIST   (1 << 2)

Extension can exist

Definition at line 667 of file chan_iax2.c.

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

#define CACHE_FLAG_EXISTS   (1 << 0)

Extension exists

Definition at line 663 of file chan_iax2.c.

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

#define CACHE_FLAG_MATCHMORE   (1 << 7)

Matchmore

Definition at line 677 of file chan_iax2.c.

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

#define CACHE_FLAG_NONEXISTENT   (1 << 1)

Extension is nonexistent

Definition at line 665 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

#define CACHE_FLAG_PENDING   (1 << 3)

Waiting to hear back response

Definition at line 669 of file chan_iax2.c.

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

#define CACHE_FLAG_TIMEOUT   (1 << 4)

Timed out

Definition at line 671 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

Definition at line 673 of file chan_iax2.c.

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

#define CACHE_FLAG_UNKNOWN   (1 << 6)

Timeout

Definition at line 675 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

#define CALLNO_TO_PTR (  )     ((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 137 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 204 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 203 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 202 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 130 of file chan_iax2.c.

Referenced by complete_transfer(), and find_callno().

#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 446 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 142 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 367 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 185 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 193 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 198 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 187 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 698 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 700 of file chan_iax2.c.

Referenced by iax2_process_thread().

#define IAX_IOSTATE_READY   1

Definition at line 699 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 701 of file chan_iax2.c.

Referenced by __schedule_action(), and iax2_process_thread().

#define IAX_TYPE_DYNAMIC   2

#define IAX_TYPE_POOL   1

Definition at line 703 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 117 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 443 of file chan_iax2.c.

#define MAX_PEER_BUCKETS   1

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

Definition at line 649 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 447 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 654 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 131 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 444 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 440 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 139 of file chan_iax2.c.

Referenced by find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1240 of file chan_iax2.c.

Referenced by find_callno(), and socket_process().

#define NEW_FORCE   2

#define NEW_PREVENT   0

Definition at line 1239 of file chan_iax2.c.

Referenced by socket_process().

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

#define SCHED_MULTITHREADED

Definition at line 110 of file chan_iax2.c.

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

#define TRUNK_CALL_START   0x4000

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

00238      {
00239    IAX_STATE_STARTED =     (1 << 0),
00240    IAX_STATE_AUTHENTICATED =  (1 << 1),
00241    IAX_STATE_TBD =      (1 << 2),
00242    IAX_STATE_UNCHANGED =      (1 << 3),
00243 } 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 250 of file chan_iax2.c.

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

Enumerator:
REG_STATE_UNREGISTERED 
REG_STATE_REGSENT 
REG_STATE_AUTHSENT 
REG_STATE_REGISTERED 
REG_STATE_REJECTED 
REG_STATE_TIMEOUT 
REG_STATE_NOAUTH 

Definition at line 398 of file chan_iax2.c.

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

Definition at line 408 of file chan_iax2.c.


Function Documentation

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

Definition at line 2042 of file chan_iax2.c.

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

Referenced by attempt_transmit().

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

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

Definition at line 6169 of file chan_iax2.c.

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

Referenced by auth_reject().

06170 {
06171    /* Called from IAX thread only, without iaxs lock */
06172    int callno = (int)(long)(nothing);
06173    struct iax_ie_data ied;
06174    ast_mutex_lock(&iaxsl[callno]);
06175    if (iaxs[callno]) {
06176       memset(&ied, 0, sizeof(ied));
06177       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06178          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06179          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06180       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06181          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06182          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06183       }
06184       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06185    }
06186    ast_mutex_unlock(&iaxsl[callno]);
06187 }

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

Definition at line 2986 of file chan_iax2.c.

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

Referenced by auto_congest().

02987 {
02988    int callno = PTR_TO_CALLNO(nothing);
02989    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
02990    ast_mutex_lock(&iaxsl[callno]);
02991    if (iaxs[callno]) {
02992       iaxs[callno]->initid = -1;
02993       iax2_queue_frame(callno, &f);
02994       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
02995    }
02996    ast_mutex_unlock(&iaxsl[callno]);
02997 }

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

Definition at line 6219 of file chan_iax2.c.

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

Referenced by auto_hangup().

06220 {
06221    /* Called from IAX thread only, without iaxs lock */
06222    int callno = (int)(long)(nothing);
06223    struct iax_ie_data ied;
06224    ast_mutex_lock(&iaxsl[callno]);
06225    if (iaxs[callno]) {
06226       memset(&ied, 0, sizeof(ied));
06227       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06228       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06229       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06230    }
06231    ast_mutex_unlock(&iaxsl[callno]);
06232 }

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

References iax_frame::af, ast_test_flag, iax_frame::callno, ast_frame::has_timing_info, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, and iax_frame::retrans.

Referenced by __get_from_jb(), and schedule_delivery().

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

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

Definition at line 5857 of file chan_iax2.c.

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

Referenced by expire_registry().

05858 {
05859    struct iax2_peer *peer = (struct iax2_peer *) data;
05860 
05861    if (!peer)
05862       return;
05863 
05864    peer->expire = -1;
05865 
05866    if (option_debug)
05867       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
05868    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
05869       realtime_update_peer(peer->name, &peer->addr, 0);
05870    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
05871    /* Reset the address */
05872    memset(&peer->addr, 0, sizeof(peer->addr));
05873    /* Reset expiry value */
05874    peer->expiry = min_reg_expire;
05875    if (!ast_test_flag(peer, IAX_TEMPONLY))
05876       ast_db_del("IAX/Registry", peer->name);
05877    register_peer_exten(peer, 0);
05878    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
05879    if (iax2_regfunk)
05880       iax2_regfunk(peer->name, 0);
05881 
05882    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
05883       unlink_peer(peer);
05884 
05885    peer_unref(peer);
05886 }

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

Definition at line 2439 of file chan_iax2.c.

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

Referenced by get_from_jb().

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

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

Definition at line 5555 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05556 {
05557    struct iax2_registry *reg = (struct iax2_registry *)data;
05558    reg->expire = -1;
05559    iax2_do_register(reg);
05560 }

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

Definition at line 8595 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, and iax2_peer::pokefreqnotok.

Referenced by iax2_poke_noanswer().

08596 {
08597    struct iax2_peer *peer = (struct iax2_peer *)data;
08598    if (peer->lastms > -1) {
08599       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08600       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08601       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08602    }
08603    if (peer->callno > 0) {
08604       ast_mutex_lock(&iaxsl[peer->callno]);
08605       iax2_destroy(peer->callno);
08606       ast_mutex_unlock(&iaxsl[peer->callno]);
08607    }
08608    peer->callno = 0;
08609    peer->lastms = -1;
08610    /* Try again quickly */
08611    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08612    if (peer->pokeexpire == -1)
08613       peer_unref(peer);
08614 }

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

Definition at line 6283 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06284 {
06285    struct iax2_peer *peer = (struct iax2_peer *)data;
06286    iax2_poke_peer(peer, 0);
06287    peer_unref(peer);
06288 }

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

Definition at line 4345 of file chan_iax2.c.

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

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04346 {
04347    regex_t regexbuf;
04348    int havepattern = 0;
04349    int total_peers = 0;
04350    int online_peers = 0;
04351    int offline_peers = 0;
04352    int unmonitored_peers = 0;
04353    struct ao2_iterator i;
04354 
04355 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04356 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04357 
04358    struct iax2_peer *peer = NULL;
04359    char name[256];
04360    int registeredonly=0;
04361    char *term = manager ? "\r\n" : "\n";
04362 
04363    switch (argc) {
04364    case 6:
04365       if (!strcasecmp(argv[3], "registered"))
04366          registeredonly = 1;
04367       else
04368          return RESULT_SHOWUSAGE;
04369       if (!strcasecmp(argv[4], "like")) {
04370          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04371             return RESULT_SHOWUSAGE;
04372          havepattern = 1;
04373       } else
04374          return RESULT_SHOWUSAGE;
04375       break;
04376    case 5:
04377       if (!strcasecmp(argv[3], "like")) {
04378          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04379             return RESULT_SHOWUSAGE;
04380          havepattern = 1;
04381       } else
04382          return RESULT_SHOWUSAGE;
04383       break;
04384    case 4:
04385       if (!strcasecmp(argv[3], "registered"))
04386          registeredonly = 1;
04387       else
04388          return RESULT_SHOWUSAGE;
04389       break;
04390    case 3:
04391       break;
04392    default:
04393       return RESULT_SHOWUSAGE;
04394    }
04395 
04396 
04397    if (s)
04398       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04399    else
04400       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04401 
04402    i = ao2_iterator_init(peers, 0);
04403    for (peer = ao2_iterator_next(&i); peer; 
04404       peer_unref(peer), peer = ao2_iterator_next(&i)) {
04405       char nm[20];
04406       char status[20];
04407       char srch[2000];
04408       int retstatus;
04409 
04410       if (registeredonly && !peer->addr.sin_addr.s_addr)
04411          continue;
04412       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04413          continue;
04414 
04415       if (!ast_strlen_zero(peer->username))
04416          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04417       else
04418          ast_copy_string(name, peer->name, sizeof(name));
04419       
04420       retstatus = peer_status(peer, status, sizeof(status));
04421       if (retstatus > 0)
04422          online_peers++;
04423       else if (!retstatus)
04424          offline_peers++;
04425       else
04426          unmonitored_peers++;
04427       
04428       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04429       
04430       snprintf(srch, sizeof(srch), FORMAT, name, 
04431           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04432           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04433           nm,
04434           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04435           peer->encmethods ? "(E)" : "   ", status, term);
04436       
04437       if (s)
04438          astman_append(s, FORMAT, name, 
04439                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04440                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04441                   nm,
04442                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04443                   peer->encmethods ? "(E)" : "   ", status, term);
04444       else
04445          ast_cli(fd, FORMAT, name, 
04446             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04447             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04448             nm,
04449             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04450             peer->encmethods ? "(E)" : "   ", status, term);
04451       total_peers++;
04452    }
04453 
04454    if (s)
04455       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04456    else
04457       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04458 
04459    if (havepattern)
04460       regfree(&regexbuf);
04461 
04462    return RESULT_SUCCESS;
04463 #undef FORMAT
04464 #undef FORMAT2
04465 }

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

Definition at line 942 of file chan_iax2.c.

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

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

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

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

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

04848 {
04849    struct ast_frame f = { 0, };
04850 
04851    f.frametype = type;
04852    f.subclass = command;
04853    f.datalen = datalen;
04854    f.src = __FUNCTION__;
04855    f.data = (void *) data;
04856 
04857    return iax2_send(i, &f, ts, seqno, now, transfer, final);
04858 }

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

Definition at line 1016 of file chan_iax2.c.

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

Referenced by send_lagrq().

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

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

Definition at line 982 of file chan_iax2.c.

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

Referenced by send_ping().

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

static int __unload_module ( void   )  [static]

Definition at line 10710 of file chan_iax2.c.

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

Referenced by load_module(), and unload_module().

10711 {
10712    struct iax2_thread *thread = NULL;
10713    int x;
10714 
10715    /* Make sure threads do not hold shared resources when they are canceled */
10716    
10717    /* Grab the sched lock resource to keep it away from threads about to die */
10718    /* Cancel the network thread, close the net socket */
10719    if (netthreadid != AST_PTHREADT_NULL) {
10720       AST_LIST_LOCK(&iaxq.queue);
10721       ast_mutex_lock(&sched_lock);
10722       pthread_cancel(netthreadid);
10723       ast_cond_signal(&sched_cond);
10724       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
10725       AST_LIST_UNLOCK(&iaxq.queue);
10726       pthread_join(netthreadid, NULL);
10727    }
10728    if (schedthreadid != AST_PTHREADT_NULL) {
10729       ast_mutex_lock(&sched_lock);  
10730       pthread_cancel(schedthreadid);
10731       ast_cond_signal(&sched_cond);
10732       ast_mutex_unlock(&sched_lock);   
10733       pthread_join(schedthreadid, NULL);
10734    }
10735    
10736    /* Call for all threads to halt */
10737    AST_LIST_LOCK(&idle_list);
10738    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
10739       AST_LIST_REMOVE_CURRENT(&idle_list, list);
10740       pthread_cancel(thread->threadid);
10741    }
10742    AST_LIST_TRAVERSE_SAFE_END
10743    AST_LIST_UNLOCK(&idle_list);
10744 
10745    AST_LIST_LOCK(&active_list);
10746    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
10747       AST_LIST_REMOVE_CURRENT(&active_list, list);
10748       pthread_cancel(thread->threadid);
10749    }
10750    AST_LIST_TRAVERSE_SAFE_END
10751    AST_LIST_UNLOCK(&active_list);
10752 
10753    AST_LIST_LOCK(&dynamic_list);
10754         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
10755       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
10756       pthread_cancel(thread->threadid);
10757         }
10758    AST_LIST_TRAVERSE_SAFE_END
10759         AST_LIST_UNLOCK(&dynamic_list);
10760 
10761    AST_LIST_HEAD_DESTROY(&iaxq.queue);
10762 
10763    /* Wait for threads to exit */
10764    while(0 < iaxactivethreadcount)
10765       usleep(10000);
10766    
10767    ast_netsock_release(netsock);
10768    ast_netsock_release(outsock);
10769    for (x=0;x<IAX_MAX_CALLS;x++)
10770       if (iaxs[x])
10771          iax2_destroy(x);
10772    ast_manager_unregister( "IAXpeers" );
10773    ast_manager_unregister( "IAXnetstats" );
10774    ast_unregister_application(papp);
10775    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10776    ast_unregister_switch(&iax2_switch);
10777    ast_channel_unregister(&iax2_tech);
10778    delete_users();
10779    iax_provision_unload();
10780    sched_context_destroy(sched);
10781    reload_firmware(1);
10782 
10783    ast_mutex_destroy(&waresl.lock);
10784 
10785    for (x = 0; x < IAX_MAX_CALLS; x++)
10786       ast_mutex_destroy(&iaxsl[x]);
10787 
10788    ao2_ref(peers, -1);
10789    ao2_ref(users, -1);
10790 
10791    return 0;
10792 }

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

Definition at line 4899 of file chan_iax2.c.

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

Referenced by check_access().

04900 {
04901    while(con) {
04902       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
04903          return -1;
04904       con = con->next;
04905    }
04906    return 0;
04907 }

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

Definition at line 4673 of file chan_iax2.c.

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

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04674 {
04675    int x;
04676    int numchans = 0;
04677    for (x=0;x<IAX_MAX_CALLS;x++) {
04678       ast_mutex_lock(&iaxsl[x]);
04679       if (iaxs[x]) {
04680          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04681          char *fmt;
04682          jb_info jbinfo;
04683          
04684          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04685             jb_getinfo(iaxs[x]->jb, &jbinfo);
04686             localjitter = jbinfo.jitter;
04687             localdelay = jbinfo.current - jbinfo.min;
04688             locallost = jbinfo.frames_lost;
04689             locallosspct = jbinfo.losspct/1000;
04690             localdropped = jbinfo.frames_dropped;
04691             localooo = jbinfo.frames_ooo;
04692          } else {
04693             localjitter = -1;
04694             localdelay = 0;
04695             locallost = -1;
04696             locallosspct = -1;
04697             localdropped = 0;
04698             localooo = -1;
04699          }
04700          if (limit_fmt)
04701             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04702          else
04703             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04704          if (s)
04705             
04706             astman_append(s, fmt,
04707                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04708                      iaxs[x]->pingtime,
04709                      localjitter, 
04710                      localdelay,
04711                      locallost,
04712                      locallosspct,
04713                      localdropped,
04714                      localooo,
04715                      iaxs[x]->frames_received/1000,
04716                      iaxs[x]->remote_rr.jitter,
04717                      iaxs[x]->remote_rr.delay,
04718                      iaxs[x]->remote_rr.losscnt,
04719                      iaxs[x]->remote_rr.losspct,
04720                      iaxs[x]->remote_rr.dropped,
04721                      iaxs[x]->remote_rr.ooo,
04722                      iaxs[x]->remote_rr.packets/1000);
04723          else
04724             ast_cli(fd, fmt,
04725                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04726                iaxs[x]->pingtime,
04727                localjitter, 
04728                localdelay,
04729                locallost,
04730                locallosspct,
04731                localdropped,
04732                localooo,
04733                iaxs[x]->frames_received/1000,
04734                iaxs[x]->remote_rr.jitter,
04735                iaxs[x]->remote_rr.delay,
04736                iaxs[x]->remote_rr.losscnt,
04737                iaxs[x]->remote_rr.losspct,
04738                iaxs[x]->remote_rr.dropped,
04739                iaxs[x]->remote_rr.ooo,
04740                iaxs[x]->remote_rr.packets/1000
04741                );
04742          numchans++;
04743       }
04744       ast_mutex_unlock(&iaxsl[x]);
04745    }
04746    return numchans;
04747 }

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

Create new call, interface with the PBX core.

Definition at line 3581 of file chan_iax2.c.

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

Referenced by iax2_request(), and socket_process().

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

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02124 {
02125 #ifdef SCHED_MULTITHREADED
02126    if (schedule_action(__attempt_transmit, data))
02127 #endif      
02128       __attempt_transmit(data);
02129    return 0;
02130 }

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

Definition at line 6203 of file chan_iax2.c.

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

Referenced by socket_process().

06204 {
06205    /* Schedule sending the authentication failure in one second, to prevent
06206       guessing */
06207    if (iaxs[callno]) {
06208       iaxs[callno]->authfail = failcode;
06209       if (delayreject) {
06210          if (iaxs[callno]->authid > -1)
06211             ast_sched_del(sched, iaxs[callno]->authid);
06212          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06213       } else
06214          auth_reject((void *)(long)callno);
06215    }
06216    return 0;
06217 }

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

Definition at line 6189 of file chan_iax2.c.

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

Referenced by auth_fail().

06190 {
06191    int callno = (int)(long)(data);
06192    ast_mutex_lock(&iaxsl[callno]);
06193    if (iaxs[callno])
06194       iaxs[callno]->authid = -1;
06195    ast_mutex_unlock(&iaxsl[callno]);
06196 #ifdef SCHED_MULTITHREADED
06197    if (schedule_action(__auth_reject, data))
06198 #endif      
06199       __auth_reject(data);
06200    return 0;
06201 }

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

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

05425 {
05426    int res = -1;
05427    int x;
05428    if (!ast_strlen_zero(keyn)) {
05429       if (!(authmethods & IAX_AUTH_RSA)) {
05430          if (ast_strlen_zero(secret)) 
05431             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));
05432       } else if (ast_strlen_zero(challenge)) {
05433          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05434       } else {
05435          char sig[256];
05436          struct ast_key *key;
05437          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05438          if (!key) {
05439             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05440          } else {
05441             if (ast_sign(key, (char*)challenge, sig)) {
05442                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05443                res = -1;
05444             } else {
05445                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05446                res = 0;
05447             }
05448          }
05449       }
05450    } 
05451    /* Fall back */
05452    if (res && !ast_strlen_zero(secret)) {
05453       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05454          struct MD5Context md5;
05455          unsigned char digest[16];
05456          char digres[128];
05457          MD5Init(&md5);
05458          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05459          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05460          MD5Final(digest, &md5);
05461          /* If they support md5, authenticate with it.  */
05462          for (x=0;x<16;x++)
05463             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05464          if (ecx && dcx)
05465             build_enc_keys(digest, ecx, dcx);
05466          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05467          res = 0;
05468       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05469          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05470          res = 0;
05471       } else
05472          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05473    }
05474    return res;
05475 }

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

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

Referenced by socket_process().

05482 {
05483    struct iax2_peer *peer = NULL;
05484    /* Start pessimistic */
05485    int res = -1;
05486    int authmethods = 0;
05487    struct iax_ie_data ied;
05488    uint16_t callno = p->callno;
05489 
05490    memset(&ied, 0, sizeof(ied));
05491    
05492    if (ies->username)
05493       ast_string_field_set(p, username, ies->username);
05494    if (ies->challenge)
05495       ast_string_field_set(p, challenge, ies->challenge);
05496    if (ies->authmethods)
05497       authmethods = ies->authmethods;
05498    if (authmethods & IAX_AUTH_MD5)
05499       merge_encryption(p, ies->encmethods);
05500    else
05501       p->encmethods = 0;
05502 
05503    /* Check for override RSA authentication first */
05504    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05505       /* Normal password authentication */
05506       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05507    } else {
05508       struct ao2_iterator i = ao2_iterator_init(peers, 0);
05509       while ((peer = ao2_iterator_next(&i))) {
05510          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05511              /* No peer specified at our end, or this is the peer */
05512              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05513              /* No username specified in peer rule, or this is the right username */
05514              && (!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)))
05515              /* No specified host, or this is our host */
05516             ) {
05517             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05518             if (!res) {
05519                peer_unref(peer);
05520                break;
05521             }
05522          }
05523          peer_unref(peer);
05524       }
05525       if (!peer) {
05526          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05527             that we're trying to authenticate *to* a realtime peer */
05528          const char *peer_name = ast_strdupa(p->peer);
05529          ast_mutex_unlock(&iaxsl[callno]);
05530          if ((peer = realtime_peer(peer_name, NULL))) {
05531             ast_mutex_lock(&iaxsl[callno]);
05532             if (!(p = iaxs[callno])) {
05533                peer_unref(peer);
05534                return -1;
05535             }
05536             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05537             peer_unref(peer);
05538          }
05539          if (!peer) {
05540             ast_mutex_lock(&iaxsl[callno]);
05541             if (!(p = iaxs[callno]))
05542                return -1;
05543          }
05544       }
05545    }
05546    if (ies->encmethods)
05547       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05548    if (!res)
05549       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05550    return res;
05551 }

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

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

Referenced by socket_process().

05160 {
05161    struct iax_ie_data ied;
05162    int res = -1, authreq_restrict = 0;
05163    char challenge[10];
05164    struct chan_iax2_pvt *p = iaxs[call_num];
05165 
05166    memset(&ied, 0, sizeof(ied));
05167 
05168    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05169    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05170       struct iax2_user *user, tmp_user = {
05171          .name = p->username, 
05172       };
05173 
05174       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05175       if (user) {
05176          if (user->curauthreq == user->maxauthreq)
05177             authreq_restrict = 1;
05178          else
05179             user->curauthreq++;
05180          user = user_unref(user);
05181       }
05182    }
05183 
05184    /* If the AUTHREQ limit test failed, send back an error */
05185    if (authreq_restrict) {
05186       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05187       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05188       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05189       return 0;
05190    }
05191 
05192    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05193    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05194       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05195       ast_string_field_set(p, challenge, challenge);
05196       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05197       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05198    }
05199    if (p->encmethods)
05200       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05201 
05202    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05203 
05204    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05205 
05206    if (p->encmethods)
05207       ast_set_flag(p, IAX_ENCRYPTED);
05208 
05209    return res;
05210 }

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

Definition at line 5212 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, key(), LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::rsa_result, iax2_registry::secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.

Referenced by socket_process().

05213 {
05214    char requeststr[256];
05215    char md5secret[256] = "";
05216    char secret[256] = "";
05217    char rsasecret[256] = "";
05218    int res = -1; 
05219    int x;
05220    struct iax2_user *user, tmp_user = {
05221       .name = p->username, 
05222    };
05223 
05224    user = ao2_find(users, &tmp_user, OBJ_POINTER);
05225    if (user) {
05226       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05227          ast_atomic_fetchadd_int(&user->curauthreq, -1);
05228          ast_clear_flag(p, IAX_MAXAUTHREQ);
05229       }
05230       ast_string_field_set(p, host, user->name);
05231       user = user_unref(user);
05232    }
05233 
05234    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
05235       return res;
05236    if (ies->password)
05237       ast_copy_string(secret, ies->password, sizeof(secret));
05238    if (ies->md5_result)
05239       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05240    if (ies->rsa_result)
05241       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05242    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
05243       struct ast_key *key;
05244       char *keyn;
05245       char tmpkey[256];
05246       char *stringp=NULL;
05247       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
05248       stringp=tmpkey;
05249       keyn = strsep(&stringp, ":");
05250       while(keyn) {
05251          key = ast_key_get(keyn, AST_KEY_PUBLIC);
05252          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
05253             res = 0;
05254             break;
05255          } else if (!key)
05256             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
05257          keyn = strsep(&stringp, ":");
05258       }
05259    } else if (p->authmethods & IAX_AUTH_MD5) {
05260       struct MD5Context md5;
05261       unsigned char digest[16];
05262       char *tmppw, *stringp;
05263       
05264       tmppw = ast_strdupa(p->secret);
05265       stringp = tmppw;
05266       while((tmppw = strsep(&stringp, ";"))) {
05267          MD5Init(&md5);
05268          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05269          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05270          MD5Final(digest, &md5);
05271          /* If they support md5, authenticate with it.  */
05272          for (x=0;x<16;x++)
05273             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05274          if (!strcasecmp(requeststr, md5secret)) {
05275             res = 0;
05276             break;
05277          }
05278       }
05279    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05280       if (!strcmp(secret, p->secret))
05281          res = 0;
05282    }
05283    return res;
05284 }

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

Definition at line 2999 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03000 {
03001 #ifdef SCHED_MULTITHREADED
03002    if (schedule_action(__auto_congest, data))
03003 #endif      
03004       __auto_congest(data);
03005    return 0;
03006 }

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

Definition at line 6234 of file chan_iax2.c.

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

Referenced by iax2_dprequest(), and iax2_provision().

06235 {
06236    int callno = (int)(long)(data);
06237    ast_mutex_lock(&iaxsl[callno]);
06238    if (iaxs[callno]) {
06239       iaxs[callno]->autoid = -1;
06240    }
06241    ast_mutex_unlock(&iaxsl[callno]);
06242 #ifdef SCHED_MULTITHREADED
06243    if (schedule_action(__auto_hangup, data))
06244 #endif      
06245       __auto_hangup(data);
06246    return 0;
06247 }

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

Definition at line 8910 of file chan_iax2.c.

References ast_calloc, and iax2_context::context.

Referenced by build_user().

08911 {
08912    struct iax2_context *con;
08913 
08914    if ((con = ast_calloc(1, sizeof(*con))))
08915       ast_copy_string(con->context, context, sizeof(con->context));
08916    
08917    return con;
08918 }

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

Definition at line 3942 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

03943 {
03944    aes_encrypt_key128(digest, ecx);
03945    aes_decrypt_key128(digest, dcx);
03946 }

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

Create peer structure based on configuration.

Definition at line 9056 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, ao2_alloc(), ao2_find(), ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), ast_sched_del(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), iax2_peer::authmethods, iax2_peer::capability, cid_name, cid_num, iax2_peer::defaddr, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, iax2_peer::dnsmgr, iax2_peer::encmethods, iax2_peer::expire, iax2_peer::expiry, get_auth_methods(), get_encrypt_methods(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, prefs, iax2_peer::prefs, iax2_registry::secret, iax2_peer::smoothing, iax2_peer::sockfd, unlink_peer(), and ast_variable::value.

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

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

Create in-memory user structure from configuration.

Definition at line 9299 of file chan_iax2.c.

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

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

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

Definition at line 10014 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, iax_ie_data::buf, iax2_registry::callno, chan_iax2_pvt::capability, parsed_dial_string::context, create_addr(), parsed_dial_string::exten, find_callno(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_MAX_CALLS, IAX_PROTO_VERSION, iaxs, iaxsl, parsed_dial_string::key, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, iax_ie_data::pos, iax2_registry::secret, send_command(), create_addr_info::sockfd, and parsed_dial_string::username.

Referenced by find_cache().

10015 {
10016    struct sockaddr_in sin;
10017    int x;
10018    int callno;
10019    struct iax_ie_data ied;
10020    struct create_addr_info cai;
10021    struct parsed_dial_string pds;
10022    char *tmpstr;
10023 
10024    for (x=0; x<IAX_MAX_CALLS; x++) {
10025       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10026          look up entries for a single context */
10027       if (!ast_mutex_trylock(&iaxsl[x])) {
10028          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10029             return x;
10030          ast_mutex_unlock(&iaxsl[x]);
10031       }
10032    }
10033 
10034    /* No match found, we need to create a new one */
10035 
10036    memset(&cai, 0, sizeof(cai));
10037    memset(&ied, 0, sizeof(ied));
10038    memset(&pds, 0, sizeof(pds));
10039 
10040    tmpstr = ast_strdupa(data);
10041    parse_dial_string(tmpstr, &pds);
10042 
10043    /* Populate our address from the given */
10044    if (create_addr(pds.peer, &sin, &cai))
10045       return -1;
10046 
10047    if (option_debug)
10048       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10049          pds.peer, pds.username, pds.password, pds.context);
10050 
10051    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
10052    if (callno < 1) {
10053       ast_log(LOG_WARNING, "Unable to create call\n");
10054       return -1;
10055    }
10056 
10057    ast_mutex_lock(&iaxsl[callno]);
10058    ast_string_field_set(iaxs[callno], dproot, data);
10059    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10060 
10061    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10062    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10063    /* the string format is slightly different from a standard dial string,
10064       because the context appears in the 'exten' position
10065    */
10066    if (pds.exten)
10067       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10068    if (pds.username)
10069       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10070    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10071    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10072    /* Keep password handy */
10073    if (pds.password)
10074       ast_string_field_set(iaxs[callno], secret, pds.password);
10075    if (pds.key)
10076       ast_string_field_set(iaxs[callno], outkey, pds.key);
10077    /* Start the call going */
10078    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10079 
10080    return callno;
10081 }

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

Definition at line 3810 of file chan_iax2.c.

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

03811 {
03812    /* Returns where in "receive time" we are.  That is, how many ms
03813       since we received (or would have received) the frame with timestamp 0 */
03814    int ms;
03815 #ifdef IAXTESTS
03816    int jit;
03817 #endif /* IAXTESTS */
03818    /* Setup rxcore if necessary */
03819    if (ast_tvzero(p->rxcore)) {
03820       p->rxcore = ast_tvnow();
03821       if (option_debug && iaxdebug)
03822          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
03823                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
03824       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
03825 #if 1
03826       if (option_debug && iaxdebug)
03827          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
03828                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
03829 #endif
03830    }
03831 
03832    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
03833 #ifdef IAXTESTS
03834    if (test_jit) {
03835       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
03836          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
03837          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
03838             jit = -jit;
03839          ms += jit;
03840       }
03841    }
03842    if (test_late) {
03843       ms += test_late;
03844       test_late = 0;
03845    }
03846 #endif /* IAXTESTS */
03847    return ms;
03848 }

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

Definition at line 3692 of file chan_iax2.c.

References AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VOICE, ast_log(), ast_tvadd(), ast_tvsub(), chan_iax2_pvt::callno, ast_frame::delivery, ast_frame::frametype, iaxs, chan_iax2_pvt::lastsent, LOG_DEBUG, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, option_debug, chan_iax2_pvt::peercallno, and ast_frame::samples.

Referenced by iax2_send(), and socket_process().

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

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

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

03649 {
03650    unsigned long int mssincetx; /* unsigned to handle overflows */
03651    long int ms, pred;
03652 
03653    tpeer->trunkact = *tv;
03654    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03655    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03656       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03657       tpeer->txtrunktime = *tv;
03658       tpeer->lastsent = 999999;
03659    }
03660    /* Update last transmit time now */
03661    tpeer->lasttxtime = *tv;
03662    
03663    /* Calculate ms offset */
03664    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03665    /* Predict from last value */
03666    pred = tpeer->lastsent + sampms;
03667    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03668       ms = pred;
03669    
03670    /* We never send the same timestamp twice, so fudge a little if we must */
03671    if (ms == tpeer->lastsent)
03672       ms = tpeer->lastsent + 1;
03673    tpeer->lastsent = ms;
03674    return ms;
03675 }

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

Definition at line 4910 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

Definition at line 6588 of file chan_iax2.c.

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

Referenced by socket_process().

06589 {
06590    unsigned int ourver;
06591    char rsi[80];
06592    snprintf(rsi, sizeof(rsi), "si-%s", si);
06593    if (iax_provision_version(&ourver, rsi, 1))
06594       return 0;
06595    if (option_debug)
06596       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06597    if (ourver != ver) 
06598       iax2_provision(sin, sockfd, NULL, rsi, 1);
06599    return 0;
06600 }

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

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

Referenced by peer_set_srcaddr().

08937 {
08938    int sd;
08939    int res;
08940    
08941    sd = socket(AF_INET, SOCK_DGRAM, 0);
08942    if (sd < 0) {
08943       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
08944       return -1;
08945    }
08946 
08947    res = bind(sd, sa, salen);
08948    if (res < 0) {
08949       if (option_debug)
08950          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
08951       close(sd);
08952       return 1;
08953    }
08954 
08955    close(sd);
08956    return 0;
08957 }

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

Definition at line 5600 of file chan_iax2.c.

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

Referenced by socket_process().

05601 {
05602    char exten[256] = "";
05603    int status = CACHE_FLAG_UNKNOWN;
05604    int expiry = iaxdefaultdpcache;
05605    int x;
05606    int matchmore = 0;
05607    struct iax2_dpcache *dp, *prev;
05608    
05609    if (ies->called_number)
05610       ast_copy_string(exten, ies->called_number, sizeof(exten));
05611 
05612    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05613       status = CACHE_FLAG_EXISTS;
05614    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05615       status = CACHE_FLAG_CANEXIST;
05616    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05617       status = CACHE_FLAG_NONEXISTENT;
05618 
05619    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05620       /* Don't really do anything with this */
05621    }
05622    if (ies->refresh)
05623       expiry = ies->refresh;
05624    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05625       matchmore = CACHE_FLAG_MATCHMORE;
05626    ast_mutex_lock(&dpcache_lock);
05627    prev = NULL;
05628    dp = pvt->dpentries;
05629    while(dp) {
05630       if (!strcmp(dp->exten, exten)) {
05631          /* Let them go */
05632          if (prev)
05633             prev->peer = dp->peer;
05634          else
05635             pvt->dpentries = dp->peer;
05636          dp->peer = NULL;
05637          dp->callno = 0;
05638          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05639          if (dp->flags & CACHE_FLAG_PENDING) {
05640             dp->flags &= ~CACHE_FLAG_PENDING;
05641             dp->flags |= status;
05642             dp->flags |= matchmore;
05643          }
05644          /* Wake up waiters */
05645          for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
05646             if (dp->waiters[x] > -1)
05647                write(dp->waiters[x], "asdf", 4);
05648       }
05649       prev = dp;
05650       dp = dp->peer;
05651    }
05652    ast_mutex_unlock(&dpcache_lock);
05653    return 0;
05654 }

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

Definition at line 2285 of file chan_iax2.c.

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

02286 {
02287    int which = 0;
02288    struct iax2_peer *peer;
02289    char *res = NULL;
02290    int wordlen = strlen(word);
02291    struct ao2_iterator i;
02292 
02293    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02294    if (pos != 3)
02295       return NULL;
02296 
02297    i = ao2_iterator_init(peers, 0);
02298    while ((peer = ao2_iterator_next(&i))) {
02299       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02300          res = ast_strdup(peer->name);
02301          peer_unref(peer);
02302          break;
02303       }
02304       peer_unref(peer);
02305    }
02306 
02307    return res;
02308 }

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

Definition at line 5656 of file chan_iax2.c.

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

Referenced by socket_process().

05657 {
05658    int peercallno = 0;
05659    struct chan_iax2_pvt *pvt = iaxs[callno];
05660    struct iax_frame *cur;
05661    jb_frame frame;
05662 
05663    if (ies->callno)
05664       peercallno = ies->callno;
05665 
05666    if (peercallno < 1) {
05667       ast_log(LOG_WARNING, "Invalid transfer request\n");
05668       return -1;
05669    }
05670    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05671    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05672    /* Reset sequence numbers */
05673    pvt->oseqno = 0;
05674    pvt->rseqno = 0;
05675    pvt->iseqno = 0;
05676    pvt->aseqno = 0;
05677    pvt->peercallno = peercallno;
05678    pvt->transferring = TRANSFER_NONE;
05679    pvt->svoiceformat = -1;
05680    pvt->voiceformat = 0;
05681    pvt->svideoformat = -1;
05682    pvt->videoformat = 0;
05683    pvt->transfercallno = -1;
05684    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05685    memset(&pvt->offset, 0, sizeof(pvt->offset));
05686    /* reset jitterbuffer */
05687    while(jb_getall(pvt->jb,&frame) == JB_OK)
05688       iax2_frame_free(frame.data);
05689    jb_reset(pvt->jb);
05690    pvt->lag = 0;
05691    pvt->last = 0;
05692    pvt->lastsent = 0;
05693    pvt->nextpred = 0;
05694    pvt->pingtime = DEFAULT_RETRY_TIME;
05695    AST_LIST_LOCK(&iaxq.queue);
05696    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05697       /* We must cancel any packets that would have been transmitted
05698          because now we're talking to someone new.  It's okay, they
05699          were transmitted to someone that didn't care anyway. */
05700       if (callno == cur->callno) 
05701          cur->retries = -1;
05702    }
05703    AST_LIST_UNLOCK(&iaxq.queue);
05704    return 0; 
05705 }

static unsigned char compress_subclass ( int  subclass  )  [static]

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

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

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

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

06603 {
06604    jb_info stats;
06605    jb_getinfo(pvt->jb, &stats);
06606    
06607    memset(iep, 0, sizeof(*iep));
06608 
06609    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06610    if(stats.frames_in == 0) stats.frames_in = 1;
06611    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06612    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06613    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06614    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06615    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06616 }

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

Definition at line 2902 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, key(), iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, 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.

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

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

Definition at line 3996 of file chan_iax2.c.

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

Referenced by decrypt_frame().

03997 {
03998    int padding;
03999    unsigned char *workspace;
04000 
04001    workspace = alloca(*datalen);
04002    memset(f, 0, sizeof(*f));
04003    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04004       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04005       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04006          return -1;
04007       /* Decrypt */
04008       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04009 
04010       padding = 16 + (workspace[15] & 0xf);
04011       if (option_debug && iaxdebug)
04012          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04013       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04014          return -1;
04015 
04016       *datalen -= padding;
04017       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04018       f->frametype = fh->type;
04019       if (f->frametype == AST_FRAME_VIDEO) {
04020          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04021       } else {
04022          f->subclass = uncompress_subclass(fh->csub);
04023       }
04024    } else {
04025       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04026       if (option_debug && iaxdebug)
04027          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04028       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04029          return -1;
04030       /* Decrypt */
04031       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04032       padding = 16 + (workspace[15] & 0x0f);
04033       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04034          return -1;
04035       *datalen -= padding;
04036       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04037    }
04038    return 0;
04039 }

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

Definition at line 4082 of file chan_iax2.c.

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

Referenced by socket_process().

04083 {
04084    int res=-1;
04085    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04086       /* Search for possible keys, given secrets */
04087       struct MD5Context md5;
04088       unsigned char digest[16];
04089       char *tmppw, *stringp;
04090       
04091       tmppw = ast_strdupa(iaxs[callno]->secret);
04092       stringp = tmppw;
04093       while ((tmppw = strsep(&stringp, ";"))) {
04094          MD5Init(&md5);
04095          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04096          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04097          MD5Final(digest, &md5);
04098          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04099          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04100          if (!res) {
04101             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04102             break;
04103          }
04104       }
04105    } else 
04106       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04107    return res;
04108 }

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

06665 {
06666    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06667    struct ast_iax2_full_hdr *fh, *cur_fh;
06668 
06669    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06670       return;
06671 
06672    pkt_buf->len = from_here->buf_len;
06673    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06674 
06675    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06676    ast_mutex_lock(&to_here->lock);
06677    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06678       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06679       if (fh->oseqno < cur_fh->oseqno) {
06680          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06681          break;
06682       }
06683    }
06684    AST_LIST_TRAVERSE_SAFE_END
06685 
06686    if (!cur_pkt_buf)
06687       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06688    
06689    ast_mutex_unlock(&to_here->lock);
06690 }

static void delete_users ( void   )  [static]

Definition at line 9530 of file chan_iax2.c.

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

09531 {
09532    struct iax2_registry *reg;
09533 
09534    ao2_callback(users, 0, user_delme_cb, NULL);
09535 
09536    AST_LIST_LOCK(&registrations);
09537    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09538       if (reg->expire > -1)
09539          ast_sched_del(sched, reg->expire);
09540       if (reg->callno) {
09541          ast_mutex_lock(&iaxsl[reg->callno]);
09542          if (iaxs[reg->callno]) {
09543             iaxs[reg->callno]->reg = NULL;
09544             iax2_destroy(reg->callno);
09545          }
09546          ast_mutex_unlock(&iaxsl[reg->callno]);
09547       }
09548       if (reg->dnsmgr)
09549          ast_dnsmgr_release(reg->dnsmgr);
09550       free(reg);
09551    }
09552    AST_LIST_UNLOCK(&registrations);
09553 
09554    ao2_callback(peers, 0, peer_delme_cb, NULL);
09555 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1528 of file chan_iax2.c.

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

Referenced by reload_firmware().

01529 {
01530    /* Close firmware */
01531    if (cur->fwh) {
01532       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01533    }
01534    close(cur->fd);
01535    free(cur);
01536 }

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

Definition at line 6436 of file chan_iax2.c.

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

Referenced by dp_lookup_thread(), and socket_process().

06437 {
06438    unsigned short dpstatus = 0;
06439    struct iax_ie_data ied1;
06440    int mm;
06441 
06442    memset(&ied1, 0, sizeof(ied1));
06443    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06444    /* Must be started */
06445    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06446       dpstatus = IAX_DPSTATUS_EXISTS;
06447    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06448       dpstatus = IAX_DPSTATUS_CANEXIST;
06449    } else {
06450       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06451    }
06452    if (ast_ignore_pattern(context, callednum))
06453       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06454    if (mm)
06455       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06456    if (!skiplock)
06457       ast_mutex_lock(&iaxsl[callno]);
06458    if (iaxs[callno]) {
06459       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06460       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06461       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06462       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06463    }
06464    if (!skiplock)
06465       ast_mutex_unlock(&iaxsl[callno]);
06466 }

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

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

06469 {
06470    /* Look up for dpreq */
06471    struct dpreq_data *dpr = data;
06472    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06473    if (dpr->callerid)
06474       free(dpr->callerid);
06475    free(dpr);
06476    return NULL;
06477 }

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

Definition at line 4041 of file chan_iax2.c.

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

Referenced by iax2_send().

04042 {
04043    int padding;
04044    unsigned char *workspace;
04045    workspace = alloca(*datalen + 32);
04046    if (!workspace)
04047       return -1;
04048    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04049       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04050       if (option_debug && iaxdebug)
04051          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04052       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04053       padding = 16 + (padding & 0xf);
04054       memcpy(workspace, poo, padding);
04055       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04056       workspace[15] &= 0xf0;
04057       workspace[15] |= (padding & 0xf);
04058       if (option_debug && iaxdebug)
04059          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]);
04060       *datalen += padding;
04061       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04062       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04063          memcpy(poo, workspace + *datalen - 32, 32);
04064    } else {
04065       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04066       if (option_debug && iaxdebug)
04067          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04068       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04069       padding = 16 + (padding & 0xf);
04070       memcpy(workspace, poo, padding);
04071       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04072       workspace[15] &= 0xf0;
04073       workspace[15] |= (padding & 0x0f);
04074       *datalen += padding;
04075       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04076       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04077          memcpy(poo, workspace + *datalen - 32, 32);
04078    }
04079    return 0;
04080 }

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

Definition at line 5888 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

05889 {
05890 #ifdef SCHED_MULTITHREADED
05891    if (schedule_action(__expire_registry, data))
05892 #endif      
05893       __expire_registry(data);
05894    return 0;
05895 }

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

Definition at line 10083 of file chan_iax2.c.

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

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

10084 {
10085    struct iax2_dpcache *dp, *prev = NULL, *next;
10086    struct timeval tv;
10087    int x;
10088    int com[2];
10089    int timeout;
10090    int old=0;
10091    int outfd;
10092    int abort;
10093    int callno;
10094    struct ast_channel *c;
10095    struct ast_frame *f;
10096    gettimeofday(&tv, NULL);
10097    dp = dpcache;
10098    while(dp) {
10099       next = dp->next;
10100       /* Expire old caches */
10101       if (ast_tvcmp(tv, dp->expiry) > 0) {
10102             /* It's expired, let it disappear */
10103             if (prev)
10104                prev->next = dp->next;
10105             else
10106                dpcache = dp->next;
10107             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
10108                /* Free memory and go again */
10109                free(dp);
10110             } else {
10111                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);
10112             }
10113             dp = next;
10114             continue;
10115       }
10116       /* We found an entry that matches us! */
10117       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
10118          break;
10119       prev = dp;
10120       dp = next;
10121    }
10122    if (!dp) {
10123       /* No matching entry.  Create a new one. */
10124       /* First, can we make a callno? */
10125       callno = cache_get_callno_locked(data);
10126       if (callno < 0) {
10127          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
10128          return NULL;
10129       }
10130       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
10131          ast_mutex_unlock(&iaxsl[callno]);
10132          return NULL;
10133       }
10134       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
10135       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
10136       gettimeofday(&dp->expiry, NULL);
10137       dp->orig = dp->expiry;
10138       /* Expires in 30 mins by default */
10139       dp->expiry.tv_sec += iaxdefaultdpcache;
10140       dp->next = dpcache;
10141       dp->flags = CACHE_FLAG_PENDING;
10142       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10143          dp->waiters[x] = -1;
10144       dpcache = dp;
10145       dp->peer = iaxs[callno]->dpentries;
10146       iaxs[callno]->dpentries = dp;
10147       /* Send the request if we're already up */
10148       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
10149          iax2_dprequest(dp, callno);
10150       ast_mutex_unlock(&iaxsl[callno]);
10151    }
10152    /* By here we must have a dp */
10153    if (dp->flags & CACHE_FLAG_PENDING) {
10154       /* Okay, here it starts to get nasty.  We need a pipe now to wait
10155          for a reply to come back so long as it's pending */
10156       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
10157          /* Find an empty slot */
10158          if (dp->waiters[x] < 0)
10159             break;
10160       }
10161       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
10162          ast_log(LOG_WARNING, "No more waiter positions available\n");
10163          return NULL;
10164       }
10165       if (pipe(com)) {
10166          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
10167          return NULL;
10168       }
10169       dp->waiters[x] = com[1];
10170       /* Okay, now we wait */
10171       timeout = iaxdefaulttimeout * 1000;
10172       /* Temporarily unlock */
10173       ast_mutex_unlock(&dpcache_lock);
10174       /* Defer any dtmf */
10175       if (chan)
10176          old = ast_channel_defer_dtmf(chan);
10177       abort = 0;
10178       while(timeout) {
10179          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
10180          if (outfd > -1) {
10181             break;
10182          }
10183          if (c) {
10184             f = ast_read(c);
10185             if (f)
10186                ast_frfree(f);
10187             else {
10188                /* Got hung up on, abort! */
10189                break;
10190                abort = 1;
10191             }
10192          }
10193       }
10194       if (!timeout) {
10195          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
10196       }
10197       ast_mutex_lock(&dpcache_lock);
10198       dp->waiters[x] = -1;
10199       close(com[1]);
10200       close(com[0]);
10201       if (abort) {
10202          /* Don't interpret anything, just abort.  Not sure what th epoint
10203            of undeferring dtmf on a hung up channel is but hey whatever */
10204          if (!old && chan)
10205             ast_channel_undefer_dtmf(chan);
10206          return NULL;
10207       }
10208       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
10209          /* Now to do non-independent analysis the results of our wait */
10210          if (dp->flags & CACHE_FLAG_PENDING) {
10211             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
10212                pending.  Don't let it take as long to timeout. */
10213             dp->flags &= ~CACHE_FLAG_PENDING;
10214             dp->flags |= CACHE_FLAG_TIMEOUT;
10215             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
10216                systems without leaving it unavailable once the server comes back online */
10217             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
10218             for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10219                if (dp->waiters[x] > -1)
10220                   write(dp->waiters[x], "asdf", 4);
10221          }
10222       }
10223       /* Our caller will obtain the rest */
10224       if (!old && chan)
10225          ast_channel_undefer_dtmf(chan);
10226    }
10227    return dp;  
10228 }

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

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

Definition at line 1342 of file chan_iax2.c.

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

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

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

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

Definition at line 893 of file chan_iax2.c.

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

Referenced by __schedule_action(), and socket_read().

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

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

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

Definition at line 1115 of file chan_iax2.c.

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

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

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

Definition at line 3850 of file chan_iax2.c.

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

Referenced by iax2_trunk_queue(), and socket_process().

03851 {
03852    struct iax2_trunk_peer *tpeer;
03853    
03854    /* Finds and locks trunk peer */
03855    ast_mutex_lock(&tpeerlock);
03856    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
03857       /* We don't lock here because tpeer->addr *never* changes */
03858       if (!inaddrcmp(&tpeer->addr, sin)) {
03859          ast_mutex_lock(&tpeer->lock);
03860          break;
03861       }
03862    }
03863    if (!tpeer) {
03864       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
03865          ast_mutex_init(&tpeer->lock);
03866          tpeer->lastsent = 9999;
03867          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
03868          tpeer->trunkact = ast_tvnow();
03869          ast_mutex_lock(&tpeer->lock);
03870          tpeer->next = tpeers;
03871          tpeer->sockfd = fd;
03872          tpeers = tpeer;
03873 #ifdef SO_NO_CHECK
03874          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
03875 #endif
03876          if (option_debug)
03877             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
03878       }
03879    }
03880    ast_mutex_unlock(&tpeerlock);
03881    return tpeer;
03882 }

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

Definition at line 3677 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03678 {
03679    long ms; /* NOT unsigned */
03680    if (ast_tvzero(iaxs[callno]->rxcore)) {
03681       /* Initialize rxcore time if appropriate */
03682       gettimeofday(&iaxs[callno]->rxcore, NULL);
03683       /* Round to nearest 20ms so traces look pretty */
03684       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03685    }
03686    /* Calculate difference between trunk and channel */
03687    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03688    /* Return as the sum of trunk time and the difference between trunk and real time */
03689    return ms + ts;
03690 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8692 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08693 {
08694    struct iax2_context *conl;
08695    while(con) {
08696       conl = con;
08697       con = con->next;
08698       free(conl);
08699    }
08700 }

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

Todo:
: will be removed after the 1.4 relese

Definition at line 10352 of file chan_iax2.c.

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

10353 {
10354    struct iax2_peer *peer;
10355    char *peername, *colname;
10356 
10357    peername = ast_strdupa(data);
10358 
10359    /* if our channel, return the IP address of the endpoint of current channel */
10360    if (!strcmp(peername,"CURRENTCHANNEL")) {
10361            unsigned short callno;
10362       if (chan->tech != &iax2_tech)
10363          return -1;
10364       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10365       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10366       return 0;
10367    }
10368 
10369    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10370       *colname++ = '\0';
10371    else if ((colname = strchr(peername, '|')))
10372       *colname++ = '\0';
10373    else
10374       colname = "ip";
10375 
10376    if (!(peer = find_peer(peername, 1)))
10377       return -1;
10378 
10379    if (!strcasecmp(colname, "ip")) {
10380       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10381    } else  if (!strcasecmp(colname, "status")) {
10382       peer_status(peer, buf, len); 
10383    } else  if (!strcasecmp(colname, "mailbox")) {
10384       ast_copy_string(buf, peer->mailbox, len);
10385    } else  if (!strcasecmp(colname, "context")) {
10386       ast_copy_string(buf, peer->context, len);
10387    } else  if (!strcasecmp(colname, "expire")) {
10388       snprintf(buf, len, "%d", peer->expire);
10389    } else  if (!strcasecmp(colname, "dynamic")) {
10390       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10391    } else  if (!strcasecmp(colname, "callerid_name")) {
10392       ast_copy_string(buf, peer->cid_name, len);
10393    } else  if (!strcasecmp(colname, "callerid_num")) {
10394       ast_copy_string(buf, peer->cid_num, len);
10395    } else  if (!strcasecmp(colname, "codecs")) {
10396       ast_getformatname_multiple(buf, len -1, peer->capability);
10397    } else  if (!strncasecmp(colname, "codec[", 6)) {
10398       char *codecnum, *ptr;
10399       int index = 0, codec = 0;
10400       
10401       codecnum = strchr(colname, '[');
10402       *codecnum = '\0';
10403       codecnum++;
10404       if ((ptr = strchr(codecnum, ']'))) {
10405          *ptr = '\0';
10406       }
10407       index = atoi(codecnum);
10408       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10409          ast_copy_string(buf, ast_getformatname(codec), len);
10410       }
10411    }
10412 
10413    peer_unref(peer);
10414 
10415    return 0;
10416 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 8920 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

08921 {
08922    int methods = 0;
08923    if (strstr(value, "rsa"))
08924       methods |= IAX_AUTH_RSA;
08925    if (strstr(value, "md5"))
08926       methods |= IAX_AUTH_MD5;
08927    if (strstr(value, "plaintext"))
08928       methods |= IAX_AUTH_PLAINTEXT;
08929    return methods;
08930 }

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

Definition at line 1002 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

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

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

Definition at line 2516 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

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

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6634 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

06635 {
06636    struct iax2_pkt_buf *pkt_buf;
06637 
06638    ast_mutex_lock(&thread->lock);
06639 
06640    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06641       ast_mutex_unlock(&thread->lock);
06642 
06643       thread->buf = pkt_buf->buf;
06644       thread->buf_len = pkt_buf->len;
06645       thread->buf_size = pkt_buf->len + 1;
06646       
06647       socket_process(thread);
06648 
06649       thread->buf = NULL;
06650       ast_free(pkt_buf);
06651 
06652       ast_mutex_lock(&thread->lock);
06653    }
06654 
06655    ast_mutex_unlock(&thread->lock);
06656 }

static int handle_error ( void   )  [static]

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

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

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

Acknowledgment received for OUR registration.

Definition at line 5708 of file chan_iax2.c.

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

Referenced by socket_process().

05709 {
05710    struct iax2_registry *reg;
05711    /* Start pessimistic */
05712    char peer[256] = "";
05713    char msgstatus[60];
05714    int refresh = 60;
05715    char ourip[256] = "<Unspecified>";
05716    struct sockaddr_in oldus;
05717    struct sockaddr_in us;
05718    int oldmsgs;
05719 
05720    memset(&us, 0, sizeof(us));
05721    if (ies->apparent_addr)
05722       bcopy(ies->apparent_addr, &us, sizeof(us));
05723    if (ies->username)
05724       ast_copy_string(peer, ies->username, sizeof(peer));
05725    if (ies->refresh)
05726       refresh = ies->refresh;
05727    if (ies->calling_number) {
05728       /* We don't do anything with it really, but maybe we should */
05729    }
05730    reg = iaxs[callno]->reg;
05731    if (!reg) {
05732       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
05733       return -1;
05734    }
05735    memcpy(&oldus, &reg->us, sizeof(oldus));
05736    oldmsgs = reg->messages;
05737    if (inaddrcmp(&reg->addr, sin)) {
05738       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
05739       return -1;
05740    }
05741    memcpy(&reg->us, &us, sizeof(reg->us));
05742    if (ies->msgcount >= 0)
05743       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
05744    /* always refresh the registration at the interval requested by the server
05745       we are registering to
05746    */
05747    reg->refresh = refresh;
05748    if (reg->expire > -1)
05749       ast_sched_del(sched, reg->expire);
05750    reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
05751    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
05752       if (option_verbose > 2) {
05753          if (reg->messages > 255)
05754             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
05755          else if (reg->messages > 1)
05756             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
05757          else if (reg->messages > 0)
05758             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
05759          else
05760             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
05761          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05762          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
05763       }
05764       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
05765    }
05766    reg->regstate = REG_STATE_REGISTERED;
05767    return 0;
05768 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3498 of file chan_iax2.c.

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

03499 {
03500    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03501    if (option_debug)
03502       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03503    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03504 }

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

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

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

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

Definition at line 3096 of file chan_iax2.c.

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

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

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

10255 {
10256    int res = 0;
10257    struct iax2_dpcache *dp;
10258 #if 0
10259    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10260 #endif
10261    if ((priority != 1) && (priority != 2))
10262       return 0;
10263    ast_mutex_lock(&dpcache_lock);
10264    dp = find_cache(chan, data, context, exten, priority);
10265    if (dp) {
10266       if (dp->flags & CACHE_FLAG_CANEXIST)
10267          res= 1;
10268    }
10269    ast_mutex_unlock(&dpcache_lock);
10270    if (!dp) {
10271       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10272    }
10273    return res;
10274 }

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

Definition at line 3008 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03009 {
03010    time_t t;
03011    struct tm tm;
03012    unsigned int tmp;
03013    time(&t);
03014    if (!ast_strlen_zero(tz))
03015       ast_localtime(&t, &tm, tz);
03016    else
03017       ast_localtime(&t, &tm, NULL);
03018    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03019    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03020    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03021    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03022    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03023    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03024    return tmp;
03025 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1959 of file chan_iax2.c.

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

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

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1896 of file chan_iax2.c.

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

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

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

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 10441 of file chan_iax2.c.

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

10442 {
10443    struct parsed_dial_string pds;
10444    char *tmp = ast_strdupa(data);
10445    struct iax2_peer *p;
10446    int res = AST_DEVICE_INVALID;
10447 
10448    memset(&pds, 0, sizeof(pds));
10449    parse_dial_string(tmp, &pds);
10450    if (ast_strlen_zero(pds.peer))
10451       return res;
10452    
10453    if (option_debug > 2)
10454       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10455 
10456    /* SLD: FIXME: second call to find_peer during registration */
10457    if (!(p = find_peer(pds.peer, 1)))
10458       return res;
10459 
10460    res = AST_DEVICE_UNAVAILABLE;
10461    if (option_debug > 2) 
10462       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10463          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10464    
10465    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10466        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10467       /* Peer is registered, or have default IP address
10468          and a valid registration */
10469       if (p->historicms == 0 || p->historicms <= p->maxms)
10470          /* let the core figure out whether it is in use or not */
10471          res = AST_DEVICE_UNKNOWN;  
10472    }
10473 
10474    peer_unref(p);
10475 
10476    return res;
10477 }

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

Definition at line 2635 of file chan_iax2.c.

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

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

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

Definition at line 2640 of file chan_iax2.c.

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

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

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

Definition at line 4761 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04762 {
04763    if (argc < 2 || argc > 3)
04764       return RESULT_SHOWUSAGE;
04765    iaxdebug = 1;
04766    ast_cli(fd, "IAX2 Debugging Enabled\n");
04767    return RESULT_SUCCESS;
04768 }

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

Definition at line 4779 of file chan_iax2.c.

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

04780 {
04781    if (argc < 3 || argc > 4)
04782       return RESULT_SHOWUSAGE;
04783    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04784    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04785    return RESULT_SUCCESS;
04786 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8417 of file chan_iax2.c.

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

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

08418 {
08419    struct iax_ie_data ied;
08420    if (option_debug && iaxdebug)
08421       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08422 
08423    if (reg->dnsmgr && 
08424        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08425       /* Maybe the IP has changed, force DNS refresh */
08426       ast_dnsmgr_refresh(reg->dnsmgr);
08427    }
08428    
08429    /*
08430     * if IP has Changed, free allocated call to create a new one with new IP
08431     * call has the pointer to IP and must be updated to the new one
08432     */
08433    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08434       ast_mutex_lock(&iaxsl[reg->callno]);
08435       iax2_destroy(reg->callno);
08436       ast_mutex_unlock(&iaxsl[reg->callno]);
08437       reg->callno = 0;
08438    }
08439    if (!reg->addr.sin_addr.s_addr) {
08440       if (option_debug && iaxdebug)
08441          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08442       /* Setup the next registration attempt */
08443       if (reg->expire > -1)
08444          ast_sched_del(sched, reg->expire);
08445       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08446       return -1;
08447    }
08448 
08449    if (!reg->callno) {
08450       if (option_debug)
08451          ast_log(LOG_DEBUG, "Allocate call number\n");
08452       reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE, defaultsockfd);
08453       if (reg->callno < 1) {
08454          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08455          return -1;
08456       } else if (option_debug)
08457          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08458       iaxs[reg->callno]->reg = reg;
08459    }
08460    /* Schedule the next registration attempt */
08461    if (reg->expire > -1)
08462       ast_sched_del(sched, reg->expire);
08463    /* Setup the next registration a little early */
08464    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08465    /* Send the request */
08466    memset(&ied, 0, sizeof(ied));
08467    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08468    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08469    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08470    reg->regstate = REG_STATE_REGSENT;
08471    return 0;
08472 }

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

Definition at line 5562 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05563 {
05564 #ifdef SCHED_MULTITHREADED
05565    if (schedule_action(__iax2_do_register_s, data))
05566 #endif      
05567       __iax2_do_register_s(data);
05568    return 0;
05569 }

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

Definition at line 4770 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04771 {
04772    if (argc < 3 || argc > 4)
04773       return RESULT_SHOWUSAGE;
04774    iaxtrunkdebug = 1;
04775    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04776    return RESULT_SUCCESS;
04777 }

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

Definition at line 6249 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

06250 {
06251    struct iax_ie_data ied;
06252    /* Auto-hangup with 30 seconds of inactivity */
06253    if (iaxs[callno]->autoid > -1)
06254       ast_sched_del(sched, iaxs[callno]->autoid);
06255    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06256    memset(&ied, 0, sizeof(ied));
06257    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06258    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06259    dp->flags |= CACHE_FLAG_TRANSMITTED;
06260 }

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

10301 {
10302    char odata[256];
10303    char req[256];
10304    char *ncontext;
10305    struct iax2_dpcache *dp;
10306    struct ast_app *dial;
10307 #if 0
10308    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);
10309 #endif
10310    if (priority == 2) {
10311       /* Indicate status, can be overridden in dialplan */
10312       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10313       if (dialstatus) {
10314          dial = pbx_findapp(dialstatus);
10315          if (dial) 
10316             pbx_exec(chan, dial, "");
10317       }
10318       return -1;
10319    } else if (priority != 1)
10320       return -1;
10321    ast_mutex_lock(&dpcache_lock);
10322    dp = find_cache(chan, data, context, exten, priority);
10323    if (dp) {
10324       if (dp->flags & CACHE_FLAG_EXISTS) {
10325          ast_copy_string(odata, data, sizeof(odata));
10326          ncontext = strchr(odata, '/');
10327          if (ncontext) {
10328             *ncontext = '\0';
10329             ncontext++;
10330             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10331          } else {
10332             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10333          }
10334          if (option_verbose > 2)
10335             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10336       } else {
10337          ast_mutex_unlock(&dpcache_lock);
10338          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10339          return -1;
10340       }
10341    }
10342    ast_mutex_unlock(&dpcache_lock);
10343    dial = pbx_findapp("Dial");
10344    if (dial) {
10345       return pbx_exec(chan, dial, req);
10346    } else {
10347       ast_log(LOG_WARNING, "No dial application registered\n");
10348    }
10349    return -1;
10350 }

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

10232 {
10233    struct iax2_dpcache *dp;
10234    int res = 0;
10235 #if 0
10236    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10237 #endif
10238    if ((priority != 1) && (priority != 2))
10239       return 0;
10240    ast_mutex_lock(&dpcache_lock);
10241    dp = find_cache(chan, data, context, exten, priority);
10242    if (dp) {
10243       if (dp->flags & CACHE_FLAG_EXISTS)
10244          res= 1;
10245    }
10246    ast_mutex_unlock(&dpcache_lock);
10247    if (!dp) {
10248       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10249    }
10250    return res;
10251 }

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

Definition at line 2662 of file chan_iax2.c.

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

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

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1425 of file chan_iax2.c.

References ast_sched_del(), iax_frame_free(), and iax_frame::retrans.

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

01426 {
01427    if (fr->retrans > -1)
01428       ast_sched_del(sched, fr->retrans);
01429    iax_frame_free(fr);
01430 }

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

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

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

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03561 {
03562    struct iax2_peer *peer;
03563    int res = 0;
03564    struct ao2_iterator i;
03565 
03566    i = ao2_iterator_init(peers, 0);
03567    while ((peer = ao2_iterator_next(&i))) {
03568       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03569           (peer->addr.sin_port == sin.sin_port)) {
03570          res = ast_test_flag(peer, IAX_TRUNK);
03571          peer_unref(peer);
03572          break;
03573       }
03574       peer_unref(peer);
03575    }
03576 
03577    return res;
03578 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3237 of file chan_iax2.c.

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

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

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

Definition at line 3506 of file chan_iax2.c.

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

03507 {
03508    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03509    struct chan_iax2_pvt *pvt;
03510    int res = 0;
03511 
03512    if (option_debug && iaxdebug)
03513       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03514 
03515    ast_mutex_lock(&iaxsl[callno]);
03516    pvt = iaxs[callno];
03517 
03518    switch (condition) {
03519    case AST_CONTROL_HOLD:
03520       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03521          ast_moh_start(c, data, pvt->mohinterpret);
03522          goto done;
03523       }
03524       break;
03525    case AST_CONTROL_UNHOLD:
03526       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03527          ast_moh_stop(c);
03528          goto done;
03529       }
03530    }
03531 
03532    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03533 
03534 done:
03535    ast_mutex_unlock(&iaxsl[callno]);
03536 
03537    return res;
03538 }

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

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

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

Definition at line 4788 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04789 {
04790    if (argc < 3 || argc > 4)
04791       return RESULT_SHOWUSAGE;
04792    iaxdebug = 0;
04793    ast_cli(fd, "IAX2 Debugging Disabled\n");
04794    return RESULT_SUCCESS;
04795 }

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

Definition at line 4806 of file chan_iax2.c.

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

04807 {
04808    if (argc < 4 || argc > 5)
04809       return RESULT_SHOWUSAGE;
04810    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04811    jb_debug_output("\n");
04812    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04813    return RESULT_SUCCESS;
04814 }

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

Definition at line 4797 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04798 {
04799    if (argc < 4 || argc > 5)
04800       return RESULT_SHOWUSAGE;
04801    iaxtrunkdebug = 0;
04802    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
04803    return RESULT_SUCCESS;
04804 }

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

Definition at line 8616 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08617 {
08618    struct iax2_peer *peer = (struct iax2_peer *)data;
08619    peer->pokeexpire = -1;
08620 #ifdef SCHED_MULTITHREADED
08621    if (schedule_action(__iax2_poke_noanswer, data))
08622 #endif      
08623       __iax2_poke_noanswer(data);
08624    peer_unref(peer);
08625    return 0;
08626 }

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

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

08638 {
08639    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
08640       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
08641         immediately after clearing things out */
08642       peer->lastms = 0;
08643       peer->historicms = 0;
08644       peer->pokeexpire = -1;
08645       peer->callno = 0;
08646       return 0;
08647    }
08648    if (peer->callno > 0) {
08649       ast_log(LOG_NOTICE, "Still have a callno...\n");
08650       ast_mutex_lock(&iaxsl[peer->callno]);
08651       iax2_destroy(peer->callno);
08652       ast_mutex_unlock(&iaxsl[peer->callno]);
08653    }
08654    if (heldcall)
08655       ast_mutex_unlock(&iaxsl[heldcall]);
08656    peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd);
08657    if (heldcall)
08658       ast_mutex_lock(&iaxsl[heldcall]);
08659    if (peer->callno < 1) {
08660       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
08661       return -1;
08662    }
08663 
08664    /* Speed up retransmission times for this qualify call */
08665    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
08666    iaxs[peer->callno]->peerpoke = peer;
08667    
08668    /* Remove any pending pokeexpire task */
08669    if (peer->pokeexpire > -1) {
08670       if (!ast_sched_del(sched, peer->pokeexpire)) {
08671          peer->pokeexpire = -1;
08672          peer_unref(peer);
08673       }
08674    }
08675 
08676    /* Queue up a new task to handle no reply */
08677    /* If the host is already unreachable then use the unreachable interval instead */
08678    if (peer->lastms < 0) {
08679       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
08680    } else
08681       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
08682 
08683    if (peer->pokeexpire == -1)
08684       peer_unref(peer);
08685 
08686    /* And send the poke */
08687    send_command(iaxs[peer->callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
08688 
08689    return 0;
08690 }

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

Definition at line 8628 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08629 {
08630    struct iax2_peer *peer = obj;
08631 
08632    iax2_poke_peer(peer, 0);
08633 
08634    return 0;
08635 }

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

Definition at line 6290 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06291 {
06292    struct iax2_peer *peer = (struct iax2_peer *)data;
06293    peer->pokeexpire = -1;
06294 #ifdef SCHED_MULTITHREADED
06295    if (schedule_action(__iax2_poke_peer_s, data))
06296 #endif      
06297       __iax2_poke_peer_s(data);
06298    return 0;
06299 }

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

01939 {
01940    struct ast_channel *c;
01941    struct chan_iax2_pvt *pvt = iaxs[callno];
01942 
01943    if (!pvt)
01944       return -1;
01945    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
01946       iax2_destroy_helper(pvt);
01947       ast_set_flag(pvt, IAX_ALREADYGONE); 
01948    }
01949    c = pvt->owner;
01950    if (c) {
01951       c->tech_pvt = NULL;
01952       iax2_queue_hangup(callno);
01953       pvt->owner = NULL;
01954       ast_module_unref(ast_module_info->self);
01955    }
01956    return 0;
01957 }

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

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

Definition at line 8292 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

08293 {
08294    struct iax2_thread *thread = data;
08295    struct timeval tv;
08296    struct timespec ts;
08297    int put_into_idle = 0;
08298 
08299    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
08300    pthread_cleanup_push(iax2_process_thread_cleanup, data);
08301    for(;;) {
08302       /* Wait for something to signal us to be awake */
08303       ast_mutex_lock(&thread->lock);
08304 
08305       /* Flag that we're ready to accept signals */
08306       thread->ready_for_signal = 1;
08307       
08308       /* Put into idle list if applicable */
08309       if (put_into_idle)
08310          insert_idle_thread(thread);
08311 
08312       if (thread->type == IAX_TYPE_DYNAMIC) {
08313          struct iax2_thread *t = NULL;
08314          /* Wait to be signalled or time out */
08315          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08316          ts.tv_sec = tv.tv_sec;
08317          ts.tv_nsec = tv.tv_usec * 1000;
08318          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
08319             /* This thread was never put back into the available dynamic
08320              * thread list, so just go away. */
08321             if (!put_into_idle) {
08322                ast_mutex_unlock(&thread->lock);
08323                break;
08324             }
08325             AST_LIST_LOCK(&dynamic_list);
08326             /* Account for the case where this thread is acquired *right* after a timeout */
08327             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
08328                iaxdynamicthreadcount--;
08329             AST_LIST_UNLOCK(&dynamic_list);
08330             if (t) {
08331                /* This dynamic thread timed out waiting for a task and was
08332                 * not acquired immediately after the timeout, 
08333                 * so it's time to go away. */
08334                ast_mutex_unlock(&thread->lock);
08335                break;
08336             }
08337             /* Someone grabbed our thread *right* after we timed out.
08338              * Wait for them to set us up with something to do and signal
08339              * us to continue. */
08340             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08341             ts.tv_sec = tv.tv_sec;
08342             ts.tv_nsec = tv.tv_usec * 1000;
08343             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
08344             {
08345                ast_mutex_unlock(&thread->lock);
08346                break;
08347             }
08348          }
08349       } else {
08350          ast_cond_wait(&thread->cond, &thread->lock);
08351       }
08352 
08353       /* Go back into our respective list */
08354       put_into_idle = 1;
08355 
08356       ast_mutex_unlock(&thread->lock);
08357 
08358       if (thread->iostate == IAX_IOSTATE_IDLE)
08359          continue;
08360 
08361       /* Add ourselves to the active list now */
08362       AST_LIST_LOCK(&active_list);
08363       AST_LIST_INSERT_HEAD(&active_list, thread, list);
08364       AST_LIST_UNLOCK(&active_list);
08365 
08366       /* See what we need to do */
08367       switch(thread->iostate) {
08368       case IAX_IOSTATE_READY:
08369          thread->actions++;
08370          thread->iostate = IAX_IOSTATE_PROCESSING;
08371          socket_process(thread);
08372          handle_deferred_full_frames(thread);
08373          break;
08374       case IAX_IOSTATE_SCHEDREADY:
08375          thread->actions++;
08376          thread->iostate = IAX_IOSTATE_PROCESSING;
08377 #ifdef SCHED_MULTITHREADED
08378          thread->schedfunc(thread->scheddata);
08379 #endif      
08380          break;
08381       }
08382       time(&thread->checktime);
08383       thread->iostate = IAX_IOSTATE_IDLE;
08384 #ifdef DEBUG_SCHED_MULTITHREAD
08385       thread->curfunc[0]='\0';
08386 #endif      
08387 
08388       /* Now... remove ourselves from the active list, and return to the idle list */
08389       AST_LIST_LOCK(&active_list);
08390       AST_LIST_REMOVE(&active_list, thread, list);
08391       AST_LIST_UNLOCK(&active_list);
08392 
08393       /* Make sure another frame didn't sneak in there after we thought we were done. */
08394       handle_deferred_full_frames(thread);
08395    }
08396 
08397    /*!\note For some reason, idle threads are exiting without being removed
08398     * from an idle list, which is causing memory corruption.  Forcibly remove
08399     * it from the list, if it's there.
08400     */
08401    AST_LIST_LOCK(&idle_list);
08402    AST_LIST_REMOVE(&idle_list, thread, list);
08403    AST_LIST_UNLOCK(&idle_list);
08404 
08405    AST_LIST_LOCK(&dynamic_list);
08406    AST_LIST_REMOVE(&dynamic_list, thread, list);
08407    AST_LIST_UNLOCK(&dynamic_list);
08408 
08409    /* I am exiting here on my own volition, I need to clean up my own data structures
08410    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
08411    */
08412    pthread_cleanup_pop(1);
08413 
08414    return NULL;
08415 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8283 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08284 {
08285    struct iax2_thread *thread = data;
08286    ast_mutex_destroy(&thread->lock);
08287    ast_cond_destroy(&thread->cond);
08288    free(thread);
08289    ast_atomic_dec_and_test(&iaxactivethreadcount);
08290 }

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

Definition at line 8573 of file chan_iax2.c.

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

08574 {
08575    int force = 0;
08576    int res;
08577    if (argc < 4)
08578       return RESULT_SHOWUSAGE;
08579    if ((argc > 4)) {
08580       if (!strcasecmp(argv[4], "forced"))
08581          force = 1;
08582       else
08583          return RESULT_SHOWUSAGE;
08584    }
08585    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08586    if (res < 0)
08587       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08588    else if (res < 1)
08589       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08590    else
08591       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08592    return RESULT_SUCCESS;
08593 }

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

Definition at line 8474 of file chan_iax2.c.

References iax_prov_complete_template().

08475 {
08476    if (pos != 3)
08477       return NULL;
08478    return iax_prov_complete_template(line, word, pos, state);
08479 }

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

Definition at line 8481 of file chan_iax2.c.

References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, iax2_registry::callno, create_addr(), find_callno(), iax2_sched_add(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), iaxs, iaxsl, LOG_DEBUG, NEW_FORCE, option_debug, iax_ie_data::pos, send_command(), and create_addr_info::sockfd.

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

08482 {
08483    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08484       is found for template */
08485    struct iax_ie_data provdata;
08486    struct iax_ie_data ied;
08487    unsigned int sig;
08488    struct sockaddr_in sin;
08489    int callno;
08490    struct create_addr_info cai;
08491 
08492    memset(&cai, 0, sizeof(cai));
08493 
08494    if (option_debug)
08495       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08496 
08497    if (iax_provision_build(&provdata, &sig, template, force)) {
08498       if (option_debug)
08499          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08500       return 0;
08501    }
08502 
08503    if (end) {
08504       memcpy(&sin, end, sizeof(sin));
08505       cai.sockfd = sockfd;
08506    } else if (create_addr(dest, &sin, &cai))
08507       return -1;
08508 
08509    /* Build the rest of the message */
08510    memset(&ied, 0, sizeof(ied));
08511    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08512 
08513    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
08514    if (!callno)
08515       return -1;
08516 
08517    ast_mutex_lock(&iaxsl[callno]);
08518    if (iaxs[callno]) {
08519       /* Schedule autodestruct in case they don't ever give us anything back */
08520       if (iaxs[callno]->autoid > -1)
08521          ast_sched_del(sched, iaxs[callno]->autoid);
08522       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08523       ast_set_flag(iaxs[callno], IAX_PROVISION);
08524       /* Got a call number now, so go ahead and send the provisioning information */
08525       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08526    }
08527    ast_mutex_unlock(&iaxsl[callno]);
08528 
08529    return 1;
08530 }

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

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

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

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

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

Referenced by socket_process().

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

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

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

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

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

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

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

Referenced by iax2_predestroy().

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

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

Definition at line 3298 of file chan_iax2.c.

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

03299 {
03300    if (option_verbose > 3)
03301        ast_log(LOG_NOTICE, "I should never be called!\n");
03302    return &ast_null_frame;
03303 }

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

Definition at line 5770 of file chan_iax2.c.

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

Referenced by set_config().

05771 {
05772    struct iax2_registry *reg;
05773    char copy[256];
05774    char *username, *hostname, *secret;
05775    char *porta;
05776    char *stringp=NULL;
05777    
05778    if (!value)
05779       return -1;
05780    ast_copy_string(copy, value, sizeof(copy));
05781    stringp=copy;
05782    username = strsep(&stringp, "@");
05783    hostname = strsep(&stringp, "@");
05784    if (!hostname) {
05785       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
05786       return -1;
05787    }
05788    stringp=username;
05789    username = strsep(&stringp, ":");
05790    secret = strsep(&stringp, ":");
05791    stringp=hostname;
05792    hostname = strsep(&stringp, ":");
05793    porta = strsep(&stringp, ":");
05794    
05795    if (porta && !atoi(porta)) {
05796       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
05797       return -1;
05798    }
05799    if (!(reg = ast_calloc(1, sizeof(*reg))))
05800       return -1;
05801    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
05802       free(reg);
05803       return -1;
05804    }
05805    ast_copy_string(reg->username, username, sizeof(reg->username));
05806    if (secret)
05807       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
05808    reg->expire = -1;
05809    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
05810    reg->addr.sin_family = AF_INET;
05811    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
05812    AST_LIST_LOCK(&registrations);
05813    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
05814    AST_LIST_UNLOCK(&registrations);
05815    
05816    return 0;
05817 }

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

Definition at line 10004 of file chan_iax2.c.

References reload_config().

10005 {
10006    return reload_config();
10007 }

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

Definition at line 8702 of file chan_iax2.c.

References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_test_flag, ast_translator_best_choice(), iax2_registry::callno, create_addr_info::capability, create_addr(), find_callno(), fmt, create_addr_info::found, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), create_addr_info::maxtime, chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), parsed_dial_string::peer, parsed_dial_string::port, ast_channel::readformat, create_addr_info::sockfd, and ast_channel::writeformat.

08703 {
08704    int callno;
08705    int res;
08706    int fmt, native;
08707    struct sockaddr_in sin;
08708    struct ast_channel *c;
08709    struct parsed_dial_string pds;
08710    struct create_addr_info cai;
08711    char *tmpstr;
08712 
08713    memset(&pds, 0, sizeof(pds));
08714    tmpstr = ast_strdupa(data);
08715    parse_dial_string(tmpstr, &pds);
08716 
08717    memset(&cai, 0, sizeof(cai));
08718    cai.capability = iax2_capability;
08719 
08720    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
08721 
08722    if (!pds.peer) {
08723       ast_log(LOG_WARNING, "No peer given\n");
08724       return NULL;
08725    }
08726           
08727    
08728    /* Populate our address from the given */
08729    if (create_addr(pds.peer, &sin, &cai)) {
08730       *cause = AST_CAUSE_UNREGISTERED;
08731       return NULL;
08732    }
08733 
08734    if (pds.port)
08735       sin.sin_port = htons(atoi(pds.port));
08736 
08737    callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
08738    if (callno < 1) {
08739       ast_log(LOG_WARNING, "Unable to create call\n");
08740       *cause = AST_CAUSE_CONGESTION;
08741       return NULL;
08742    }
08743 
08744    ast_mutex_lock(&iaxsl[callno]);
08745 
08746    /* If this is a trunk, update it now */
08747    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
08748    if (ast_test_flag(&cai, IAX_TRUNK)) {
08749       int new_callno;
08750       if ((new_callno = make_trunk(callno, 1)) != -1)
08751          callno = new_callno;
08752    }
08753    iaxs[callno]->maxtime = cai.maxtime;
08754    if (cai.found)
08755       ast_string_field_set(iaxs[callno], host, pds.peer);
08756 
08757    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
08758 
08759    ast_mutex_unlock(&iaxsl[callno]);
08760 
08761    if (c) {
08762       /* Choose a format we can live with */
08763       if (c->nativeformats & format) 
08764          c->nativeformats &= format;
08765       else {
08766          native = c->nativeformats;
08767          fmt = format;
08768          res = ast_translator_best_choice(&fmt, &native);
08769          if (res < 0) {
08770             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
08771                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
08772             ast_hangup(c);
08773             return NULL;
08774          }
08775          c->nativeformats = native;
08776       }
08777       c->readformat = ast_best_codec(c->nativeformats);
08778       c->writeformat = c->readformat;
08779    }
08780 
08781    return c;
08782 }

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

static int iax2_send ( struct chan_iax2_pvt pvt,
struct ast_frame f,
unsigned int  ts,
int  seqno,
int  now,
int  transfer,
int  final 
) [static]

Definition at line 4110 of file chan_iax2.c.

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

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

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

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

Definition at line 2657 of file chan_iax2.c.

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

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

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

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

Definition at line 2645 of file chan_iax2.c.

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

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

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

Definition at line 3272 of file chan_iax2.c.

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

03273 {
03274    struct ast_option_header *h;
03275    int res;
03276 
03277    switch (option) {
03278    case AST_OPTION_TXGAIN:
03279    case AST_OPTION_RXGAIN:
03280       /* these two cannot be sent, because they require a result */
03281       errno = ENOSYS;
03282       return -1;
03283    default:
03284       if (!(h = ast_malloc(datalen + sizeof(*h))))
03285          return -1;
03286 
03287       h->flag = AST_OPTION_FLAG_REQUEST;
03288       h->option = htons(option);
03289       memcpy(h->data, data, datalen);
03290       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03291                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03292                  datalen + sizeof(*h), -1);
03293       free(h);
03294       return res;
03295    }
03296 }

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

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

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

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

Definition at line 4626 of file chan_iax2.c.

References iax2_registry::addr, 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_MAX_CALLS, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), jb_info::jitter, jb_info::min, chan_iax2_pvt::remote_rr, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_OR.

04627 {
04628 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04629 #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"
04630 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04631    int x;
04632    int numchans = 0;
04633 
04634    if (argc != 3)
04635       return RESULT_SHOWUSAGE;
04636    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04637    for (x=0;x<IAX_MAX_CALLS;x++) {
04638       ast_mutex_lock(&iaxsl[x]);
04639       if (iaxs[x]) {
04640          int lag, jitter, localdelay;
04641          jb_info jbinfo;
04642          
04643          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04644             jb_getinfo(iaxs[x]->jb, &jbinfo);
04645             jitter = jbinfo.jitter;
04646             localdelay = jbinfo.current - jbinfo.min;
04647          } else {
04648             jitter = -1;
04649             localdelay = 0;
04650          }
04651          lag = iaxs[x]->remote_rr.delay;
04652          ast_cli(fd, FORMAT,
04653             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04654             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04655             S_OR(iaxs[x]->username, "(None)"),
04656             iaxs[x]->callno, iaxs[x]->peercallno,
04657             iaxs[x]->oseqno, iaxs[x]->iseqno,
04658             lag,
04659             jitter,
04660             localdelay,
04661             ast_getformatname(iaxs[x]->voiceformat) );
04662          numchans++;
04663       }
04664       ast_mutex_unlock(&iaxsl[x]);
04665    }
04666    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04667    return RESULT_SUCCESS;
04668 #undef FORMAT
04669 #undef FORMAT2
04670 #undef FORMATB
04671 }

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

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

04538 {
04539 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04540 #if !defined(__FreeBSD__)
04541 #define FORMAT "%-15.15s  %-15d %-15d\n"
04542 #else /* __FreeBSD__ */
04543 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04544 #endif /* __FreeBSD__ */
04545    struct iax_firmware *cur;
04546    if ((argc != 3) && (argc != 4))
04547       return RESULT_SHOWUSAGE;
04548    ast_mutex_lock(&waresl.lock);
04549    
04550    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04551    for (cur = waresl.wares;cur;cur = cur->next) {
04552       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04553          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04554             (int)ntohl(cur->fwh->datalen));
04555    }
04556    ast_mutex_unlock(&waresl.lock);
04557    return RESULT_SUCCESS;
04558 #undef FORMAT
04559 #undef FORMAT2
04560 }

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

Definition at line 4749 of file chan_iax2.c.

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

04750 {
04751    int numchans = 0;
04752    if (argc != 3)
04753       return RESULT_SHOWUSAGE;
04754    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04755    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04756    numchans = ast_cli_netstats(NULL, fd, 1);
04757    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04758    return RESULT_SUCCESS;
04759 }

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

Show one peer in detail.

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

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

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

Definition at line 4526 of file chan_iax2.c.

References __iax2_show_peers().

04527 {
04528    return __iax2_show_peers(0, fd, NULL, argc, argv);
04529 }

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

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

04599 {
04600 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04601 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04602    struct iax2_registry *reg = NULL;
04603 
04604    char host[80];
04605    char perceived[80];
04606    if (argc != 3)
04607       return RESULT_SHOWUSAGE;
04608    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04609    AST_LIST_LOCK(&registrations);
04610    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04611       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04612       if (reg->us.sin_addr.s_addr) 
04613          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04614       else
04615          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04616       ast_cli(fd, FORMAT, host, 
04617                (reg->dnsmgr) ? "Y" : "N", 
04618                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04619    }
04620    AST_LIST_UNLOCK(&registrations);
04621    return RESULT_SUCCESS;
04622 #undef FORMAT
04623 #undef FORMAT2
04624 }

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

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

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

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

Definition at line 4467 of file chan_iax2.c.

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

04468 {
04469    struct iax2_thread *thread = NULL;
04470    time_t t;
04471    int threadcount = 0, dynamiccount = 0;
04472    char type;
04473 
04474    if (argc != 3)
04475       return RESULT_SHOWUSAGE;
04476       
04477    ast_cli(fd, "IAX2 Thread Information\n");
04478    time(&t);
04479    ast_cli(fd, "Idle Threads:\n");
04480    AST_LIST_LOCK(&idle_list);
04481    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04482 #ifdef DEBUG_SCHED_MULTITHREAD
04483       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04484          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04485 #else
04486       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04487          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04488 #endif
04489       threadcount++;
04490    }
04491    AST_LIST_UNLOCK(&idle_list);
04492    ast_cli(fd, "Active Threads:\n");
04493    AST_LIST_LOCK(&active_list);
04494    AST_LIST_TRAVERSE(&active_list, thread, list) {
04495       if (thread->type == IAX_TYPE_DYNAMIC)
04496          type = 'D';
04497       else
04498          type = 'P';
04499 #ifdef DEBUG_SCHED_MULTITHREAD
04500       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04501          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04502 #else
04503       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04504          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04505 #endif
04506       threadcount++;
04507    }
04508    AST_LIST_UNLOCK(&active_list);
04509    ast_cli(fd, "Dynamic Threads:\n");
04510         AST_LIST_LOCK(&dynamic_list);
04511         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04512 #ifdef DEBUG_SCHED_MULTITHREAD
04513                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04514                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04515 #else
04516                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04517                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04518 #endif
04519       dynamiccount++;
04520         }
04521         AST_LIST_UNLOCK(&dynamic_list);
04522    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04523    return RESULT_SUCCESS;
04524 }

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

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

04285 {
04286    regex_t regexbuf;
04287    int havepattern = 0;
04288 
04289 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04290 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04291 
04292    struct iax2_user *user = NULL;
04293    char auth[90];
04294    char *pstr = "";
04295    struct ao2_iterator i;
04296 
04297    switch (argc) {
04298    case 5:
04299       if (!strcasecmp(argv[3], "like")) {
04300          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04301             return RESULT_SHOWUSAGE;
04302          havepattern = 1;
04303       } else
04304          return RESULT_SHOWUSAGE;
04305    case 3:
04306       break;
04307    default:
04308       return RESULT_SHOWUSAGE;
04309    }
04310 
04311    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04312    i = ao2_iterator_init(users, 0);
04313    for (user = ao2_iterator_next(&i); user; 
04314       user_unref(user), user = ao2_iterator_next(&i)) {
04315       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04316          continue;
04317       
04318       if (!ast_strlen_zero(user->secret)) {
04319          ast_copy_string(auth,user->secret,sizeof(auth));
04320       } else if (!ast_strlen_zero(user->inkeys)) {
04321          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04322       } else
04323          ast_copy_string(auth, "-no secret-", sizeof(auth));
04324       
04325       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04326          pstr = "REQ Only";
04327       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04328          pstr = "Disabled";
04329       else
04330          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04331       
04332       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04333          user->contexts ? user->contexts->context : context,
04334          user->ha ? "Yes" : "No", pstr);
04335    }
04336 
04337    if (havepattern)
04338       regfree(&regexbuf);
04339 
04340    return RESULT_SUCCESS;
04341 #undef FORMAT
04342 #undef FORMAT2
04343 }

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

Definition at line 3305 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03306 {
03307    int res;
03308    struct iax_ie_data ied0;
03309    struct iax_ie_data ied1;
03310    unsigned int transferid = (unsigned int)ast_random();
03311    memset(&ied0, 0, sizeof(ied0));
03312    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03313    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03314    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03315 
03316    memset(&ied1, 0, sizeof(ied1));
03317    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03318    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03319    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03320    
03321    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03322    if (res)
03323       return -1;
03324    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03325    if (res)
03326       return -1;
03327    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03328    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03329    return 0;
03330 }

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

Definition at line 2157 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02158 {
02159        if (argc != 4)
02160                return RESULT_SHOWUSAGE;
02161 
02162        test_losspct = atoi(argv[3]);
02163 
02164        return RESULT_SUCCESS;
02165 }

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

Definition at line 3540 of file chan_iax2.c.

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

03541 {
03542    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03543    struct iax_ie_data ied;
03544    char tmp[256], *context;
03545    ast_copy_string(tmp, dest, sizeof(tmp));
03546    context = strchr(tmp, '@');
03547    if (context) {
03548       *context = '\0';
03549       context++;
03550    }
03551    memset(&ied, 0, sizeof(ied));
03552    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03553    if (context)
03554       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03555    if (option_debug)
03556       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03557    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03558 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

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

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

Definition at line 6345 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06346 {
06347    /* Drop when trunk is about 5 seconds idle */
06348    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06349       return 1;
06350    return 0;
06351 }

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

Definition at line 3884 of file chan_iax2.c.

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

Referenced by iax2_send().

03885 {
03886    struct ast_frame *f;
03887    struct iax2_trunk_peer *tpeer;
03888    void *tmp, *ptr;
03889    struct ast_iax2_meta_trunk_entry *met;
03890    struct ast_iax2_meta_trunk_mini *mtm;
03891 
03892    f = &fr->af;
03893    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
03894    if (tpeer) {
03895       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
03896          /* Need to reallocate space */
03897          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
03898             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
03899                ast_mutex_unlock(&tpeer->lock);
03900                return -1;
03901             }
03902             
03903             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
03904             tpeer->trunkdata = tmp;
03905             if (option_debug)
03906                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);
03907          } else {
03908             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));
03909             ast_mutex_unlock(&tpeer->lock);
03910             return -1;
03911          }
03912       }
03913 
03914       /* Append to meta frame */
03915       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
03916       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
03917          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
03918          mtm->len = htons(f->datalen);
03919          mtm->mini.callno = htons(pvt->callno);
03920          mtm->mini.ts = htons(0xffff & fr->ts);
03921          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
03922          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
03923       } else {
03924          met = (struct ast_iax2_meta_trunk_entry *)ptr;
03925          /* Store call number and length in meta header */
03926          met->callno = htons(pvt->callno);
03927          met->len = htons(f->datalen);
03928          /* Advance pointers/decrease length past trunk entry header */
03929          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
03930          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
03931       }
03932       /* Copy actual trunk data */
03933       memcpy(ptr, f->data, f->datalen);
03934       tpeer->trunkdatalen += f->datalen;
03935 
03936       tpeer->calls++;
03937       ast_mutex_unlock(&tpeer->lock);
03938    }
03939    return 0;
03940 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6262 of file chan_iax2.c.

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

Referenced by socket_process().

06263 {
06264    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06265 }

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

Definition at line 4816 of file chan_iax2.c.

References AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, errno, error(), ast_frame::frametype, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, LOG_DEBUG, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.

04817 {
04818    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04819    int res = -1;
04820    ast_mutex_lock(&iaxsl[callno]);
04821    if (iaxs[callno]) {
04822    /* If there's an outstanding error, return failure now */
04823       if (!iaxs[callno]->error) {
04824          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
04825             res = 0;
04826             /* Don't waste bandwidth sending null frames */
04827          else if (f->frametype == AST_FRAME_NULL)
04828             res = 0;
04829          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
04830             res = 0;
04831          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
04832             res = 0;
04833          else
04834          /* Simple, just queue for transmission */
04835             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
04836       } else {
04837          if (option_debug)
04838             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
04839       }
04840    }
04841    /* If it's already gone, just return */
04842    ast_mutex_unlock(&iaxsl[callno]);
04843    return res;
04844 }

static int iax_check_version ( char *  dev  )  [static]

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

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

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

Definition at line 766 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 772 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

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

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

Definition at line 6528 of file chan_iax2.c.

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

Referenced by socket_process().

06529 {
06530    struct iax_dual *d;
06531    struct ast_channel *chan1m, *chan2m;
06532    pthread_t th;
06533    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06534    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06535    if (chan2m && chan1m) {
06536       /* Make formats okay */
06537       chan1m->readformat = chan1->readformat;
06538       chan1m->writeformat = chan1->writeformat;
06539       ast_channel_masquerade(chan1m, chan1);
06540       /* Setup the extensions and such */
06541       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06542       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06543       chan1m->priority = chan1->priority;
06544       
06545       /* We make a clone of the peer channel too, so we can play
06546          back the announcement */
06547       /* Make formats okay */
06548       chan2m->readformat = chan2->readformat;
06549       chan2m->writeformat = chan2->writeformat;
06550       ast_channel_masquerade(chan2m, chan2);
06551       /* Setup the extensions and such */
06552       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06553       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06554       chan2m->priority = chan2->priority;
06555       if (ast_do_masquerade(chan2m)) {
06556          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06557          ast_hangup(chan2m);
06558          return -1;
06559       }
06560    } else {
06561       if (chan1m)
06562          ast_hangup(chan1m);
06563       if (chan2m)
06564          ast_hangup(chan2m);
06565       return -1;
06566    }
06567    if ((d = ast_calloc(1, sizeof(*d)))) {
06568       pthread_attr_t attr;
06569 
06570       pthread_attr_init(&attr);
06571       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06572 
06573       d->chan1 = chan1m;
06574       d->chan2 = chan2m;
06575       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06576          pthread_attr_destroy(&attr);
06577          return 0;
06578       }
06579       pthread_attr_destroy(&attr);
06580       free(d);
06581    }
06582    return -1;
06583 }

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

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

06509 {
06510    struct ast_channel *chan1, *chan2;
06511    struct iax_dual *d;
06512    struct ast_frame *f;
06513    int ext;
06514    int res;
06515    d = stuff;
06516    chan1 = d->chan1;
06517    chan2 = d->chan2;
06518    free(d);
06519    f = ast_read(chan1);
06520    if (f)
06521       ast_frfree(f);
06522    res = ast_park_call(chan1, chan2, 0, &ext);
06523    ast_hangup(chan2);
06524    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06525    return NULL;
06526 }

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

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

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

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 878 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, and IAX_TYPE_DYNAMIC.

Referenced by iax2_process_thread().

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

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

Definition at line 801 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 777 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 789 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 10811 of file chan_iax2.c.

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

10812 {
10813    char *config = "iax.conf";
10814    int res = 0;
10815    int x;
10816    struct iax2_registry *reg = NULL;
10817 
10818    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
10819    if (!peers)
10820       return AST_MODULE_LOAD_FAILURE;
10821    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
10822    if (!users) {
10823       ao2_ref(peers, -1);
10824       return AST_MODULE_LOAD_FAILURE;
10825    }
10826 
10827    ast_custom_function_register(&iaxpeer_function);
10828 
10829    iax_set_output(iax_debug_output);
10830    iax_set_error(iax_error_output);
10831    jb_setoutput(jb_error_output, jb_warning_output, NULL);
10832    
10833 #ifdef HAVE_ZAPTEL
10834 #ifdef ZT_TIMERACK
10835    timingfd = open("/dev/zap/timer", O_RDWR);
10836    if (timingfd < 0)
10837 #endif
10838       timingfd = open("/dev/zap/pseudo", O_RDWR);
10839    if (timingfd < 0) 
10840       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
10841 #endif      
10842 
10843    memset(iaxs, 0, sizeof(iaxs));
10844 
10845    for (x=0;x<IAX_MAX_CALLS;x++)
10846       ast_mutex_init(&iaxsl[x]);
10847    
10848    ast_cond_init(&sched_cond, NULL);
10849 
10850    io = io_context_create();
10851    sched = sched_context_create();
10852    
10853    if (!io || !sched) {
10854       ast_log(LOG_ERROR, "Out of memory\n");
10855       return -1;
10856    }
10857 
10858    netsock = ast_netsock_list_alloc();
10859    if (!netsock) {
10860       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
10861       return -1;
10862    }
10863    ast_netsock_init(netsock);
10864 
10865    outsock = ast_netsock_list_alloc();
10866    if (!outsock) {
10867       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10868       return -1;
10869    }
10870    ast_netsock_init(outsock);
10871 
10872    ast_mutex_init(&waresl.lock);
10873 
10874    AST_LIST_HEAD_INIT(&iaxq.queue);
10875    
10876    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
10877 
10878    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
10879    
10880    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
10881    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
10882 
10883    if(set_config(config, 0) == -1)
10884       return AST_MODULE_LOAD_DECLINE;
10885 
10886    if (ast_channel_register(&iax2_tech)) {
10887       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
10888       __unload_module();
10889       return -1;
10890    }
10891 
10892    if (ast_register_switch(&iax2_switch)) 
10893       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
10894 
10895    res = start_network_thread();
10896    if (!res) {
10897       if (option_verbose > 1) 
10898          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
10899    } else {
10900       ast_log(LOG_ERROR, "Unable to start network thread\n");
10901       ast_netsock_release(netsock);
10902       ast_netsock_release(outsock);
10903    }
10904 
10905    AST_LIST_LOCK(&registrations);
10906    AST_LIST_TRAVERSE(&registrations, reg, entry)
10907       iax2_do_register(reg);
10908    AST_LIST_UNLOCK(&registrations); 
10909 
10910    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
10911    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
10912 
10913    reload_firmware(0);
10914    iax_provision_reload();
10915    return res;
10916 }

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

Definition at line 3332 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03333 {
03334    ast_mutex_lock(&iaxsl[callno0]);
03335    while (ast_mutex_trylock(&iaxsl[callno1])) {
03336       ast_mutex_unlock(&iaxsl[callno0]);
03337       usleep(10);
03338       ast_mutex_lock(&iaxsl[callno0]);
03339    }
03340 }

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

Definition at line 1291 of file chan_iax2.c.

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

Referenced by iax2_request(), and socket_process().

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

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

Definition at line 4530 of file chan_iax2.c.

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

Referenced by load_module().

04531 {
04532    ast_cli_netstats(s, -1, 0);
04533    astman_append(s, "\r\n");
04534    return RESULT_SUCCESS;
04535 }

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

Definition at line 4563 of file chan_iax2.c.

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

Referenced by load_module().

04564 {
04565    char *a[] = { "iax2", "show", "users" };
04566    int ret;
04567    const char *id = astman_get_header(m,"ActionID");
04568 
04569    if (!ast_strlen_zero(id))
04570       astman_append(s, "ActionID: %s\r\n",id);
04571    ret = __iax2_show_peers(1, -1, s, 3, a );
04572    astman_append(s, "\r\n\r\n" );
04573    return ret;
04574 } /* /JDG */

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

Definition at line 1243 of file chan_iax2.c.

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

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

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

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

Definition at line 3948 of file chan_iax2.c.

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

Referenced by decode_frame().

03949 {
03950 #if 0
03951    /* Debug with "fake encryption" */
03952    int x;
03953    if (len % 16)
03954       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
03955    for (x=0;x<len;x++)
03956       dst[x] = src[x] ^ 0xff;
03957 #else 
03958    unsigned char lastblock[16] = { 0 };
03959    int x;
03960    while(len > 0) {
03961       aes_decrypt(src, dst, dcx);
03962       for (x=0;x<16;x++)
03963          dst[x] ^= lastblock[x];
03964       memcpy(lastblock, src, sizeof(lastblock));
03965       dst += 16;
03966       src += 16;
03967       len -= 16;
03968    }
03969 #endif
03970 }

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

Definition at line 3972 of file chan_iax2.c.

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

Referenced by encrypt_frame().

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

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

Definition at line 5141 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05142 {
05143    /* Select exactly one common encryption if there are any */
05144    p->encmethods &= enc;
05145    if (p->encmethods) {
05146       if (p->encmethods & IAX_ENCRYPT_AES128)
05147          p->encmethods = IAX_ENCRYPT_AES128;
05148       else
05149          p->encmethods = 0;
05150    }
05151 }

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

Definition at line 8812 of file chan_iax2.c.

References ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, f, iax2_sched_add(), iax_frame_free(), iaxq, iaxs, iaxsl, LOG_DEBUG, option_debug, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_packet(), iax_frame::sentyet, and timing_read().

Referenced by start_network_thread().

08813 {
08814    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
08815       from the network, and queue them for delivery to the channels */
08816    int res, count, wakeup;
08817    struct iax_frame *f;
08818 
08819    if (timingfd > -1)
08820       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
08821    
08822    for(;;) {
08823       pthread_testcancel();
08824 
08825       /* Go through the queue, sending messages which have not yet been
08826          sent, and scheduling retransmissions if appropriate */
08827       AST_LIST_LOCK(&iaxq.queue);
08828       count = 0;
08829       wakeup = -1;
08830       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
08831          if (f->sentyet)
08832             continue;
08833          
08834          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
08835          if (ast_mutex_trylock(&iaxsl[f->callno])) {
08836             wakeup = 1;
08837             continue;
08838          }
08839 
08840          f->sentyet++;
08841 
08842          if (iaxs[f->callno]) {
08843             send_packet(f);
08844             count++;
08845          } 
08846 
08847          ast_mutex_unlock(&iaxsl[f->callno]);
08848 
08849          if (f->retries < 0) {
08850             /* This is not supposed to be retransmitted */
08851             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
08852             iaxq.count--;
08853             /* Free the iax frame */
08854             iax_frame_free(f);
08855          } else {
08856             /* We need reliable delivery.  Schedule a retransmission */
08857             f->retries++;
08858             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
08859          }
08860       }
08861       AST_LIST_TRAVERSE_SAFE_END
08862       AST_LIST_UNLOCK(&iaxq.queue);
08863 
08864       pthread_testcancel();
08865 
08866       if (option_debug && count >= 20)
08867          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
08868 
08869       /* Now do the IO, and run scheduled tasks */
08870       res = ast_io_wait(io, wakeup);
08871       if (res >= 0) {
08872          if (option_debug && res >= 20)
08873             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
08874       }
08875    }
08876    return NULL;
08877 }

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

Definition at line 1185 of file chan_iax2.c.

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

Referenced by find_callno().

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

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

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

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

Referenced by load_module().

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

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

Definition at line 9512 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09513 {
09514    struct iax2_peer *peer = obj;
09515 
09516    ast_set_flag(peer, IAX_DELME);
09517 
09518    return 0;
09519 }

static void peer_destructor ( void *  obj  )  [static]

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

09036 {
09037    struct iax2_peer *peer = obj;
09038 
09039    ast_free_ha(peer->ha);
09040 
09041    if (peer->callno > 0) {
09042       ast_mutex_lock(&iaxsl[peer->callno]);
09043       iax2_destroy(peer->callno);
09044       ast_mutex_unlock(&iaxsl[peer->callno]);
09045    }
09046 
09047    register_peer_exten(peer, 0);
09048 
09049    if (peer->dnsmgr)
09050       ast_dnsmgr_release(peer->dnsmgr);
09051 
09052    ast_string_field_free_memory(peer);
09053 }

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

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1131 of file chan_iax2.c.

References ao2_ref().

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

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

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

Definition at line 10800 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

10801 {
10802    struct iax2_peer *peer = obj;
10803 
10804    if (peer->sockfd < 0)
10805       peer->sockfd = defaultsockfd;
10806 
10807    return 0;
10808 }

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

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

Referenced by build_peer().

08963 {
08964    struct sockaddr_in sin;
08965    int nonlocal = 1;
08966    int port = IAX_DEFAULT_PORTNO;
08967    int sockfd = defaultsockfd;
08968    char *tmp;
08969    char *addr;
08970    char *portstr;
08971 
08972    if (!(tmp = ast_strdupa(srcaddr)))
08973       return -1;
08974 
08975    addr = strsep(&tmp, ":");
08976    portstr = tmp;
08977 
08978    if (portstr) {
08979       port = atoi(portstr);
08980       if (port < 1)
08981          port = IAX_DEFAULT_PORTNO;
08982    }
08983    
08984    if (!ast_get_ip(&sin, addr)) {
08985       struct ast_netsock *sock;
08986       int res;
08987 
08988       sin.sin_port = 0;
08989       sin.sin_family = AF_INET;
08990       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
08991       if (res == 0) {
08992          /* ip address valid. */
08993          sin.sin_port = htons(port);
08994          if (!(sock = ast_netsock_find(netsock, &sin)))
08995             sock = ast_netsock_find(outsock, &sin);
08996          if (sock) {
08997             sockfd = ast_netsock_sockfd(sock);
08998             nonlocal = 0;
08999          } else {
09000             unsigned int orig_saddr = sin.sin_addr.s_addr;
09001             /* INADDR_ANY matches anyway! */
09002             sin.sin_addr.s_addr = INADDR_ANY;
09003             if (ast_netsock_find(netsock, &sin)) {
09004                sin.sin_addr.s_addr = orig_saddr;
09005                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09006                if (sock) {
09007                   sockfd = ast_netsock_sockfd(sock);
09008                   ast_netsock_unref(sock);
09009                   nonlocal = 0;
09010                } else {
09011                   nonlocal = 2;
09012                }
09013             }
09014          }
09015       }
09016    }
09017       
09018    peer->sockfd = sockfd;
09019 
09020    if (nonlocal == 1) {
09021       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09022          srcaddr, peer->name);
09023       return -1;
09024         } else if (nonlocal == 2) {
09025       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09026          srcaddr, peer->name);
09027          return -1;
09028    } else {
09029       if (option_debug)
09030          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09031       return 0;
09032    }
09033 }

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

peer_status: Report Peer status in character string

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

02204 {
02205    int res = 0;
02206    if (peer->maxms) {
02207       if (peer->lastms < 0) {
02208          ast_copy_string(status, "UNREACHABLE", statuslen);
02209       } else if (peer->lastms > peer->maxms) {
02210          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02211          res = 1;
02212       } else if (peer->lastms) {
02213          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02214          res = 1;
02215       } else {
02216          ast_copy_string(status, "UNKNOWN", statuslen);
02217       }
02218    } else { 
02219       ast_copy_string(status, "Unmonitored", statuslen);
02220       res = -1;
02221    }
02222    return res;
02223 }

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

static void poke_all_peers ( void   )  [static]

Definition at line 9972 of file chan_iax2.c.

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

Referenced by reload_config().

09973 {
09974    struct ao2_iterator i;
09975    struct iax2_peer *peer;
09976 
09977    i = ao2_iterator_init(peers, 0);
09978    while ((peer = ao2_iterator_next(&i))) {
09979       iax2_poke_peer(peer, 0);
09980       peer_unref(peer);
09981    }
09982 }

static void prune_peers ( void   )  [static]

Definition at line 9571 of file chan_iax2.c.

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

09572 {
09573    struct iax2_peer *peer;
09574    struct ao2_iterator i;
09575 
09576    i = ao2_iterator_init(peers, 0);
09577    while ((peer = ao2_iterator_next(&i))) {
09578       if (ast_test_flag(peer, IAX_DELME))
09579          unlink_peer(peer);
09580       peer_unref(peer);
09581    }
09582 }

static void prune_users ( void   )  [static]

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

09558 {
09559    struct iax2_user *user;
09560    struct ao2_iterator i;
09561 
09562    i = ao2_iterator_init(users, 0);
09563    while ((user = ao2_iterator_next(&i))) {
09564       if (ast_test_flag(user, IAX_DELME))
09565          ao2_unlink(users, user);
09566       user_unref(user);
09567    }
09568 }

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

Definition at line 5123 of file chan_iax2.c.

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

Referenced by socket_process().

05124 {
05125    struct ast_iax2_full_hdr fh;
05126    fh.scallno = htons(src | IAX_FLAG_FULL);
05127    fh.dcallno = htons(dst);
05128    fh.ts = 0;
05129    fh.oseqno = 0;
05130    fh.iseqno = 0;
05131    fh.type = AST_FRAME_IAX;
05132    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05133    if (iaxdebug)
05134        iax_showframe(NULL, &fh, 0, sin, 0);
05135    if (option_debug)
05136       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05137          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05138    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05139 }

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

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

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

Definition at line 2678 of file chan_iax2.c.

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

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

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

Definition at line 2871 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

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

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

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

Definition at line 2800 of file chan_iax2.c.

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

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

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 5899 of file chan_iax2.c.

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

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

05900 {
05901    char data[80];
05902    struct in_addr in;
05903    char *c, *d;
05904    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
05905       c = strchr(data, ':');
05906       if (c) {
05907          *c = '\0';
05908          c++;
05909          if (inet_aton(data, &in)) {
05910             d = strchr(c, ':');
05911             if (d) {
05912                *d = '\0';
05913                d++;
05914                if (option_verbose > 2)
05915                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
05916                   ast_inet_ntoa(in), atoi(c), atoi(d));
05917                iax2_poke_peer(p, 0);
05918                p->expiry = atoi(d);
05919                memset(&p->addr, 0, sizeof(p->addr));
05920                p->addr.sin_family = AF_INET;
05921                p->addr.sin_addr = in;
05922                p->addr.sin_port = htons(atoi(c));
05923                if (p->expire > -1) {
05924                   if (!ast_sched_del(sched, p->expire)) {
05925                      p->expire = -1;
05926                      peer_unref(p);
05927                   }
05928                }
05929                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05930                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
05931                if (p->expire == -1)
05932                   peer_unref(p);
05933                if (iax2_regfunk)
05934                   iax2_regfunk(p->name, 1);
05935                register_peer_exten(p, 1);
05936             }              
05937                
05938          }
05939       }
05940    }
05941 }

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

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

05820 {
05821    char multi[256];
05822    char *stringp, *ext;
05823    if (!ast_strlen_zero(regcontext)) {
05824       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
05825       stringp = multi;
05826       while((ext = strsep(&stringp, "&"))) {
05827          if (onoff) {
05828             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
05829                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
05830                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
05831          } else
05832             ast_context_remove_extension(regcontext, ext, 1, NULL);
05833       }
05834    }
05835 }

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

Verify inbound registration.

Definition at line 5287 of file chan_iax2.c.

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

Referenced by handle_request_register(), and socket_process().

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

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6078 of file chan_iax2.c.

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

Referenced by socket_process().

06079 {
06080    struct iax_ie_data ied;
06081    struct iax2_peer *p;
06082    char challenge[10];
06083    const char *peer_name;
06084    int res = -1;
06085 
06086    peer_name = ast_strdupa(iaxs[callno]->peer);
06087 
06088    /* SLD: third call to find_peer in registration */
06089    ast_mutex_unlock(&iaxsl[callno]);
06090    p = find_peer(peer_name, 1);
06091    ast_mutex_lock(&iaxsl[callno]);
06092    if (!iaxs[callno])
06093       goto return_unref;
06094    if (!p) {
06095       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06096       goto return_unref;
06097    }
06098    
06099    memset(&ied, 0, sizeof(ied));
06100    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06101    if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06102       /* Build the challenge */
06103       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06104       ast_string_field_set(iaxs[callno], challenge, challenge);
06105       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06106    }
06107    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06108 
06109    res = 0;
06110 
06111 return_unref:
06112    peer_unref(p);
06113 
06114    return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
06115 }

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

Definition at line 6117 of file chan_iax2.c.

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

Referenced by socket_process().

06118 {
06119    struct iax2_registry *reg;
06120    /* Start pessimistic */
06121    struct iax_ie_data ied;
06122    char peer[256] = "";
06123    char challenge[256] = "";
06124    int res;
06125    int authmethods = 0;
06126    if (ies->authmethods)
06127       authmethods = ies->authmethods;
06128    if (ies->username)
06129       ast_copy_string(peer, ies->username, sizeof(peer));
06130    if (ies->challenge)
06131       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06132    memset(&ied, 0, sizeof(ied));
06133    reg = iaxs[callno]->reg;
06134    if (reg) {
06135          if (inaddrcmp(&reg->addr, sin)) {
06136             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06137             return -1;
06138          }
06139          if (ast_strlen_zero(reg->secret)) {
06140             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06141             reg->regstate = REG_STATE_NOAUTH;
06142             return -1;
06143          }
06144          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06145          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06146          if (reg->secret[0] == '[') {
06147             char tmpkey[256];
06148             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06149             tmpkey[strlen(tmpkey) - 1] = '\0';
06150             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
06151          } else
06152             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
06153          if (!res) {
06154             reg->regstate = REG_STATE_AUTHSENT;
06155             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06156          } else
06157             return -1;
06158          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06159    } else   
06160       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06161    return -1;
06162 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4576 of file chan_iax2.c.

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

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

04577 {
04578    switch(regstate) {
04579    case REG_STATE_UNREGISTERED:
04580       return "Unregistered";
04581    case REG_STATE_REGSENT:
04582       return "Request Sent";
04583    case REG_STATE_AUTHSENT:
04584       return "Auth. Sent";
04585    case REG_STATE_REGISTERED:
04586       return "Registered";
04587    case REG_STATE_REJECTED:
04588       return "Rejected";
04589    case REG_STATE_TIMEOUT:
04590       return "Timeout";
04591    case REG_STATE_NOAUTH:
04592       return "No Authentication";
04593    default:
04594       return "Unknown";
04595    }
04596 }

static int reload ( void   )  [static]

Definition at line 10009 of file chan_iax2.c.

References reload_config().

10010 {
10011    return reload_config();
10012 }

static int reload_config ( void   )  [static]

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

09984 {
09985    char *config = "iax.conf";
09986    struct iax2_registry *reg;
09987 
09988    if (set_config(config, 1) > 0) {
09989       prune_peers();
09990       prune_users();
09991       AST_LIST_LOCK(&registrations);
09992       AST_LIST_TRAVERSE(&registrations, reg, entry)
09993          iax2_do_register(reg);
09994       AST_LIST_UNLOCK(&registrations);
09995       /* Qualify hosts, too */
09996       poke_all_peers();
09997    }
09998    reload_firmware(0);
09999    iax_provision_reload();
10000 
10001    return 0;
10002 }

static void reload_firmware ( int  unload  )  [static]

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

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

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

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

Definition at line 8784 of file chan_iax2.c.

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

Referenced by start_network_thread().

08785 {
08786    int count;
08787    int res;
08788    struct timeval tv;
08789    struct timespec ts;
08790 
08791    for (;;) {
08792       res = ast_sched_wait(sched);
08793       if ((res > 1000) || (res < 0))
08794          res = 1000;
08795       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
08796       ts.tv_sec = tv.tv_sec;
08797       ts.tv_nsec = tv.tv_usec * 1000;
08798 
08799       pthread_testcancel();
08800       ast_mutex_lock(&sched_lock);
08801       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
08802       ast_mutex_unlock(&sched_lock);
08803       pthread_testcancel();
08804 
08805       count = ast_sched_runq(sched);
08806       if (option_debug && count >= 20)
08807          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
08808    }
08809    return NULL;
08810 }

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

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

Referenced by socket_process().

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

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

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

Note:
Since this function calls iax2_predestroy() -> iax2_queue_hangup(), the pvt struct for the given call number may disappear during its execution.

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

04880 {
04881    int call_num = i->callno;
04882    /* It is assumed that the callno has already been locked */
04883    iax2_predestroy(i->callno);
04884    if (!iaxs[call_num])
04885       return -1;
04886    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
04887 }

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

Definition at line 4889 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

04890 {
04891    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
04892 }

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

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

04866 {
04867    int res;
04868    ast_mutex_lock(&iaxsl[callno]);
04869    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
04870    ast_mutex_unlock(&iaxsl[callno]);
04871    return res;
04872 }

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

Definition at line 4894 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

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

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

Definition at line 1028 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

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

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 1864 of file chan_iax2.c.

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

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

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

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

Definition at line 993 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

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

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

Definition at line 6301 of file chan_iax2.c.

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

Referenced by timing_read().

06302 {
06303    int res = 0;
06304    struct iax_frame *fr;
06305    struct ast_iax2_meta_hdr *meta;
06306    struct ast_iax2_meta_trunk_hdr *mth;
06307    int calls = 0;
06308    
06309    /* Point to frame */
06310    fr = (struct iax_frame *)tpeer->trunkdata;
06311    /* Point to meta data */
06312    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06313    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06314    if (tpeer->trunkdatalen) {
06315       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06316       meta->zeros = 0;
06317       meta->metacmd = IAX_META_TRUNK;
06318       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06319          meta->cmddata = IAX_META_TRUNK_MINI;
06320       else
06321          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06322       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06323       /* And the rest of the ast_iax2 header */
06324       fr->direction = DIRECTION_OUTGRESS;
06325       fr->retrans = -1;
06326       fr->transfer = 0;
06327       /* Any appropriate call will do */
06328       fr->data = fr->afdata;
06329       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06330       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06331       calls = tpeer->calls;
06332 #if 0
06333       if (option_debug)
06334          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));
06335 #endif      
06336       /* Reset transmit trunk side data */
06337       tpeer->trunkdatalen = 0;
06338       tpeer->calls = 0;
06339    }
06340    if (res < 0)
06341       return res;
06342    return calls;
06343 }

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

Load configuration.

Definition at line 9615 of file chan_iax2.c.

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

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

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

static void set_config_destroy ( void   )  [static]

Definition at line 9599 of file chan_iax2.c.

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

Referenced by set_config().

09600 {
09601    strcpy(accountcode, "");
09602    strcpy(language, "");
09603    strcpy(mohinterpret, "default");
09604    strcpy(mohsuggest, "");
09605    amaflags = 0;
09606    delayreject = 0;
09607    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09608    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09609    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09610    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09611    delete_users();
09612 }

static void set_timing ( void   )  [static]

Definition at line 9584 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09585 {
09586 #ifdef HAVE_ZAPTEL
09587    int bs = trunkfreq * 8;
09588    if (timingfd > -1) {
09589       if (
09590 #ifdef ZT_TIMERACK
09591          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09592 #endif         
09593          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09594          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09595    }
09596 #endif
09597 }

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

Definition at line 759 of file chan_iax2.c.

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

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

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

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6770 of file chan_iax2.c.

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

Referenced by handle_deferred_full_frames(), and iax2_process_thread().

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

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

Definition at line 6692 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_registry::callno, ast_iax2_full_hdr::csub, defer_full_frame(), errno, iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), len, LOG_NOTICE, LOG_WARNING, 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().

06693 {
06694    struct iax2_thread *thread;
06695    socklen_t len;
06696    time_t t;
06697    static time_t last_errtime = 0;
06698    struct ast_iax2_full_hdr *fh;
06699 
06700    if (!(thread = find_idle_thread())) {
06701       time(&t);
06702       if (t != last_errtime)
06703          ast_log(LOG_NOTICE, "Out of idle IAX2 threads for I/O, pausing!\n");
06704       last_errtime = t;
06705       usleep(1);
06706       return 1;
06707    }
06708 
06709    len = sizeof(thread->iosin);
06710    thread->iofd = fd;
06711    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
06712    thread->buf_size = sizeof(thread->readbuf);
06713    thread->buf = thread->readbuf;
06714    if (thread->buf_len < 0) {
06715       if (errno != ECONNREFUSED && errno != EAGAIN)
06716          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
06717       handle_error();
06718       thread->iostate = IAX_IOSTATE_IDLE;
06719       signal_condition(&thread->lock, &thread->cond);
06720       return 1;
06721    }
06722    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
06723       thread->iostate = IAX_IOSTATE_IDLE;
06724       signal_condition(&thread->lock, &thread->cond);
06725       return 1;
06726    }
06727    
06728    /* Determine if this frame is a full frame; if so, and any thread is currently
06729       processing a full frame for the same callno from this peer, then drop this
06730       frame (and the peer will retransmit it) */
06731    fh = (struct ast_iax2_full_hdr *) thread->buf;
06732    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
06733       struct iax2_thread *cur = NULL;
06734       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
06735       
06736       AST_LIST_LOCK(&active_list);
06737       AST_LIST_TRAVERSE(&active_list, cur, list) {
06738          if ((cur->ffinfo.callno == callno) &&
06739              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
06740             break;
06741       }
06742       if (cur) {
06743          /* we found another thread processing a full frame for this call,
06744             so queue it up for processing later. */
06745          defer_full_frame(thread, cur);
06746          AST_LIST_UNLOCK(&active_list);
06747          thread->iostate = IAX_IOSTATE_IDLE;
06748          signal_condition(&thread->lock, &thread->cond);
06749          return 1;
06750       } else {
06751          /* this thread is going to process this frame, so mark it */
06752          thread->ffinfo.callno = callno;
06753          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
06754          thread->ffinfo.type = fh->type;
06755          thread->ffinfo.csub = fh->csub;
06756       }
06757       AST_LIST_UNLOCK(&active_list);
06758    }
06759    
06760    /* Mark as ready and send on its way */
06761    thread->iostate = IAX_IOSTATE_READY;
06762 #ifdef DEBUG_SCHED_MULTITHREAD
06763    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
06764 #endif
06765    signal_condition(&thread->lock, &thread->cond);
06766 
06767    return 1;
06768 }

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

Definition at line 6479 of file chan_iax2.c.

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

Referenced by socket_process().

06480 {
06481    pthread_t newthread;
06482    struct dpreq_data *dpr;
06483    pthread_attr_t attr;
06484    
06485    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06486       return;
06487 
06488    pthread_attr_init(&attr);
06489    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06490 
06491    dpr->callno = callno;
06492    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06493    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06494    if (callerid)
06495       dpr->callerid = ast_strdup(callerid);
06496    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06497       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06498    }
06499 
06500    pthread_attr_destroy(&attr);
06501 }

static int start_network_thread ( void   )  [static]

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

08880 {
08881    pthread_attr_t attr;
08882    int threadcount = 0;
08883    int x;
08884    for (x = 0; x < iaxthreadcount; x++) {
08885       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
08886       if (thread) {
08887          thread->type = IAX_TYPE_POOL;
08888          thread->threadnum = ++threadcount;
08889          ast_mutex_init(&thread->lock);
08890          ast_cond_init(&thread->cond, NULL);
08891          pthread_attr_init(&attr);
08892          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
08893          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
08894             ast_log(LOG_WARNING, "Failed to create new thread!\n");
08895             free(thread);
08896             thread = NULL;
08897          }
08898          AST_LIST_LOCK(&idle_list);
08899          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
08900          AST_LIST_UNLOCK(&idle_list);
08901       }
08902    }
08903    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
08904    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
08905    if (option_verbose > 1)
08906       ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount);
08907    return 0;
08908 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6164 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06165 {
06166    iax2_destroy_helper(iaxs[callno]);
06167 }

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

Definition at line 6353 of file chan_iax2.c.

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

Referenced by network_thread().

06354 {
06355    char buf[1024];
06356    int res;
06357    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06358    int processed = 0;
06359    int totalcalls = 0;
06360 #ifdef ZT_TIMERACK
06361    int x = 1;
06362 #endif
06363    struct timeval now;
06364    if (iaxtrunkdebug)
06365       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06366    gettimeofday(&now, NULL);
06367    if (events & AST_IO_PRI) {
06368 #ifdef ZT_TIMERACK
06369       /* Great, this is a timing interface, just call the ioctl */
06370       if (ioctl(fd, ZT_TIMERACK, &x)) 
06371          ast_log(LOG_WARNING, "Unable to acknowledge zap timer\n");
06372       res = 0;
06373 #endif      
06374    } else {
06375       /* Read and ignore from the pseudo channel for timing */
06376       res = read(fd, buf, sizeof(buf));
06377       if (res < 1) {
06378          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06379          return 1;
06380       }
06381    }
06382    /* For each peer that supports trunking... */
06383    ast_mutex_lock(&tpeerlock);
06384    tpeer = tpeers;
06385    while(tpeer) {
06386       processed++;
06387       res = 0;
06388       ast_mutex_lock(&tpeer->lock);
06389       /* We can drop a single tpeer per pass.  That makes all this logic
06390          substantially easier */
06391       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06392          /* Take it out of the list, but don't free it yet, because it
06393             could be in use */
06394          if (prev)
06395             prev->next = tpeer->next;
06396          else
06397             tpeers = tpeer->next;
06398          drop = tpeer;
06399       } else {
06400          res = send_trunk(tpeer, &now);
06401          if (iaxtrunkdebug)
06402             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);
06403       }     
06404       totalcalls += res;   
06405       res = 0;
06406       ast_mutex_unlock(&tpeer->lock);
06407       prev = tpeer;
06408       tpeer = tpeer->next;
06409    }
06410    ast_mutex_unlock(&tpeerlock);
06411    if (drop) {
06412       ast_mutex_lock(&drop->lock);
06413       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06414          because by the time they could get tpeerlock, we've already grabbed it */
06415       if (option_debug)
06416          ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06417       free(drop->trunkdata);
06418       ast_mutex_unlock(&drop->lock);
06419       ast_mutex_destroy(&drop->lock);
06420       free(drop);
06421       
06422    }
06423    if (iaxtrunkdebug)
06424       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06425    iaxtrunkdebug =0;
06426    return 1;
06427 }

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

Definition at line 1850 of file chan_iax2.c.

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

Referenced by send_trunk().

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

static int try_firmware ( char *  s  )  [static]

Definition at line 1538 of file chan_iax2.c.

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

Referenced by reload_firmware().

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

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

Definition at line 5571 of file chan_iax2.c.

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

Referenced by socket_process().

05572 {
05573    int newcall = 0;
05574    char newip[256];
05575    struct iax_ie_data ied;
05576    struct sockaddr_in new;
05577    
05578    
05579    memset(&ied, 0, sizeof(ied));
05580    if (ies->apparent_addr)
05581       bcopy(ies->apparent_addr, &new, sizeof(new));
05582    if (ies->callno)
05583       newcall = ies->callno;
05584    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05585       ast_log(LOG_WARNING, "Invalid transfer request\n");
05586       return -1;
05587    }
05588    pvt->transfercallno = newcall;
05589    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05590    inet_aton(newip, &pvt->transfer.sin_addr);
05591    pvt->transfer.sin_family = AF_INET;
05592    pvt->transferring = TRANSFER_BEGIN;
05593    pvt->transferid = ies->transferid;
05594    if (ies->transferid)
05595       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05596    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05597    return 0; 
05598 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1057 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

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

static void unlink_peer ( struct iax2_peer peer  )  [static]

Definition at line 5838 of file chan_iax2.c.

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

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

05839 {
05840    if (peer->expire > -1) {
05841       if (!ast_sched_del(sched, peer->expire)) {
05842          peer->expire = -1;
05843          peer_unref(peer);
05844       }
05845    }
05846 
05847    if (peer->pokeexpire > -1) {
05848       if (!ast_sched_del(sched, peer->pokeexpire)) {
05849          peer->pokeexpire = -1;
05850          peer_unref(peer);
05851       }
05852    }
05853 
05854    ao2_unlink(peers, peer);
05855 }

static int unload_module ( void   )  [static]

Definition at line 10794 of file chan_iax2.c.

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

10795 {
10796    ast_custom_function_unregister(&iaxpeer_function);
10797    return __unload_module();
10798 }

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

Definition at line 3342 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03343 {
03344    ast_mutex_unlock(&iaxsl[callno1]);
03345    ast_mutex_unlock(&iaxsl[callno0]);
03346 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

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

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2421 of file chan_iax2.c.

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

Referenced by __get_from_jb(), and schedule_delivery().

02422 {
02423    int when;
02424    
02425    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02426    
02427    when = jb_next(pvt->jb) - when;
02428    
02429    if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
02430    
02431    if(when <= 0) {
02432       /* XXX should really just empty until when > 0.. */
02433       when = 1;
02434    }
02435    
02436    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02437 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1277 of file chan_iax2.c.

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

Referenced by find_callno(), and make_trunk().

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

static void update_max_trunk ( void   )  [static]

Definition at line 1263 of file chan_iax2.c.

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

Referenced by iax2_destroy(), and make_trunk().

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

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2029 of file chan_iax2.c.

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

Referenced by __attempt_transmit().

02030 {
02031    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02032    struct ast_iax2_full_hdr *fh = f->data;
02033    /* Mark this as a retransmission */
02034    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02035    /* Update iseqno */
02036    f->iseqno = iaxs[f->callno]->iseqno;
02037    fh->iseqno = f->iseqno;
02038    return 0;
02039 }

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

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

Referenced by socket_process().

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

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

Referenced by load_module().

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

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

Definition at line 9521 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09522 {
09523    struct iax2_user *user = obj;
09524 
09525    ast_set_flag(user, IAX_DELME);
09526 
09527    return 0;
09528 }

static void user_destructor ( void *  obj  )  [static]

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

09286 {
09287    struct iax2_user *user = obj;
09288 
09289    ast_free_ha(user->ha);
09290    free_context(user->contexts);
09291    if(user->vars) {
09292       ast_variables_destroy(user->vars);
09293       user->vars = NULL;
09294    }
09295    ast_string_field_free_memory(user);
09296 }

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

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1143 of file chan_iax2.c.

References ao2_ref().

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

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

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

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

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

Definition at line 6267 of file chan_iax2.c.

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

Referenced by socket_process().

06268 {
06269    struct iax_frame *f;
06270 
06271    AST_LIST_LOCK(&iaxq.queue);
06272    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06273       /* Send a copy immediately */
06274       if ((f->callno == callno) && iaxs[f->callno] &&
06275          ((unsigned char ) (f->oseqno - last) < 128) &&
06276          (f->retries >= 0)) {
06277          send_packet(f);
06278       }
06279    }
06280    AST_LIST_UNLOCK(&iaxq.queue);
06281 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

int adsi = 0 [static]

Definition at line 227 of file chan_iax2.c.

int amaflags = 0 [static]

Definition at line 226 of file chan_iax2.c.

int authdebug = 1 [static]

Definition at line 163 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 164 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 10614 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

Initial value:

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

Definition at line 10594 of file chan_iax2.c.

Initial value:

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

Definition at line 10599 of file chan_iax2.c.

Initial value:

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

Definition at line 10609 of file chan_iax2.c.

Initial value:

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

Definition at line 10604 of file chan_iax2.c.

Initial value:

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

Definition at line 10589 of file chan_iax2.c.

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

Definition at line 148 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 10563 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 10555 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 10547 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 180 of file chan_iax2.c.

int delayreject = 0 [static]

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

struct ast_flags globalflags = { 0 } [static]

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 209 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 229 of file chan_iax2.c.

enum { ... } iax2_flags

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

char iax2_reload_usage[] [static]

Initial value:

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

Definition at line 10505 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10479 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

char iax2_test_losspct_usage[] [static]

Initial value:

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

Definition at line 10571 of file chan_iax2.c.

int iaxactivethreadcount = 0 [static]

Definition at line 457 of file chan_iax2.c.

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

int iaxcompat = 0 [static]

Definition at line 165 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 211 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 167 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 169 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 456 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 455 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

Definition at line 10418 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

ast_mutex_t iaxsl[IAX_MAX_CALLS] [static]

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 454 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 213 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 206 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 156 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 150 of file chan_iax2.c.

struct timeval lastused[IAX_MAX_CALLS] [static]

Definition at line 816 of file chan_iax2.c.

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

int max_reg_expire [static]

Definition at line 174 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 154 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 153 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 159 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 161 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 158 of file chan_iax2.c.

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 157 of file chan_iax2.c.

int min_reg_expire [static]

Definition at line 173 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 224 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 225 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 178 of file chan_iax2.c.

pthread_t netthreadid = AST_PTHREADT_NULL [static]

Definition at line 233 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 10567 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 10559 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 10551 of file chan_iax2.c.

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 179 of file chan_iax2.c.

char* papp = "IAX2Provision" [static]

Definition at line 8532 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

char* pdescrip [static]

Initial value:

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

Definition at line 8534 of file chan_iax2.c.

Referenced by load_module().

struct ao2_container* peers [static]

int ping_time = 21 [static]

Definition at line 155 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10501 of file chan_iax2.c.

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

Definition at line 8533 of file chan_iax2.c.

Referenced by load_module().

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 151 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 160 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 207 of file chan_iax2.c.

Definition at line 236 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 234 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 10493 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 10521 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 10539 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 10525 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 10497 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 10533 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10509 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 10543 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 10489 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 10529 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 10516 of file chan_iax2.c.

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

Definition at line 146 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 215 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 176 of file chan_iax2.c.

unsigned int tos = 0 [static]

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

struct ao2_container* users [static]

struct ast_firmware_list waresl [static]


Generated on Sat Apr 12 07:12:37 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5