Fri Sep 25 19:28:23 2009

Asterisk developer's documentation


chan_iax2.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

#define CACHE_FLAG_CANEXIST   (1 << 2)
#define CACHE_FLAG_EXISTS   (1 << 0)
#define CACHE_FLAG_MATCHMORE   (1 << 7)
#define CACHE_FLAG_NONEXISTENT   (1 << 1)
#define CACHE_FLAG_PENDING   (1 << 3)
#define CACHE_FLAG_TIMEOUT   (1 << 4)
#define CACHE_FLAG_TRANSMITTED   (1 << 5)
#define CACHE_FLAG_UNKNOWN   (1 << 6)
#define CALLNO_TO_PTR(a)   ((void *)(unsigned long)(a))
#define DEBUG_SCHED_MULTITHREAD
#define DEBUG_SUPPORT
#define DEFAULT_DROP   3
#define DEFAULT_FREQ_NOTOK   10 * 1000
#define DEFAULT_FREQ_OK   60 * 1000
#define DEFAULT_MAX_THREAD_COUNT   100
#define DEFAULT_MAXMS   2000
#define DEFAULT_RETRY_TIME   1000
#define DEFAULT_THREAD_COUNT   10
#define DEFAULT_TRUNKDATA   640 * 10
#define FORMAT   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n"
#define FORMAT   "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n"
#define FORMAT   "%-15.15s %-15d %-15d\n"
#define FORMAT   "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s"
#define FORMAT   "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n"
#define FORMAT2   "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n"
#define FORMAT2   "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n"
#define FORMAT2   "%-15.15s %-15.15s %-15.15s\n"
#define FORMAT2   "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s"
#define FORMAT2   "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n"
#define FORMATB   "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n"
#define GAMMA   (0.01)
#define IAX2_TRUNK_PREFACE   (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))
#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF
#define IAX_CAPABILITY_LOWBANDWIDTH
#define IAX_CAPABILITY_LOWFREE
#define IAX_CAPABILITY_MEDBANDWIDTH
#define IAX_IOSTATE_IDLE   0
#define IAX_IOSTATE_PROCESSING   2
#define IAX_IOSTATE_READY   1
#define IAX_IOSTATE_SCHEDREADY   3
#define IAX_TYPE_DYNAMIC   2
#define IAX_TYPE_POOL   1
#define IPTOS_MINCOST   0x02
#define MAX_JITTER_BUFFER   50
#define MAX_PEER_BUCKETS   1
#define MAX_RETRY_TIME   10000
#define MAX_TIMESTAMP_SKEW   160
#define MAX_TRUNKDATA   640 * 200
#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS
#define MEMORY_SIZE   100
#define MIN_JITTER_BUFFER   10
#define MIN_RETRY_TIME   100
#define MIN_REUSE_TIME   60
#define NEW_ALLOW   1
#define NEW_FORCE   2
#define NEW_PREVENT   0
#define PTR_TO_CALLNO(a)   ((unsigned short)(unsigned long)(a))
#define SCHED_MULTITHREADED
#define schedule_action(func, data)   __schedule_action(func, data, __PRETTY_FUNCTION__)
#define TRUNK_CALL_START   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), IAX_ALLOWFWDOWNLOAD = (1 << 26)
}
enum  iax_reg_state {
  REG_STATE_UNREGISTERED = 0, REG_STATE_REGSENT, REG_STATE_AUTHSENT, REG_STATE_REGISTERED,
  REG_STATE_REJECTED, REG_STATE_TIMEOUT, REG_STATE_NOAUTH
}
enum  iax_transfer_state {
  TRANSFER_NONE = 0, TRANSFER_BEGIN, TRANSFER_READY, TRANSFER_RELEASED,
  TRANSFER_PASSTHROUGH, TRANSFER_MBEGIN, TRANSFER_MREADY, TRANSFER_MRELEASED,
  TRANSFER_MPASSTHROUGH, TRANSFER_MEDIA, TRANSFER_MEDIAPASS
}

Functions

static void __attempt_transmit (const void *data)
static void __auth_reject (const void *nothing)
static void __auto_congest (const void *nothing)
static void __auto_hangup (const void *nothing)
static int __do_deliver (void *data)
static void __expire_registry (const void *data)
static 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, int full_frame)
static struct iax2_threadfind_idle_thread (void)
static struct iax2_peerfind_peer (const char *name, int realtime)
static struct iax2_trunk_peerfind_tpeer (struct sockaddr_in *sin, int fd)
static unsigned int fix_peerts (struct timeval *tv, int callno, unsigned int ts)
static void free_context (struct iax2_context *con)
static int function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int get_auth_methods (char *value)
static int get_encrypt_methods (const char *s)
static int get_from_jb (const void *p)
static void handle_deferred_full_frames (struct iax2_thread *thread)
 Handle any deferred full frames for this thread.
static int handle_error (void)
static int iax2_ack_registry (struct iax_ies *ies, struct sockaddr_in *sin, int callno)
 Acknowledgment received for OUR registration.
static int iax2_answer (struct ast_channel *c)
static enum ast_bridge_result iax2_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int iax2_call (struct ast_channel *c, char *dest, int timeout)
static int iax2_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 part of the IAX2 dial plan switch interface
static unsigned int iax2_datetime (const char *tz)
static void iax2_destroy (int callno)
static void iax2_destroy_helper (struct chan_iax2_pvt *pvt)
static int iax2_devicestate (void *data)
 Part of the device state notification system ---.
static int iax2_digit_begin (struct ast_channel *c, char digit)
static int iax2_digit_end (struct ast_channel *c, char digit, unsigned int duration)
static int iax2_do_debug (int fd, int argc, char *argv[])
static int iax2_do_jb_debug (int fd, int argc, char *argv[])
static int iax2_do_register (struct iax2_registry *reg)
static int iax2_do_register_s (const void *data)
static int iax2_do_trunk_debug (int fd, int argc, char *argv[])
static void iax2_dprequest (struct iax2_dpcache *dp, int callno)
static int iax2_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 Execute IAX2 dialplan switch.
static int iax2_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 Part of the IAX2 switch interface.
static int iax2_fixup (struct ast_channel *oldchannel, struct ast_channel *newchan)
static void iax2_frame_free (struct iax_frame *fr)
static int iax2_getpeername (struct sockaddr_in sin, char *host, int len)
static int iax2_getpeertrunk (struct sockaddr_in sin)
static int iax2_hangup (struct ast_channel *c)
static int iax2_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen)
static int iax2_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
 Part of the IAX2 Switch interface.
static int iax2_no_debug (int fd, int argc, char *argv[])
static int iax2_no_jb_debug (int fd, int argc, char *argv[])
static int iax2_no_trunk_debug (int fd, int argc, char *argv[])
static int iax2_poke_noanswer (const void *data)
static int iax2_poke_peer (struct iax2_peer *peer, int heldcall)
static int iax2_poke_peer_cb (void *obj, void *arg, int flags)
static int iax2_poke_peer_s (const void *data)
static int iax2_predestroy (int callno)
static void * iax2_process_thread (void *data)
static void iax2_process_thread_cleanup (void *data)
static int iax2_prov_app (struct ast_channel *chan, void *data)
static int iax2_prov_cmd (int fd, int argc, char *argv[])
static char * iax2_prov_complete_template_3rd (const char *line, const char *word, int pos, int state)
static int iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force)
static int iax2_prune_realtime (int fd, int argc, char *argv[])
static int iax2_queue_control_data (int callno, enum ast_control_frame_type control, const void *data, size_t datalen)
 Queue a control frame on the ast_channel owner.
static int iax2_queue_frame (int callno, struct ast_frame *f)
 Queue a frame to a call's owning asterisk channel.
static int iax2_queue_hangup (int callno)
 Queue a hangup frame on the ast_channel owner.
static struct ast_frameiax2_read (struct ast_channel *c)
static int iax2_register (char *value, int lineno)
static int iax2_reload (int fd, int argc, char *argv[])
static struct ast_channeliax2_request (const char *type, int format, void *data, int *cause)
static int iax2_sched_add (struct sched_context *con, int when, ast_sched_cb callback, const void *data)
static int iax2_send (struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final)
static int iax2_sendhtml (struct ast_channel *c, int subclass, const char *data, int datalen)
static int iax2_sendimage (struct ast_channel *c, struct ast_frame *img)
static int iax2_sendtext (struct ast_channel *c, const char *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, int full_frame)
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_apathetic_reply (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int command, int ts, unsigned char seqno)
static int send_command (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_final (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_immediate (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_locked (unsigned short callno, char, int, unsigned int, const unsigned char *, int, int)
static int send_command_transfer (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int)
static int send_lagrq (const void *data)
static int send_packet (struct iax_frame *f)
static int send_ping (const void *data)
static int send_trunk (struct iax2_trunk_peer *tpeer, struct timeval *now)
static int set_config (char *config_file, int reload)
 Load configuration.
static void set_config_destroy (void)
static void set_timing (void)
static void signal_condition (ast_mutex_t *lock, ast_cond_t *cond)
static int socket_process (struct iax2_thread *thread)
static int socket_read (int *id, int fd, short events, void *cbdata)
static void spawn_dp_lookup (int callno, const char *context, const char *callednum, const char *callerid)
static int start_network_thread (void)
static void stop_stuff (int callno)
static 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 int last_authmethod = 0
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 669 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 665 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 679 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 667 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 671 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 673 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

Definition at line 675 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 677 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 205 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 204 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 203 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 448 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 369 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 186 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 194 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 199 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 188 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 700 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 702 of file chan_iax2.c.

Referenced by iax2_process_thread().

#define IAX_IOSTATE_READY   1

Definition at line 701 of file chan_iax2.c.

Referenced by iax2_process_thread(), and socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 703 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 705 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 445 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 651 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 449 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

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

#define MIN_RETRY_TIME   100

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

Referenced by find_callno(), and socket_process().

#define NEW_FORCE   2

#define NEW_PREVENT   0

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

00239      {
00240    IAX_STATE_STARTED =     (1 << 0),
00241    IAX_STATE_AUTHENTICATED =  (1 << 1),
00242    IAX_STATE_TBD =      (1 << 2),
00243    IAX_STATE_UNCHANGED =      (1 << 3),
00244 } iax2_state;

anonymous enum

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

Definition at line 251 of file chan_iax2.c.

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


Function Documentation

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

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

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

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

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

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

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

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

03005 {
03006    int callno = PTR_TO_CALLNO(nothing);
03007    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03008    ast_mutex_lock(&iaxsl[callno]);
03009    if (iaxs[callno]) {
03010       iaxs[callno]->initid = -1;
03011       iax2_queue_frame(callno, &f);
03012       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03013    }
03014    ast_mutex_unlock(&iaxsl[callno]);
03015 }

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

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

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

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

01820 {
01821    /* Just deliver the packet by using queueing.  This is called by
01822      the IAX thread with the iaxsl lock held. */
01823    struct iax_frame *fr = data;
01824    fr->retrans = -1;
01825    fr->af.has_timing_info = 0;
01826    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
01827       iax2_queue_frame(fr->callno, &fr->af);
01828    /* Free our iax frame */
01829    iax2_frame_free(fr);
01830    /* And don't run again */
01831    return 0;
01832 }

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

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

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

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

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

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

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

Definition at line 5588 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

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

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

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

08650 {
08651    struct iax2_peer *peer = (struct iax2_peer *)data;
08652    if (peer->lastms > -1) {
08653       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08654       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08655       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08656    }
08657    if (peer->callno > 0) {
08658       ast_mutex_lock(&iaxsl[peer->callno]);
08659       iax2_destroy(peer->callno);
08660       ast_mutex_unlock(&iaxsl[peer->callno]);
08661    }
08662    peer->callno = 0;
08663    peer->lastms = -1;
08664    /* Try again quickly */
08665    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08666    if (peer->pokeexpire == -1)
08667       peer_unref(peer);
08668 }

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

Definition at line 6322 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06323 {
06324    struct iax2_peer *peer = (struct iax2_peer *)data;
06325    iax2_poke_peer(peer, 0);
06326    peer_unref(peer);
06327 }

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

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

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

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

Definition at line 944 of file chan_iax2.c.

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

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

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

04875 {
04876    struct ast_frame f = { 0, };
04877 
04878    f.frametype = type;
04879    f.subclass = command;
04880    f.datalen = datalen;
04881    f.src = __FUNCTION__;
04882    f.data = (void *) data;
04883 
04884    return iax2_send(i, &f, ts, seqno, now, transfer, final);
04885 }

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

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

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

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

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

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

static int __unload_module ( void   )  [static]

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

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

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

Definition at line 4926 of file chan_iax2.c.

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

Referenced by check_access().

04927 {
04928    while(con) {
04929       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
04930          return -1;
04931       con = con->next;
04932    }
04933    return 0;
04934 }

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

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

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

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

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

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

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02142 {
02143 #ifdef SCHED_MULTITHREADED
02144    if (schedule_action(__attempt_transmit, data))
02145 #endif      
02146       __attempt_transmit(data);
02147    return 0;
02148 }

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

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

06243 {
06244    /* Schedule sending the authentication failure in one second, to prevent
06245       guessing */
06246    if (iaxs[callno]) {
06247       iaxs[callno]->authfail = failcode;
06248       if (delayreject) {
06249          if (iaxs[callno]->authid > -1)
06250             ast_sched_del(sched, iaxs[callno]->authid);
06251          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06252       } else
06253          auth_reject((void *)(long)callno);
06254    }
06255    return 0;
06256 }

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

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

06229 {
06230    int callno = (int)(long)(data);
06231    ast_mutex_lock(&iaxsl[callno]);
06232    if (iaxs[callno])
06233       iaxs[callno]->authid = -1;
06234    ast_mutex_unlock(&iaxsl[callno]);
06235 #ifdef SCHED_MULTITHREADED
06236    if (schedule_action(__auth_reject, data))
06237 #endif      
06238       __auth_reject(data);
06239    return 0;
06240 }

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

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

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

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

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

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

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

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

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

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

Definition at line 3017 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03018 {
03019 #ifdef SCHED_MULTITHREADED
03020    if (schedule_action(__auto_congest, data))
03021 #endif      
03022       __auto_congest(data);
03023    return 0;
03024 }

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

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

06274 {
06275    int callno = (int)(long)(data);
06276    ast_mutex_lock(&iaxsl[callno]);
06277    if (iaxs[callno]) {
06278       iaxs[callno]->autoid = -1;
06279    }
06280    ast_mutex_unlock(&iaxsl[callno]);
06281 #ifdef SCHED_MULTITHREADED
06282    if (schedule_action(__auto_hangup, data))
06283 #endif      
06284       __auto_hangup(data);
06285    return 0;
06286 }

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

Definition at line 8964 of file chan_iax2.c.

References ast_calloc, and iax2_context::context.

Referenced by build_user().

08965 {
08966    struct iax2_context *con;
08967 
08968    if ((con = ast_calloc(1, sizeof(*con))))
08969       ast_copy_string(con->context, context, sizeof(con->context));
08970    
08971    return con;
08972 }

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

Definition at line 3969 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

03970 {
03971    aes_encrypt_key128(digest, ecx);
03972    aes_decrypt_key128(digest, dcx);
03973 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

03676 {
03677    unsigned long int mssincetx; /* unsigned to handle overflows */
03678    long int ms, pred;
03679 
03680    tpeer->trunkact = *tv;
03681    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03682    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03683       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03684       tpeer->txtrunktime = *tv;
03685       tpeer->lastsent = 999999;
03686    }
03687    /* Update last transmit time now */
03688    tpeer->lasttxtime = *tv;
03689    
03690    /* Calculate ms offset */
03691    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03692    /* Predict from last value */
03693    pred = tpeer->lastsent + sampms;
03694    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03695       ms = pred;
03696    
03697    /* We never send the same timestamp twice, so fudge a little if we must */
03698    if (ms == tpeer->lastsent)
03699       ms = tpeer->lastsent + 1;
03700    tpeer->lastsent = ms;
03701    return ms;
03702 }

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

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

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

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

Definition at line 6627 of file chan_iax2.c.

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

Referenced by socket_process().

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

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

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

Referenced by peer_set_srcaddr().

08991 {
08992    int sd;
08993    int res;
08994    
08995    sd = socket(AF_INET, SOCK_DGRAM, 0);
08996    if (sd < 0) {
08997       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
08998       return -1;
08999    }
09000 
09001    res = bind(sd, sa, salen);
09002    if (res < 0) {
09003       if (option_debug)
09004          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09005       close(sd);
09006       return 1;
09007    }
09008 
09009    close(sd);
09010    return 0;
09011 }

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

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

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

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

Definition at line 2303 of file chan_iax2.c.

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

02304 {
02305    int which = 0;
02306    struct iax2_peer *peer;
02307    char *res = NULL;
02308    int wordlen = strlen(word);
02309    struct ao2_iterator i;
02310 
02311    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02312    if (pos != 3)
02313       return NULL;
02314 
02315    i = ao2_iterator_init(peers, 0);
02316    while ((peer = ao2_iterator_next(&i))) {
02317       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02318          res = ast_strdup(peer->name);
02319          peer_unref(peer);
02320          break;
02321       }
02322       peer_unref(peer);
02323    }
02324 
02325    return res;
02326 }

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

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

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

static unsigned char compress_subclass ( int  subclass  )  [static]

Definition at line 1039 of file chan_iax2.c.

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

Referenced by iax2_send(), raw_hangup(), and send_apathetic_reply().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void delete_users ( void   )  [static]

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

09585 {
09586    struct iax2_registry *reg;
09587 
09588    ao2_callback(users, 0, user_delme_cb, NULL);
09589 
09590    AST_LIST_LOCK(&registrations);
09591    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09592       if (reg->expire > -1)
09593          ast_sched_del(sched, reg->expire);
09594       if (reg->callno) {
09595          ast_mutex_lock(&iaxsl[reg->callno]);
09596          if (iaxs[reg->callno]) {
09597             iaxs[reg->callno]->reg = NULL;
09598             iax2_destroy(reg->callno);
09599          }
09600          ast_mutex_unlock(&iaxsl[reg->callno]);
09601       }
09602       if (reg->dnsmgr)
09603          ast_dnsmgr_release(reg->dnsmgr);
09604       free(reg);
09605    }
09606    AST_LIST_UNLOCK(&registrations);
09607 
09608    ao2_callback(peers, 0, peer_delme_cb, NULL);
09609 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1546 of file chan_iax2.c.

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

Referenced by reload_firmware().

01547 {
01548    /* Close firmware */
01549    if (cur->fwh) {
01550       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01551    }
01552    close(cur->fd);
01553    free(cur);
01554 }

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

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

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

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

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

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

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

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

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

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

Definition at line 5921 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

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

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

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

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

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

Definition at line 1344 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_random(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_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().

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3704 of file chan_iax2.c.

References iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03705 {
03706    long ms; /* NOT unsigned */
03707    if (ast_tvzero(iaxs[callno]->rxcore)) {
03708       /* Initialize rxcore time if appropriate */
03709       gettimeofday(&iaxs[callno]->rxcore, NULL);
03710       /* Round to nearest 20ms so traces look pretty */
03711       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03712    }
03713    /* Calculate difference between trunk and channel */
03714    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03715    /* Return as the sum of trunk time and the difference between trunk and real time */
03716    return ms + ts;
03717 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 8746 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

08747 {
08748    struct iax2_context *conl;
08749    while(con) {
08750       conl = con;
08751       con = con->next;
08752       free(conl);
08753    }
08754 }

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

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

static int get_auth_methods ( char *  value  )  [static]

Definition at line 8974 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

08975 {
08976    int methods = 0;
08977    if (strstr(value, "rsa"))
08978       methods |= IAX_AUTH_RSA;
08979    if (strstr(value, "md5"))
08980       methods |= IAX_AUTH_MD5;
08981    if (strstr(value, "plaintext"))
08982       methods |= IAX_AUTH_PLAINTEXT;
08983    return methods;
08984 }

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

Definition at line 1004 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

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

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

Definition at line 2534 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02535 {
02536 #ifdef SCHED_MULTITHREADED
02537    if (schedule_action(__get_from_jb, data))
02538 #endif      
02539       __get_from_jb(data);
02540    return 0;
02541 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

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

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

static int handle_error ( void   )  [static]

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

01835 {
01836    /* XXX Ideally we should figure out why an error occured and then abort those
01837       rather than continuing to try.  Unfortunately, the published interface does
01838       not seem to work XXX */
01839 #if 0
01840    struct sockaddr_in *sin;
01841    int res;
01842    struct msghdr m;
01843    struct sock_extended_err e;
01844    m.msg_name = NULL;
01845    m.msg_namelen = 0;
01846    m.msg_iov = NULL;
01847    m.msg_control = &e;
01848    m.msg_controllen = sizeof(e);
01849    m.msg_flags = 0;
01850    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
01851    if (res < 0)
01852       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
01853    else {
01854       if (m.msg_controllen) {
01855          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
01856          if (sin) 
01857             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
01858          else
01859             ast_log(LOG_WARNING, "No address detected??\n");
01860       } else {
01861          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
01862       }
01863    }
01864 #endif
01865    return 0;
01866 }

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

Acknowledgment received for OUR registration.

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

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

static int iax2_answer ( struct ast_channel c  )  [static]

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

03526 {
03527    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03528    if (option_debug)
03529       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03530    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03531 }

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

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

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

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

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

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

10311 {
10312    int res = 0;
10313    struct iax2_dpcache *dp;
10314 #if 0
10315    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10316 #endif
10317    if ((priority != 1) && (priority != 2))
10318       return 0;
10319    ast_mutex_lock(&dpcache_lock);
10320    dp = find_cache(chan, data, context, exten, priority);
10321    if (dp) {
10322       if (dp->flags & CACHE_FLAG_CANEXIST)
10323          res= 1;
10324    }
10325    ast_mutex_unlock(&dpcache_lock);
10326    if (!dp) {
10327       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10328    }
10329    return res;
10330 }

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

Definition at line 3026 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03027 {
03028    time_t t;
03029    struct tm tm;
03030    unsigned int tmp;
03031    time(&t);
03032    if (!ast_strlen_zero(tz))
03033       ast_localtime(&t, &tm, tz);
03034    else
03035       ast_localtime(&t, &tm, NULL);
03036    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03037    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03038    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03039    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03040    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03041    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03042    return tmp;
03043 }

static void iax2_destroy ( int  callno  )  [static]

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

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

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

01915 {
01916    /* Decrement AUTHREQ count if needed */
01917    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01918       struct iax2_user *user;
01919       struct iax2_user tmp_user = {
01920          .name = pvt->username,
01921       };
01922 
01923       user = ao2_find(users, &tmp_user, OBJ_POINTER);
01924       if (user) {
01925          ast_atomic_fetchadd_int(&user->curauthreq, -1);
01926          user_unref(user); 
01927       }
01928 
01929       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01930    }
01931    /* No more pings or lagrq's */
01932    if (pvt->pingid > -1)
01933       ast_sched_del(sched, pvt->pingid);
01934    pvt->pingid = -1;
01935    if (pvt->lagid > -1)
01936       ast_sched_del(sched, pvt->lagid);
01937    pvt->lagid = -1;
01938    if (pvt->autoid > -1)
01939       ast_sched_del(sched, pvt->autoid);
01940    pvt->autoid = -1;
01941    if (pvt->authid > -1)
01942       ast_sched_del(sched, pvt->authid);
01943    pvt->authid = -1;
01944    if (pvt->initid > -1)
01945       ast_sched_del(sched, pvt->initid);
01946    pvt->initid = -1;
01947    if (pvt->jbid > -1)
01948       ast_sched_del(sched, pvt->jbid);
01949    pvt->jbid = -1;
01950 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

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

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

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

Definition at line 2653 of file chan_iax2.c.

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

02654 {
02655    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02656 }

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

Definition at line 2658 of file chan_iax2.c.

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

02659 {
02660    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02661 }

static int iax2_do_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 < 2 || argc > 3)
04791       return RESULT_SHOWUSAGE;
04792    iaxdebug = 1;
04793    ast_cli(fd, "IAX2 Debugging Enabled\n");
04794    return RESULT_SUCCESS;
04795 }

static int iax2_do_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 < 3 || argc > 4)
04809       return RESULT_SHOWUSAGE;
04810    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
04811    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
04812    return RESULT_SUCCESS;
04813 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

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

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

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

Definition at line 5595 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

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

static int iax2_do_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 < 3 || argc > 4)
04800       return RESULT_SHOWUSAGE;
04801    iaxtrunkdebug = 1;
04802    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
04803    return RESULT_SUCCESS;
04804 }

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

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

06289 {
06290    struct iax_ie_data ied;
06291    /* Auto-hangup with 30 seconds of inactivity */
06292    if (iaxs[callno]->autoid > -1)
06293       ast_sched_del(sched, iaxs[callno]->autoid);
06294    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06295    memset(&ied, 0, sizeof(ied));
06296    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06297    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06298    dp->flags |= CACHE_FLAG_TRANSMITTED;
06299 }

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

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

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

10288 {
10289    struct iax2_dpcache *dp;
10290    int res = 0;
10291 #if 0
10292    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10293 #endif
10294    if ((priority != 1) && (priority != 2))
10295       return 0;
10296    ast_mutex_lock(&dpcache_lock);
10297    dp = find_cache(chan, data, context, exten, priority);
10298    if (dp) {
10299       if (dp->flags & CACHE_FLAG_EXISTS)
10300          res= 1;
10301    }
10302    ast_mutex_unlock(&dpcache_lock);
10303    if (!dp) {
10304       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10305    }
10306    return res;
10307 }

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

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

02681 {
02682    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02683    ast_mutex_lock(&iaxsl[callno]);
02684    if (iaxs[callno])
02685       iaxs[callno]->owner = newchan;
02686    else
02687       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02688    ast_mutex_unlock(&iaxsl[callno]);
02689    return 0;
02690 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

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

01444 {
01445    if (fr->retrans > -1)
01446       ast_sched_del(sched, fr->retrans);
01447    iax_frame_free(fr);
01448 }

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

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

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

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

03588 {
03589    struct iax2_peer *peer;
03590    int res = 0;
03591    struct ao2_iterator i;
03592 
03593    i = ao2_iterator_init(peers, 0);
03594    while ((peer = ao2_iterator_next(&i))) {
03595       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03596           (peer->addr.sin_port == sin.sin_port)) {
03597          res = ast_test_flag(peer, IAX_TRUNK);
03598          peer_unref(peer);
03599          break;
03600       }
03601       peer_unref(peer);
03602    }
03603 
03604    return res;
03605 }

static int iax2_hangup ( struct ast_channel c  )  [static]

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

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

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

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

03534 {
03535    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03536    struct chan_iax2_pvt *pvt;
03537    int res = 0;
03538 
03539    if (option_debug && iaxdebug)
03540       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03541 
03542    ast_mutex_lock(&iaxsl[callno]);
03543    pvt = iaxs[callno];
03544 
03545    switch (condition) {
03546    case AST_CONTROL_HOLD:
03547       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03548          ast_moh_start(c, data, pvt->mohinterpret);
03549          goto done;
03550       }
03551       break;
03552    case AST_CONTROL_UNHOLD:
03553       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03554          ast_moh_stop(c);
03555          goto done;
03556       }
03557    }
03558 
03559    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03560 
03561 done:
03562    ast_mutex_unlock(&iaxsl[callno]);
03563 
03564    return res;
03565 }

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

10334 {
10335    int res = 0;
10336    struct iax2_dpcache *dp;
10337 #if 0
10338    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10339 #endif
10340    if ((priority != 1) && (priority != 2))
10341       return 0;
10342    ast_mutex_lock(&dpcache_lock);
10343    dp = find_cache(chan, data, context, exten, priority);
10344    if (dp) {
10345       if (dp->flags & CACHE_FLAG_MATCHMORE)
10346          res= 1;
10347    }
10348    ast_mutex_unlock(&dpcache_lock);
10349    if (!dp) {
10350       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10351    }
10352    return res;
10353 }

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

Definition at line 4815 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

04816 {
04817    if (argc < 3 || argc > 4)
04818       return RESULT_SHOWUSAGE;
04819    iaxdebug = 0;
04820    ast_cli(fd, "IAX2 Debugging Disabled\n");
04821    return RESULT_SUCCESS;
04822 }

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

Definition at line 4833 of file chan_iax2.c.

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

04834 {
04835    if (argc < 4 || argc > 5)
04836       return RESULT_SHOWUSAGE;
04837    jb_setoutput(jb_error_output, jb_warning_output, NULL);
04838    jb_debug_output("\n");
04839    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
04840    return RESULT_SUCCESS;
04841 }

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

Definition at line 4824 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 8670 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08671 {
08672    struct iax2_peer *peer = (struct iax2_peer *)data;
08673    peer->pokeexpire = -1;
08674 #ifdef SCHED_MULTITHREADED
08675    if (schedule_action(__iax2_poke_noanswer, data))
08676 #endif      
08677       __iax2_poke_noanswer(data);
08678    peer_unref(peer);
08679    return 0;
08680 }

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

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

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

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

Definition at line 8682 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

08683 {
08684    struct iax2_peer *peer = obj;
08685 
08686    iax2_poke_peer(peer, 0);
08687 
08688    return 0;
08689 }

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

Definition at line 6329 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06330 {
06331    struct iax2_peer *peer = (struct iax2_peer *)data;
06332    peer->pokeexpire = -1;
06333 #ifdef SCHED_MULTITHREADED
06334    if (schedule_action(__iax2_poke_peer_s, data))
06335 #endif      
06336       __iax2_poke_peer_s(data);
06337    return 0;
06338 }

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

01957 {
01958    struct ast_channel *c;
01959    struct chan_iax2_pvt *pvt = iaxs[callno];
01960 
01961    if (!pvt)
01962       return -1;
01963    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
01964       iax2_destroy_helper(pvt);
01965       ast_set_flag(pvt, IAX_ALREADYGONE); 
01966    }
01967    c = pvt->owner;
01968    if (c) {
01969       c->tech_pvt = NULL;
01970       iax2_queue_hangup(callno);
01971       pvt->owner = NULL;
01972       ast_module_unref(ast_module_info->self);
01973    }
01974    return 0;
01975 }

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

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

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8337 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08338 {
08339    struct iax2_thread *thread = data;
08340    ast_mutex_destroy(&thread->lock);
08341    ast_cond_destroy(&thread->cond);
08342    free(thread);
08343    ast_atomic_dec_and_test(&iaxactivethreadcount);
08344 }

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

Definition at line 8627 of file chan_iax2.c.

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

08628 {
08629    int force = 0;
08630    int res;
08631    if (argc < 4)
08632       return RESULT_SHOWUSAGE;
08633    if ((argc > 4)) {
08634       if (!strcasecmp(argv[4], "forced"))
08635          force = 1;
08636       else
08637          return RESULT_SHOWUSAGE;
08638    }
08639    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08640    if (res < 0)
08641       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08642    else if (res < 1)
08643       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08644    else
08645       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08646    return RESULT_SUCCESS;
08647 }

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

Definition at line 8528 of file chan_iax2.c.

References iax_prov_complete_template().

08529 {
08530    if (pos != 3)
08531       return NULL;
08532    return iax_prov_complete_template(line, word, pos, state);
08533 }

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

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

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

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

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

02151 {
02152    struct iax2_peer *peer;
02153 
02154    if (argc != 4)
02155         return RESULT_SHOWUSAGE;
02156    if (!strcmp(argv[3],"all")) {
02157       reload_config();
02158       ast_cli(fd, "OK cache is flushed.\n");
02159    } else if ((peer = find_peer(argv[3], 0))) {
02160       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02161          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02162          expire_registry(peer_ref(peer));
02163          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02164       } else {
02165          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02166       }
02167       peer_unref(peer);
02168    } else {
02169       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02170    }
02171    
02172    return RESULT_SUCCESS;
02173 }

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

01528 {
01529    for (;;) {
01530       if (iaxs[callno] && iaxs[callno]->owner) {
01531          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01532             /* Avoid deadlock by pausing and trying again */
01533             ast_mutex_unlock(&iaxsl[callno]);
01534             usleep(1);
01535             ast_mutex_lock(&iaxsl[callno]);
01536          } else {
01537             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01538             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01539             break;
01540          }
01541       } else
01542          break;
01543    }
01544    return 0;
01545 }

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

01461 {
01462    for (;;) {
01463       if (iaxs[callno] && iaxs[callno]->owner) {
01464          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01465             /* Avoid deadlock by pausing and trying again */
01466             ast_mutex_unlock(&iaxsl[callno]);
01467             usleep(1);
01468             ast_mutex_lock(&iaxsl[callno]);
01469          } else {
01470             ast_queue_frame(iaxs[callno]->owner, f);
01471             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01472             break;
01473          }
01474       } else
01475          break;
01476    }
01477    return 0;
01478 }

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

01494 {
01495    for (;;) {
01496       if (iaxs[callno] && iaxs[callno]->owner) {
01497          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01498             /* Avoid deadlock by pausing and trying again */
01499             ast_mutex_unlock(&iaxsl[callno]);
01500             usleep(1);
01501             ast_mutex_lock(&iaxsl[callno]);
01502          } else {
01503             ast_queue_hangup(iaxs[callno]->owner);
01504             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01505             break;
01506          }
01507       } else
01508          break;
01509    }
01510    return 0;
01511 }

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

Definition at line 3325 of file chan_iax2.c.

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

03326 {
03327    if (option_verbose > 3)
03328        ast_log(LOG_NOTICE, "I should never be called!\n");
03329    return &ast_null_frame;
03330 }

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

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

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

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

Definition at line 10060 of file chan_iax2.c.

References reload_config().

10061 {
10062    return reload_config();
10063 }

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

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

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

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

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

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

Definition at line 2675 of file chan_iax2.c.

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

02676 {
02677    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02678 }

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

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

02664 {
02665    
02666    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02667       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02668 }

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

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

03300 {
03301    struct ast_option_header *h;
03302    int res;
03303 
03304    switch (option) {
03305    case AST_OPTION_TXGAIN:
03306    case AST_OPTION_RXGAIN:
03307       /* these two cannot be sent, because they require a result */
03308       errno = ENOSYS;
03309       return -1;
03310    default:
03311       if (!(h = ast_malloc(datalen + sizeof(*h))))
03312          return -1;
03313 
03314       h->flag = AST_OPTION_FLAG_REQUEST;
03315       h->option = htons(option);
03316       memcpy(h->data, data, datalen);
03317       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03318                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03319                  datalen + sizeof(*h), -1);
03320       free(h);
03321       return res;
03322    }
03323 }

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

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

02355 {
02356    struct iax2_dpcache *dp;
02357    char tmp[1024], *pc;
02358    int s;
02359    int x,y;
02360    struct timeval tv;
02361    gettimeofday(&tv, NULL);
02362    ast_mutex_lock(&dpcache_lock);
02363    dp = dpcache;
02364    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02365    while(dp) {
02366       s = dp->expiry.tv_sec - tv.tv_sec;
02367       tmp[0] = '\0';
02368       if (dp->flags & CACHE_FLAG_EXISTS)
02369          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02370       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02371          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02372       if (dp->flags & CACHE_FLAG_CANEXIST)
02373          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02374       if (dp->flags & CACHE_FLAG_PENDING)
02375          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02376       if (dp->flags & CACHE_FLAG_TIMEOUT)
02377          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02378       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02379          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02380       if (dp->flags & CACHE_FLAG_MATCHMORE)
02381          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02382       if (dp->flags & CACHE_FLAG_UNKNOWN)
02383          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02384       /* Trim trailing pipe */
02385       if (!ast_strlen_zero(tmp))
02386          tmp[strlen(tmp) - 1] = '\0';
02387       else
02388          ast_copy_string(tmp, "(none)", sizeof(tmp));
02389       y=0;
02390       pc = strchr(dp->peercontext, '@');
02391       if (!pc)
02392          pc = dp->peercontext;
02393       else
02394          pc++;
02395       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02396          if (dp->waiters[x] > -1)
02397             y++;
02398       if (s > 0)
02399          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02400       else
02401          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02402       dp = dp->next;
02403    }
02404    ast_mutex_unlock(&dpcache_lock);
02405    return RESULT_SUCCESS;
02406 }

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

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

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

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

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

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

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

Definition at line 4776 of file chan_iax2.c.

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

04777 {
04778    int numchans = 0;
04779    if (argc != 3)
04780       return RESULT_SHOWUSAGE;
04781    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
04782    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
04783    numchans = ast_cli_netstats(NULL, fd, 1);
04784    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04785    return RESULT_SUCCESS;
04786 }

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

Show one peer in detail.

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

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

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

Definition at line 4553 of file chan_iax2.c.

References __iax2_show_peers().

04554 {
04555    return __iax2_show_peers(0, fd, NULL, argc, argv);
04556 }

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

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

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

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

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

02329 {
02330    struct iax_frame *cur;
02331    int cnt = 0, dead=0, final=0;
02332 
02333    if (argc != 3)
02334       return RESULT_SHOWUSAGE;
02335 
02336    AST_LIST_LOCK(&iaxq.queue);
02337    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02338       if (cur->retries < 0)
02339          dead++;
02340       if (cur->final)
02341          final++;
02342       cnt++;
02343    }
02344    AST_LIST_UNLOCK(&iaxq.queue);
02345 
02346    ast_cli(fd, "    IAX Statistics\n");
02347    ast_cli(fd, "---------------------\n");
02348    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02349    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02350    
02351    return RESULT_SUCCESS;
02352 }

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

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

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

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

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

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

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

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

03333 {
03334    int res;
03335    struct iax_ie_data ied0;
03336    struct iax_ie_data ied1;
03337    unsigned int transferid = (unsigned int)ast_random();
03338    memset(&ied0, 0, sizeof(ied0));
03339    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03340    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03341    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03342 
03343    memset(&ied1, 0, sizeof(ied1));
03344    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03345    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03346    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03347    
03348    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03349    if (res)
03350       return -1;
03351    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03352    if (res)
03353       return -1;
03354    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03355    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03356    return 0;
03357 }

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

Definition at line 2175 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02176 {
02177        if (argc != 4)
02178                return RESULT_SHOWUSAGE;
02179 
02180        test_losspct = atoi(argv[3]);
02181 
02182        return RESULT_SUCCESS;
02183 }

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

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

03568 {
03569    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03570    struct iax_ie_data ied;
03571    char tmp[256], *context;
03572    ast_copy_string(tmp, dest, sizeof(tmp));
03573    context = strchr(tmp, '@');
03574    if (context) {
03575       *context = '\0';
03576       context++;
03577    }
03578    memset(&ied, 0, sizeof(ied));
03579    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03580    if (context)
03581       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03582    if (option_debug)
03583       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03584    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03585 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

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

02635 {
02636    /* Lock the queue and place this packet at the end */
02637    /* By setting this to 0, the network thread will send it for us, and
02638       queue retransmission if necessary */
02639    fr->sentyet = 0;
02640    AST_LIST_LOCK(&iaxq.queue);
02641    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02642    iaxq.count++;
02643    AST_LIST_UNLOCK(&iaxq.queue);
02644    /* Wake up the network and scheduler thread */
02645    if (netthreadid != AST_PTHREADT_NULL)
02646       pthread_kill(netthreadid, SIGURG);
02647    signal_condition(&sched_lock, &sched_cond);
02648    return 0;
02649 }

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

Definition at line 6384 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06385 {
06386    /* Drop when trunk is about 5 seconds idle */
06387    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06388       return 1;
06389    return 0;
06390 }

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

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

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

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6301 of file chan_iax2.c.

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

Referenced by socket_process().

06302 {
06303    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06304 }

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

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

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

static int iax_check_version ( char *  dev  )  [static]

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

01702 {
01703    int res = 0;
01704    struct iax_firmware *cur;
01705    if (!ast_strlen_zero(dev)) {
01706       ast_mutex_lock(&waresl.lock);
01707       cur = waresl.wares;
01708       while(cur) {
01709          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01710             res = ntohs(cur->fwh->version);
01711             break;
01712          }
01713          cur = cur->next;
01714       }
01715       ast_mutex_unlock(&waresl.lock);
01716    }
01717    return res;
01718 }

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

Definition at line 768 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

00769 {
00770    if (iaxdebug)
00771       ast_verbose("%s", data);
00772 }

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

Definition at line 774 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00775 {
00776    ast_log(LOG_WARNING, "%s", data);
00777 }

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

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

01721 {
01722    int res = -1;
01723    unsigned int bs = desc & 0xff;
01724    unsigned int start = (desc >> 8) & 0xffffff;
01725    unsigned int bytes;
01726    struct iax_firmware *cur;
01727    if (!ast_strlen_zero((char *)dev) && bs) {
01728       start *= bs;
01729       ast_mutex_lock(&waresl.lock);
01730       cur = waresl.wares;
01731       while(cur) {
01732          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01733             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01734             if (start < ntohl(cur->fwh->datalen)) {
01735                bytes = ntohl(cur->fwh->datalen) - start;
01736                if (bytes > bs)
01737                   bytes = bs;
01738                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
01739             } else {
01740                bytes = 0;
01741                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
01742             }
01743             if (bytes == bs)
01744                res = 0;
01745             else
01746                res = 1;
01747             break;
01748          }
01749          cur = cur->next;
01750       }
01751       ast_mutex_unlock(&waresl.lock);
01752    }
01753    return res;
01754 }

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

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

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

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

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

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

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

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

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

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

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

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

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

Definition at line 803 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 779 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 791 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

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

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

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

Definition at line 3359 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03360 {
03361    ast_mutex_lock(&iaxsl[callno0]);
03362    while (ast_mutex_trylock(&iaxsl[callno1])) {
03363       ast_mutex_unlock(&iaxsl[callno0]);
03364       usleep(10);
03365       ast_mutex_lock(&iaxsl[callno0]);
03366    }
03367 }

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

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

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

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

Definition at line 4557 of file chan_iax2.c.

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

Referenced by load_module().

04558 {
04559    ast_cli_netstats(s, -1, 0);
04560    astman_append(s, "\r\n");
04561    return RESULT_SUCCESS;
04562 }

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

Definition at line 4590 of file chan_iax2.c.

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

Referenced by load_module().

04591 {
04592    char *a[] = { "iax2", "show", "users" };
04593    int ret;
04594    const char *id = astman_get_header(m,"ActionID");
04595 
04596    if (!ast_strlen_zero(id))
04597       astman_append(s, "ActionID: %s\r\n",id);
04598    ret = __iax2_show_peers(1, -1, s, 3, a );
04599    astman_append(s, "\r\n\r\n" );
04600    return ret;
04601 } /* /JDG */

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

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

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

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

Definition at line 3975 of file chan_iax2.c.

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

Referenced by decode_frame().

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

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

Definition at line 3999 of file chan_iax2.c.

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

Referenced by encrypt_frame().

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

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

Definition at line 5168 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05169 {
05170    /* Select exactly one common encryption if there are any */
05171    p->encmethods &= enc;
05172    if (p->encmethods) {
05173       if (p->encmethods & IAX_ENCRYPT_AES128)
05174          p->encmethods = IAX_ENCRYPT_AES128;
05175       else
05176          p->encmethods = 0;
05177    }
05178 }

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

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

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

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

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

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

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

03084 {
03085    if (ast_strlen_zero(data))
03086       return;
03087 
03088    pds->peer = strsep(&data, "/");
03089    pds->exten = strsep(&data, "/");
03090    pds->options = data;
03091 
03092    if (pds->exten) {
03093       data = pds->exten;
03094       pds->exten = strsep(&data, "@");
03095       pds->context = data;
03096    }
03097 
03098    if (strchr(pds->peer, '@')) {
03099       data = pds->peer;
03100       pds->username = strsep(&data, "@");
03101       pds->peer = data;
03102    }
03103 
03104    if (pds->username) {
03105       data = pds->username;
03106       pds->username = strsep(&data, ":");
03107       pds->password = data;
03108    }
03109 
03110    data = pds->peer;
03111    pds->peer = strsep(&data, ":");
03112    pds->port = data;
03113 
03114    /* check for a key name wrapped in [] in the secret position, if found,
03115       move it to the key field instead
03116    */
03117    if (pds->password && (pds->password[0] == '[')) {
03118       pds->key = ast_strip_quoted(pds->password, "[", "]");
03119       pds->password = NULL;
03120    }
03121 }

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

Referenced by load_module().

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

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

Definition at line 9566 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09567 {
09568    struct iax2_peer *peer = obj;
09569 
09570    ast_set_flag(peer, IAX_DELME);
09571 
09572    return 0;
09573 }

static void peer_destructor ( void *  obj  )  [static]

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

09090 {
09091    struct iax2_peer *peer = obj;
09092 
09093    ast_free_ha(peer->ha);
09094 
09095    if (peer->callno > 0) {
09096       ast_mutex_lock(&iaxsl[peer->callno]);
09097       iax2_destroy(peer->callno);
09098       ast_mutex_unlock(&iaxsl[peer->callno]);
09099    }
09100 
09101    register_peer_exten(peer, 0);
09102 
09103    if (peer->dnsmgr)
09104       ast_dnsmgr_release(peer->dnsmgr);
09105 
09106    ast_string_field_free_memory(peer);
09107 }

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

References ast_str_hash().

Referenced by load_module().

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

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

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

01134 {
01135    ao2_ref(peer, +1);
01136    return peer;
01137 }

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

Definition at line 10856 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

10857 {
10858    struct iax2_peer *peer = obj;
10859 
10860    if (peer->sockfd < 0)
10861       peer->sockfd = defaultsockfd;
10862 
10863    return 0;
10864 }

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

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

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

peer_status: Report Peer status in character string

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

02222 {
02223    int res = 0;
02224    if (peer->maxms) {
02225       if (peer->lastms < 0) {
02226          ast_copy_string(status, "UNREACHABLE", statuslen);
02227       } else if (peer->lastms > peer->maxms) {
02228          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02229          res = 1;
02230       } else if (peer->lastms) {
02231          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02232          res = 1;
02233       } else {
02234          ast_copy_string(status, "UNKNOWN", statuslen);
02235       }
02236    } else { 
02237       ast_copy_string(status, "Unmonitored", statuslen);
02238       res = -1;
02239    }
02240    return res;
02241 }

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

static void poke_all_peers ( void   )  [static]

Definition at line 10028 of file chan_iax2.c.

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

Referenced by reload_config().

10029 {
10030    struct ao2_iterator i;
10031    struct iax2_peer *peer;
10032 
10033    i = ao2_iterator_init(peers, 0);
10034    while ((peer = ao2_iterator_next(&i))) {
10035       iax2_poke_peer(peer, 0);
10036       peer_unref(peer);
10037    }
10038 }

static void prune_peers ( void   )  [static]

Definition at line 9625 of file chan_iax2.c.

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

09626 {
09627    struct iax2_peer *peer;
09628    struct ao2_iterator i;
09629 
09630    i = ao2_iterator_init(peers, 0);
09631    while ((peer = ao2_iterator_next(&i))) {
09632       if (ast_test_flag(peer, IAX_DELME))
09633          unlink_peer(peer);
09634       peer_unref(peer);
09635    }
09636 }

static void prune_users ( void   )  [static]

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

09612 {
09613    struct iax2_user *user;
09614    struct ao2_iterator i;
09615 
09616    i = ao2_iterator_init(users, 0);
09617    while ((user = ao2_iterator_next(&i))) {
09618       if (ast_test_flag(user, IAX_DELME))
09619          ao2_unlink(users, user);
09620       user_unref(user);
09621    }
09622 }

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

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

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

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

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

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

Definition at line 2889 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

02890 {
02891    char port[10];
02892    char regseconds[20];
02893    
02894    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
02895    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
02896    ast_update_realtime("iaxpeers", "name", peername, 
02897       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
02898       "regseconds", regseconds, NULL);
02899 }

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

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

static void reg_source_db ( struct iax2_peer p  )  [static]

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

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

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

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

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

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

Verify inbound registration.

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

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

static int registry_authrequest ( int  callno  )  [static]

Definition at line 6111 of file chan_iax2.c.

References AST_FRAME_IAX, 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_PLAINTEXT, 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, peer_unref(), iax_ie_data::pos, and send_command().

Referenced by socket_process().

06112 {
06113    struct iax_ie_data ied;
06114    struct iax2_peer *p;
06115    char challenge[10];
06116    const char *peer_name;
06117    int sentauthmethod;
06118 
06119    peer_name = ast_strdupa(iaxs[callno]->peer);
06120 
06121    /* SLD: third call to find_peer in registration */
06122    ast_mutex_unlock(&iaxsl[callno]);
06123    if ((p = find_peer(peer_name, 1))) {
06124       last_authmethod = p->authmethods;
06125    }
06126 
06127    ast_mutex_lock(&iaxsl[callno]);
06128    if (!iaxs[callno])
06129       goto return_unref;
06130 
06131    memset(&ied, 0, sizeof(ied));
06132    /* The selection of which delayed reject is sent may leak information,
06133     * if it sets a static response.  For example, if a host is known to only
06134     * use MD5 authentication, then an RSA response would indicate that the
06135     * peer does not exist, and vice-versa.
06136     * Therefore, we use whatever the last peer used (which may vary over the
06137     * course of a server, which should leak minimal information). */
06138    sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
06139    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
06140    if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06141       /* Build the challenge */
06142       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06143       ast_string_field_set(iaxs[callno], challenge, challenge);
06144       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06145    }
06146    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06147 
06148 return_unref:
06149    if (p) {
06150       peer_unref(p);
06151    }
06152 
06153    return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1;
06154 }

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

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

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

static char* regstate2str ( int  regstate  )  [static]

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

04604 {
04605    switch(regstate) {
04606    case REG_STATE_UNREGISTERED:
04607       return "Unregistered";
04608    case REG_STATE_REGSENT:
04609       return "Request Sent";
04610    case REG_STATE_AUTHSENT:
04611       return "Auth. Sent";
04612    case REG_STATE_REGISTERED:
04613       return "Registered";
04614    case REG_STATE_REJECTED:
04615       return "Rejected";
04616    case REG_STATE_TIMEOUT:
04617       return "Timeout";
04618    case REG_STATE_NOAUTH:
04619       return "No Authentication";
04620    default:
04621       return "Unknown";
04622    }
04623 }

static int reload ( void   )  [static]

Definition at line 10065 of file chan_iax2.c.

References reload_config().

10066 {
10067    return reload_config();
10068 }

static int reload_config ( void   )  [static]

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

10040 {
10041    char *config = "iax.conf";
10042    struct iax2_registry *reg;
10043 
10044    if (set_config(config, 1) > 0) {
10045       prune_peers();
10046       prune_users();
10047       AST_LIST_LOCK(&registrations);
10048       AST_LIST_TRAVERSE(&registrations, reg, entry)
10049          iax2_do_register(reg);
10050       AST_LIST_UNLOCK(&registrations);
10051       /* Qualify hosts, too */
10052       poke_all_peers();
10053    }
10054    reload_firmware(0);
10055    iax_provision_reload();
10056 
10057    return 0;
10058 }

static void reload_firmware ( int  unload  )  [static]

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

01758 {
01759    struct iax_firmware *cur, *curl, *curp;
01760    DIR *fwd;
01761    struct dirent *de;
01762    char dir[256];
01763    char fn[256];
01764    /* Mark all as dead */
01765    ast_mutex_lock(&waresl.lock);
01766    cur = waresl.wares;
01767    while(cur) {
01768       cur->dead = 1;
01769       cur = cur->next;
01770    }
01771 
01772    /* Now that we've freed them, load the new ones */
01773    if (!unload) {
01774       snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
01775       fwd = opendir(dir);
01776       if (fwd) {
01777          while((de = readdir(fwd))) {
01778             if (de->d_name[0] != '.') {
01779                snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
01780                if (!try_firmware(fn)) {
01781                   if (option_verbose > 1)
01782                      ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
01783                }
01784             }
01785          }
01786          closedir(fwd);
01787       } else 
01788          ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
01789    }
01790 
01791    /* Clean up leftovers */
01792    cur = waresl.wares;
01793    curp = NULL;
01794    while(cur) {
01795       curl = cur;
01796       cur = cur->next;
01797       if (curl->dead) {
01798          if (curp) {
01799             curp->next = cur;
01800          } else {
01801             waresl.wares = cur;
01802          }
01803          destroy_firmware(curl);
01804       } else {
01805          curp = cur;
01806       }
01807    }
01808    ast_mutex_unlock(&waresl.lock);
01809 }

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

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

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

08839 {
08840    int count;
08841    int res;
08842    struct timeval tv;
08843    struct timespec ts;
08844 
08845    for (;;) {
08846       res = ast_sched_wait(sched);
08847       if ((res > 1000) || (res < 0))
08848          res = 1000;
08849       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
08850       ts.tv_sec = tv.tv_sec;
08851       ts.tv_nsec = tv.tv_usec * 1000;
08852 
08853       pthread_testcancel();
08854       ast_mutex_lock(&sched_lock);
08855       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
08856       ast_mutex_unlock(&sched_lock);
08857       pthread_testcancel();
08858 
08859       count = ast_sched_runq(sched);
08860       if (option_debug && count >= 20)
08861          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
08862    }
08863    return NULL;
08864 }

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

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

static int send_apathetic_reply ( unsigned short  callno,
unsigned short  dcallno,
struct sockaddr_in *  sin,
int  command,
int  ts,
unsigned char  seqno 
) [static]

Definition at line 3056 of file chan_iax2.c.

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

Referenced by socket_process().

03057 {
03058    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03059       .ts = htonl(ts), .iseqno = seqno, .oseqno = 0, .type = AST_FRAME_IAX,
03060       .csub = compress_subclass(command) };
03061 
03062    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03063 }

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

04907 {
04908    int call_num = i->callno;
04909    /* It is assumed that the callno has already been locked */
04910    iax2_predestroy(i->callno);
04911    if (!iaxs[call_num])
04912       return -1;
04913    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
04914 }

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

References __send_command().

Referenced by iax2_vnak(), and socket_process().

04917 {
04918    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
04919 }

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

04893 {
04894    int res;
04895    ast_mutex_lock(&iaxsl[callno]);
04896    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
04897    ast_mutex_unlock(&iaxsl[callno]);
04898    return res;
04899 }

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

References __send_command().

Referenced by socket_process(), and try_transfer().

04922 {
04923    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
04924 }

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

Definition at line 1030 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

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

static int send_packet ( struct iax_frame f  )  [static]

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

01883 {
01884    int res;
01885    int callno = f->callno;
01886 
01887    /* Don't send if there was an error, but return error instead */
01888    if (!callno || !iaxs[callno] || iaxs[callno]->error)
01889        return -1;
01890    
01891    /* Called with iaxsl held */
01892    if (option_debug > 2 && iaxdebug)
01893       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));
01894    if (f->transfer) {
01895       if (iaxdebug)
01896          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
01897       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
01898                sizeof(iaxs[callno]->transfer));
01899    } else {
01900       if (iaxdebug)
01901          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
01902       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
01903                sizeof(iaxs[callno]->addr));
01904    }
01905    if (res < 0) {
01906       if (option_debug && iaxdebug)
01907          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01908       handle_error();
01909    } else
01910       res = 0;
01911    return res;
01912 }

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

Definition at line 995 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

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

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

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

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

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

Load configuration.

Definition at line 9669 of file chan_iax2.c.

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

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

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

static void set_config_destroy ( void   )  [static]

Definition at line 9653 of file chan_iax2.c.

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

Referenced by set_config().

09654 {
09655    strcpy(accountcode, "");
09656    strcpy(language, "");
09657    strcpy(mohinterpret, "default");
09658    strcpy(mohsuggest, "");
09659    amaflags = 0;
09660    delayreject = 0;
09661    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09662    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09663    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09664    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09665    delete_users();
09666 }

static void set_timing ( void   )  [static]

Definition at line 9638 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09639 {
09640 #ifdef HAVE_ZAPTEL
09641    int bs = trunkfreq * 8;
09642    if (timingfd > -1) {
09643       if (
09644 #ifdef ZT_TIMERACK
09645          ioctl(timingfd, ZT_TIMERCONFIG, &bs) &&
09646 #endif         
09647          ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs))
09648          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09649    }
09650 #endif
09651 }

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

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

00762 {
00763    ast_mutex_lock(lock);
00764    ast_cond_signal(cond);
00765    ast_mutex_unlock(lock);
00766 }

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 6809 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_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), iaxq, iaxs, iaxsl, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, iax_frame::iseqno, ast_iax2_full_hdr::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(), ast_iax2_full_hdr::scallno, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, spawn_dp_lookup(), ast_frame::src, chan_iax2_pvt::state, stop_stuff(), 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().

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

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

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

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

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

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

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

static int start_network_thread ( void   )  [static]

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

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

static void stop_stuff ( int  callno  )  [static]

Definition at line 6203 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06204 {
06205    iax2_destroy_helper(iaxs[callno]);
06206 }

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

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

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

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

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

01869 {
01870    int res;
01871    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
01872                sizeof(*sin));
01873    if (res < 0) {
01874       if (option_debug)
01875          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
01876       handle_error();
01877    } else
01878       res = 0;
01879    return res;
01880 }

static int try_firmware ( char *  s  )  [static]

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

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

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

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

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

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1059 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

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

static void unlink_peer ( struct iax2_peer peer  )  [static]

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

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

static int unload_module ( void   )  [static]

Definition at line 10850 of file chan_iax2.c.

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

10851 {
10852    ast_custom_function_unregister(&iaxpeer_function);
10853    return __unload_module();
10854 }

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

Definition at line 3369 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03370 {
03371    ast_mutex_unlock(&iaxsl[callno1]);
03372    ast_mutex_unlock(&iaxsl[callno0]);
03373 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

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

02411 {
02412    int x;
02413 
02414    if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) {
02415       x = fr->ts - iaxs[fr->callno]->last;
02416       if (x < -50000) {
02417          /* Sudden big jump backwards in timestamp:
02418             What likely happened here is that miniframe timestamp has circled but we haven't
02419             gotten the update from the main packet.  We'll just pretend that we did, and
02420             update the timestamp appropriately. */
02421          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF);
02422          if (option_debug && iaxdebug)
02423             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02424       }
02425       if (x > 50000) {
02426          /* Sudden apparent big jump forwards in timestamp:
02427             What's likely happened is this is an old miniframe belonging to the previous
02428             top-16-bit timestamp that has turned up out of order.
02429             Adjust the timestamp appropriately. */
02430          fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF);
02431          if (option_debug && iaxdebug)
02432             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02433       }
02434    }
02435 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

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

02440 {
02441    int when;
02442    
02443    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02444    
02445    when = jb_next(pvt->jb) - when;
02446    
02447    if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
02448    
02449    if(when <= 0) {
02450       /* XXX should really just empty until when > 0.. */
02451       when = 1;
02452    }
02453    
02454    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02455 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1279 of file chan_iax2.c.

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

Referenced by find_callno(), and make_trunk().

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

static void update_max_trunk ( void   )  [static]

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

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

static int update_packet ( struct iax_frame f  )  [static]

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

02048 {
02049    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02050    struct ast_iax2_full_hdr *fh = f->data;
02051    /* Mark this as a retransmission */
02052    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02053    /* Update iseqno */
02054    f->iseqno = iaxs[f->callno]->iseqno;
02055    fh->iseqno = f->iseqno;
02056    return 0;
02057 }

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

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

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

Referenced by load_module().

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

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

Definition at line 9575 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09576 {
09577    struct iax2_user *user = obj;
09578 
09579    ast_set_flag(user, IAX_DELME);
09580 
09581    return 0;
09582 }

static void user_destructor ( void *  obj  )  [static]

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

09340 {
09341    struct iax2_user *user = obj;
09342 
09343    ast_free_ha(user->ha);
09344    free_context(user->contexts);
09345    if(user->vars) {
09346       ast_variables_destroy(user->vars);
09347       user->vars = NULL;
09348    }
09349    ast_string_field_free_memory(user);
09350 }

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

References ast_str_hash().

Referenced by load_module().

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

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

Definition at line 1145 of file chan_iax2.c.

References ao2_ref().

01146 {
01147    ao2_ref(user, +1);
01148    return user;
01149 }

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

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

01152 {
01153    ao2_ref(user, -1);
01154    return NULL;
01155 }

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

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

06307 {
06308    struct iax_frame *f;
06309 
06310    AST_LIST_LOCK(&iaxq.queue);
06311    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06312       /* Send a copy immediately */
06313       if ((f->callno == callno) && iaxs[f->callno] &&
06314          ((unsigned char ) (f->oseqno - last) < 128) &&
06315          (f->retries >= 0)) {
06316          send_packet(f);
06317       }
06318    }
06319    AST_LIST_UNLOCK(&iaxq.queue);
06320 }


Variable Documentation

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

int adsi = 0 [static]

Definition at line 228 of file chan_iax2.c.

int amaflags = 0 [static]

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

Initial value:

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

Definition at line 10655 of file chan_iax2.c.

Initial value:

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

Definition at line 10665 of file chan_iax2.c.

Initial value:

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

Definition at line 10660 of file chan_iax2.c.

Initial value:

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

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

int defaultsockfd = -1 [static]

Definition at line 181 of file chan_iax2.c.

int delayreject = 0 [static]

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

struct ast_flags globalflags = { 0 } [static]

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 210 of file chan_iax2.c.

int iax2_encryption = 0 [static]

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

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

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

int iaxactivethreadcount = 0 [static]

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

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 168 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 170 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 458 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 457 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

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

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

int iaxtrunkdebug = 0 [static]

Definition at line 214 of file chan_iax2.c.

struct io_context* io [static]

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

int last_authmethod = 0 [static]

Definition at line 166 of file chan_iax2.c.

struct timeval lastused[IAX_MAX_CALLS] [static]

Definition at line 818 of file chan_iax2.c.

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

int max_reg_expire [static]

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

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 225 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

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

pthread_t netthreadid = AST_PTHREADT_NULL [static]

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

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 180 of file chan_iax2.c.

char* papp = "IAX2Provision" [static]

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

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

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

Definition at line 237 of file chan_iax2.c.

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 235 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 10549 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 10577 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 10595 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 10581 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 10553 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 10589 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10565 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 10599 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 10545 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 10585 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 10572 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 216 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 177 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 172 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 Fri Sep 25 19:28:25 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.5