Wed Feb 11 12:00:11 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 <sys/ioctl.h>
#include "asterisk/dahdi_compat.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  active_list
struct  ast_firmware_list
struct  ast_iax2_queue
struct  chan_iax2_pvt
struct  create_addr_info
struct  dpreq_data
struct  dynamic_list
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  idle_list
struct  parsed_dial_string
struct  registrations

Defines

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

Enumerations

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Inter Asterisk eXchange (Ver 2)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, }
static char accountcode [AST_MAX_ACCOUNT_CODE]
static int adsi = 0
static int amaflags = 0
static const struct ast_module_infoast_module_info = &__mod_info
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 ast_mutex_t dpcache_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static int global_rtautoclear = 120
static struct ast_flags globalflags = { 0 }
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH
static int iax2_encryption = 0
enum { ... }  iax2_flags
int(*) iax2_regfunk (const char *username, int onoff) = NULL
static char iax2_reload_usage []
enum { ... }  iax2_state
static struct ast_switch iax2_switch
static struct ast_channel_tech iax2_tech
static char iax2_test_losspct_usage []
static struct ao2_containeriax_peercallno_pvts
 Another container of iax2_pvt structures.
static int iaxactivethreadcount = 0
static int iaxcompat = 0
static int iaxdebug = 0
static int iaxdefaultdpcache = 10 * 60
static int iaxdefaulttimeout = 5
static int iaxdynamicthreadcount = 0
static int iaxdynamicthreadnum = 0
static int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT
ast_custom_function iaxpeer_function
static struct ast_iax2_queue iaxq
static struct chan_iax2_pvtiaxs [IAX_MAX_CALLS]
static ast_mutex_t iaxsl [ARRAY_LEN(iaxs)]
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct io_contextio
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static int last_authmethod = 0
static struct timeval lastused [ARRAY_LEN(iaxs)]
static int max_reg_expire
static int max_retries = 4
static int maxauthreq = 3
static int maxjitterbuffer = 1000
static int maxjitterinterps = 10
static int maxnontrunkcall = 1
static int maxtrunkcall = TRUNK_CALL_START
static int min_reg_expire
static char mohinterpret [MAX_MUSICCLASS]
static char mohsuggest [MAX_MUSICCLASS]
static struct ast_netsock_listnetsock
static pthread_t netthreadid = AST_PTHREADT_NULL
static char no_debug_jb_usage []
static char no_debug_trunk_usage []
static char no_debug_usage []
static struct ast_netsock_listoutsock
static char * papp = "IAX2Provision"
static char * pdescrip
static struct ao2_containerpeers
static int ping_time = 21
static struct ast_codec_pref prefs
static char prune_realtime_usage []
static char * psyn = "Provision a calling IAXy with a given template"
static char regcontext [AST_MAX_CONTEXT] = ""
static int resyncthreshold = 1000
static struct sched_contextsched
static ast_cond_t sched_cond
static ast_mutex_t sched_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
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 ast_mutex_t tpeerlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct iax2_trunk_peertpeers
static int trunkfreq = 20
static struct ao2_containerusers
static struct ast_firmware_list waresl


Detailed Description

Implementation of Inter-Asterisk eXchange Version 2.

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

Definition in file chan_iax2.c.


Define Documentation

#define CACHE_FLAG_CANEXIST   (1 << 2)

Extension can exist

Definition at line 664 of file chan_iax2.c.

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

#define CACHE_FLAG_EXISTS   (1 << 0)

Extension exists

Definition at line 660 of file chan_iax2.c.

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

#define CACHE_FLAG_MATCHMORE   (1 << 7)

Matchmore

Definition at line 674 of file chan_iax2.c.

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

#define CACHE_FLAG_NONEXISTENT   (1 << 1)

Extension is nonexistent

Definition at line 662 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

#define CACHE_FLAG_PENDING   (1 << 3)

Waiting to hear back response

Definition at line 666 of file chan_iax2.c.

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

#define CACHE_FLAG_TIMEOUT   (1 << 4)

Timed out

Definition at line 668 of file chan_iax2.c.

Referenced by find_cache(), and iax2_show_cache().

#define CACHE_FLAG_TRANSMITTED   (1 << 5)

Request transmitted

Definition at line 670 of file chan_iax2.c.

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

#define CACHE_FLAG_UNKNOWN   (1 << 6)

Timeout

Definition at line 672 of file chan_iax2.c.

Referenced by complete_dpreply(), and iax2_show_cache().

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

Definition at line 123 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 111 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 131 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 129 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

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

Referenced by build_peer(), and handle_response_peerpoke().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 126 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 195 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 127 of file chan_iax2.c.

Referenced by __find_callno(), and complete_transfer().

#define DEFAULT_THREAD_COUNT   10

Definition at line 125 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

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

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   0xFFFF

Definition at line 178 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 186 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 191 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Value:

Definition at line 180 of file chan_iax2.c.

Referenced by set_config().

#define IAX_IOSTATE_IDLE   0

Definition at line 695 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_PROCESSING   2

Definition at line 697 of file chan_iax2.c.

#define IAX_IOSTATE_READY   1

Definition at line 696 of file chan_iax2.c.

Referenced by socket_read().

#define IAX_IOSTATE_SCHEDREADY   3

Definition at line 698 of file chan_iax2.c.

Referenced by __schedule_action().

#define IAX_TYPE_DYNAMIC   2

Definition at line 701 of file chan_iax2.c.

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

#define IAX_TYPE_POOL   1

Definition at line 700 of file chan_iax2.c.

Referenced by start_network_thread().

#define IPTOS_MINCOST   0x02

Definition at line 114 of file chan_iax2.c.

#define MAX_JITTER_BUFFER   50

Definition at line 437 of file chan_iax2.c.

#define MAX_PEER_BUCKETS   1

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

Definition at line 646 of file chan_iax2.c.

Referenced by load_module(), and set_config().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 441 of file chan_iax2.c.

Referenced by iax2_trunk_queue(), and timing_read().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 651 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 128 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 438 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 434 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 133 of file chan_iax2.c.

Referenced by __find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1454 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

Definition at line 1455 of file chan_iax2.c.

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

#define NEW_PREVENT   0

Definition at line 1453 of file chan_iax2.c.

Referenced by socket_process().

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

Definition at line 122 of file chan_iax2.c.

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

#define SCHED_MULTITHREADED

Definition at line 107 of file chan_iax2.c.

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

Definition at line 982 of file chan_iax2.c.

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

#define TRUNK_CALL_START   ARRAY_LEN(iaxs) / 2

Definition at line 828 of file chan_iax2.c.

Referenced by __find_callno(), make_trunk(), update_max_nontrunk(), and update_max_trunk().

#define TS_GAP_FOR_JB_RESYNC   5000

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

00231      {
00232    IAX_STATE_STARTED =     (1 << 0),
00233    IAX_STATE_AUTHENTICATED =  (1 << 1),
00234    IAX_STATE_TBD =      (1 << 2),
00235    IAX_STATE_UNCHANGED =      (1 << 3),
00236 } 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 243 of file chan_iax2.c.

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

enum iax_reg_state

Enumerator:
REG_STATE_UNREGISTERED 
REG_STATE_REGSENT 
REG_STATE_AUTHSENT 
REG_STATE_REGISTERED 
REG_STATE_REJECTED 
REG_STATE_TIMEOUT 
REG_STATE_NOAUTH 

Definition at line 392 of file chan_iax2.c.

enum iax_transfer_state

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

Definition at line 402 of file chan_iax2.c.


Function Documentation

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

Definition at line 2213 of file chan_iax2.c.

References 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(), iax2_registry::callno, ast_iax2_queue::count, chan_iax2_pvt::error, f, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, ast_format::name, chan_iax2_pvt::owner, ast_iax2_queue::queue, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), send_packet(), ast_frame::subclass, update_packet(), and iax2_registry::us.

Referenced by attempt_transmit().

02214 {
02215    /* Attempt to transmit the frame to the remote peer...
02216       Called without iaxsl held. */
02217    struct iax_frame *f = (struct iax_frame *)data;
02218    int freeme=0;
02219    int callno = f->callno;
02220    /* Make sure this call is still active */
02221    if (callno) 
02222       ast_mutex_lock(&iaxsl[callno]);
02223    if (callno && iaxs[callno]) {
02224       if ((f->retries < 0) /* Already ACK'd */ ||
02225           (f->retries >= max_retries) /* Too many attempts */) {
02226             /* Record an error if we've transmitted too many times */
02227             if (f->retries >= max_retries) {
02228                if (f->transfer) {
02229                   /* Transfer timeout */
02230                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
02231                } else if (f->final) {
02232                   if (f->final) 
02233                      iax2_destroy(callno);
02234                } else {
02235                   if (iaxs[callno]->owner)
02236                      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);
02237                   iaxs[callno]->error = ETIMEDOUT;
02238                   if (iaxs[callno]->owner) {
02239                      struct ast_frame fr = { 0, };
02240                      /* Hangup the fd */
02241                      fr.frametype = AST_FRAME_CONTROL;
02242                      fr.subclass = AST_CONTROL_HANGUP;
02243                      iax2_queue_frame(callno, &fr); // XXX
02244                      /* Remember, owner could disappear */
02245                      if (iaxs[callno] && iaxs[callno]->owner)
02246                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
02247                   } else {
02248                      if (iaxs[callno]->reg) {
02249                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
02250                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
02251                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
02252                      }
02253                      iax2_destroy(callno);
02254                   }
02255                }
02256 
02257             }
02258             freeme++;
02259       } else {
02260          /* Update it if it needs it */
02261          update_packet(f);
02262          /* Attempt transmission */
02263          send_packet(f);
02264          f->retries++;
02265          /* Try again later after 10 times as long */
02266          f->retrytime *= 10;
02267          if (f->retrytime > MAX_RETRY_TIME)
02268             f->retrytime = MAX_RETRY_TIME;
02269          /* Transfer messages max out at one second */
02270          if (f->transfer && (f->retrytime > 1000))
02271             f->retrytime = 1000;
02272          f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
02273       }
02274    } else {
02275       /* Make sure it gets freed */
02276       f->retries = -1;
02277       freeme++;
02278    }
02279    if (callno)
02280       ast_mutex_unlock(&iaxsl[callno]);
02281    /* Do not try again */
02282    if (freeme) {
02283       /* Don't attempt delivery, just remove it from the queue */
02284       AST_LIST_LOCK(&iaxq.queue);
02285       AST_LIST_REMOVE(&iaxq.queue, f, list);
02286       iaxq.count--;
02287       AST_LIST_UNLOCK(&iaxq.queue);
02288       f->retrans = -1;
02289       /* Free the IAX frame */
02290       iax2_frame_free(f);
02291    }
02292 }

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

Definition at line 6476 of file chan_iax2.c.

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

Referenced by auth_reject().

06477 {
06478    /* Called from IAX thread only, without iaxs lock */
06479    int callno = (int)(long)(nothing);
06480    struct iax_ie_data ied;
06481    ast_mutex_lock(&iaxsl[callno]);
06482    if (iaxs[callno]) {
06483       memset(&ied, 0, sizeof(ied));
06484       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
06485          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
06486          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
06487       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
06488          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
06489          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
06490       }
06491       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
06492    }
06493    ast_mutex_unlock(&iaxsl[callno]);
06494 }

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

Definition at line 3174 of file chan_iax2.c.

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

Referenced by auto_congest().

03175 {
03176    int callno = PTR_TO_CALLNO(nothing);
03177    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03178    ast_mutex_lock(&iaxsl[callno]);
03179    if (iaxs[callno]) {
03180       iaxs[callno]->initid = -1;
03181       iax2_queue_frame(callno, &f);
03182       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03183    }
03184    ast_mutex_unlock(&iaxsl[callno]);
03185 }

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

Definition at line 6525 of file chan_iax2.c.

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

Referenced by auto_hangup().

06526 {
06527    /* Called from IAX thread only, without iaxs lock */
06528    int callno = (int)(long)(nothing);
06529    struct iax_ie_data ied;
06530    ast_mutex_lock(&iaxsl[callno]);
06531    if (iaxs[callno]) {
06532       memset(&ied, 0, sizeof(ied));
06533       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
06534       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
06535       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
06536    }
06537    ast_mutex_unlock(&iaxsl[callno]);
06538 }

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

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

Referenced by __get_from_jb(), and schedule_delivery().

02081 {
02082    /* Just deliver the packet by using queueing.  This is called by
02083      the IAX thread with the iaxsl lock held. */
02084    struct iax_frame *fr = data;
02085    fr->retrans = -1;
02086    ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
02087    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
02088       iax2_queue_frame(fr->callno, &fr->af);
02089    /* Free our iax frame */
02090    iax2_frame_free(fr);
02091    /* And don't run again */
02092    return 0;
02093 }

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

Definition at line 6158 of file chan_iax2.c.

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

Referenced by expire_registry().

06159 {
06160    struct iax2_peer *peer = (struct iax2_peer *) data;
06161 
06162    if (!peer)
06163       return;
06164 
06165    peer->expire = -1;
06166 
06167    if (option_debug)
06168       ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
06169    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
06170       realtime_update_peer(peer->name, &peer->addr, 0);
06171    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
06172    /* Reset the address */
06173    memset(&peer->addr, 0, sizeof(peer->addr));
06174    /* Reset expiry value */
06175    peer->expiry = min_reg_expire;
06176    if (!ast_test_flag(peer, IAX_TEMPONLY))
06177       ast_db_del("IAX/Registry", peer->name);
06178    register_peer_exten(peer, 0);
06179    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
06180    if (iax2_regfunk)
06181       iax2_regfunk(peer->name, 0);
06182 
06183    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
06184       unlink_peer(peer);
06185 
06186    peer_unref(peer);
06187 }

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

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

Definition at line 1544 of file chan_iax2.c.

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

Referenced by find_callno(), and find_callno_locked().

01545 {
01546    int res = 0;
01547    int x;
01548    struct timeval now;
01549    char host[80];
01550 
01551    if (new <= NEW_ALLOW) {
01552       if (callno) {
01553          struct chan_iax2_pvt *pvt;
01554          struct chan_iax2_pvt tmp_pvt = {
01555             .callno = dcallno,
01556             .peercallno = callno,
01557             /* hack!! */
01558             .frames_received = check_dcallno,
01559          };
01560  
01561          memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
01562  
01563          if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
01564             if (return_locked) {
01565                ast_mutex_lock(&iaxsl[pvt->callno]);
01566             }
01567             res = pvt->callno;
01568             ao2_ref(pvt, -1);
01569             pvt = NULL;
01570             return res;
01571          }
01572       }
01573 
01574       /* This will occur on the first response to a message that we initiated,
01575        * such as a PING. */
01576       if (dcallno) {
01577          ast_mutex_lock(&iaxsl[dcallno]);
01578       }
01579       if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) {
01580          iaxs[dcallno]->peercallno = callno;
01581          res = dcallno;
01582          store_by_peercallno(iaxs[dcallno]);
01583          if (!res || !return_locked) {
01584             ast_mutex_unlock(&iaxsl[dcallno]);
01585          }
01586          return res;
01587       }
01588       if (dcallno) {
01589          ast_mutex_unlock(&iaxsl[dcallno]);
01590       }
01591 
01592 #ifdef IAX_OLD_FIND
01593       /* If we get here, we SHOULD NOT find a call structure for this
01594          callno; if we do, it means that there is a call structure that
01595          has a peer callno but did NOT get entered into the hash table,
01596          which is bad.
01597 
01598          If we find a call structure using this old, slow method, output a log
01599          message so we'll know about it. After a few months of leaving this in
01600          place, if we don't hear about people seeing these messages, we can
01601          remove this code for good.
01602       */
01603 
01604       for (x = 1; !res && x < maxnontrunkcall; x++) {
01605          ast_mutex_lock(&iaxsl[x]);
01606          if (iaxs[x]) {
01607             /* Look for an exact match */
01608             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01609                res = x;
01610             }
01611          }
01612          if (!res || !return_locked)
01613             ast_mutex_unlock(&iaxsl[x]);
01614       }
01615 
01616       for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) {
01617          ast_mutex_lock(&iaxsl[x]);
01618          if (iaxs[x]) {
01619             /* Look for an exact match */
01620             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01621                res = x;
01622             }
01623          }
01624          if (!res || !return_locked)
01625             ast_mutex_unlock(&iaxsl[x]);
01626       }
01627 
01628       if (res) {
01629          ast_log(LOG_WARNING, "Old call search code found call number %d that was not in hash table!\n", res);
01630       }
01631 #endif
01632    }
01633    if (!res && (new >= NEW_ALLOW)) {
01634       int start, found = 0;
01635 
01636       /* It may seem odd that we look through the peer list for a name for
01637        * this *incoming* call.  Well, it is weird.  However, users don't
01638        * have an IP address/port number that we can match against.  So,
01639        * this is just checking for a peer that has that IP/port and
01640        * assuming that we have a user of the same name.  This isn't always
01641        * correct, but it will be changed if needed after authentication. */
01642       if (!iax2_getpeername(*sin, host, sizeof(host)))
01643          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01644 
01645       now = ast_tvnow();
01646       start = 2 + (ast_random() % (TRUNK_CALL_START - 1));
01647       for (x = start; 1; x++) {
01648          if (x == TRUNK_CALL_START) {
01649             x = 1;
01650             continue;
01651          }
01652 
01653          /* Find first unused call number that hasn't been used in a while */
01654          ast_mutex_lock(&iaxsl[x]);
01655          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01656             found = 1;
01657             break;
01658          }
01659          ast_mutex_unlock(&iaxsl[x]);
01660          
01661          if (x == start - 1) {
01662             break;
01663          }
01664       }
01665       /* We've still got lock held if we found a spot */
01666       if (x == start - 1 && !found) {
01667          ast_log(LOG_WARNING, "No more space\n");
01668          return 0;
01669       }
01670       iaxs[x] = new_iax(sin, host);
01671       update_max_nontrunk();
01672       if (iaxs[x]) {
01673          if (option_debug && iaxdebug)
01674             ast_log(LOG_DEBUG, "Creating new call structure %d\n", x);
01675          iaxs[x]->sockfd = sockfd;
01676          iaxs[x]->addr.sin_port = sin->sin_port;
01677          iaxs[x]->addr.sin_family = sin->sin_family;
01678          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01679          iaxs[x]->peercallno = callno;
01680          iaxs[x]->callno = x;
01681          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01682          iaxs[x]->expiry = min_reg_expire;
01683          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01684          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01685          iaxs[x]->amaflags = amaflags;
01686          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01687          
01688          ast_string_field_set(iaxs[x], accountcode, accountcode);
01689          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01690          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01691 
01692          if (iaxs[x]->peercallno) {
01693             store_by_peercallno(iaxs[x]);
01694          }
01695       } else {
01696          ast_log(LOG_WARNING, "Out of resources\n");
01697          ast_mutex_unlock(&iaxsl[x]);
01698          return 0;
01699       }
01700       if (!return_locked)
01701          ast_mutex_unlock(&iaxsl[x]);
01702       res = x;
01703    }
01704    return res;
01705 }

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

Definition at line 2616 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_samp2tv(), ast_test_flag, ast_tvadd(), ast_tvdiff_ms(), 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, iax2_registry::next, 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().

02617 {
02618    int callno = PTR_TO_CALLNO(p);
02619    struct chan_iax2_pvt *pvt = NULL;
02620    struct iax_frame *fr;
02621    jb_frame frame;
02622    int ret;
02623    long now;
02624    long next;
02625    struct timeval tv;
02626    
02627    /* Make sure we have a valid private structure before going on */
02628    ast_mutex_lock(&iaxsl[callno]);
02629    pvt = iaxs[callno];
02630    if (!pvt) {
02631       /* No go! */
02632       ast_mutex_unlock(&iaxsl[callno]);
02633       return;
02634    }
02635 
02636    pvt->jbid = -1;
02637    
02638    gettimeofday(&tv,NULL);
02639    /* round up a millisecond since ast_sched_runq does; */
02640    /* prevents us from spinning while waiting for our now */
02641    /* to catch up with runq's now */
02642    tv.tv_usec += 1000;
02643    
02644    now = ast_tvdiff_ms(tv, pvt->rxcore);
02645    
02646    if(now >= (next = jb_next(pvt->jb))) {
02647       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
02648       switch(ret) {
02649       case JB_OK:
02650          fr = frame.data;
02651          __do_deliver(fr);
02652          /* __do_deliver() can cause the call to disappear */
02653          pvt = iaxs[callno];
02654          break;
02655       case JB_INTERP:
02656       {
02657          struct ast_frame af = { 0, };
02658          
02659          /* create an interpolation frame */
02660          af.frametype = AST_FRAME_VOICE;
02661          af.subclass = pvt->voiceformat;
02662          af.samples  = frame.ms * 8;
02663          af.src  = "IAX2 JB interpolation";
02664          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
02665          af.offset = AST_FRIENDLY_OFFSET;
02666          
02667          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
02668           * which we'd need to malloc, and then it would free it.  That seems like a drag */
02669          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
02670             iax2_queue_frame(callno, &af);
02671             /* iax2_queue_frame() could cause the call to disappear */
02672             pvt = iaxs[callno];
02673          }
02674       }
02675          break;
02676       case JB_DROP:
02677          iax2_frame_free(frame.data);
02678          break;
02679       case JB_NOFRAME:
02680       case JB_EMPTY:
02681          /* do nothing */
02682          break;
02683       default:
02684          /* shouldn't happen */
02685          break;
02686       }
02687    }
02688    if (pvt)
02689       update_jbsched(pvt);
02690    ast_mutex_unlock(&iaxsl[callno]);
02691 }

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

Definition at line 5847 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

05848 {
05849    struct iax2_registry *reg = (struct iax2_registry *)data;
05850    reg->expire = -1;
05851    iax2_do_register(reg);
05852 }

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

Definition at line 8969 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(), iax2_peer::name, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, and sched.

Referenced by iax2_poke_noanswer().

08970 {
08971    struct iax2_peer *peer = (struct iax2_peer *)data;
08972    int callno;
08973 
08974    if (peer->lastms > -1) {
08975       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
08976       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
08977       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
08978    }
08979    if ((callno = peer->callno) > 0) {
08980       ast_mutex_lock(&iaxsl[callno]);
08981       iax2_destroy(callno);
08982       ast_mutex_unlock(&iaxsl[callno]);
08983    }
08984    peer->callno = 0;
08985    peer->lastms = -1;
08986    /* Try again quickly */
08987    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
08988    if (peer->pokeexpire == -1)
08989       peer_unref(peer);
08990 }

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

Definition at line 6588 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

06589 {
06590    struct iax2_peer *peer = (struct iax2_peer *)data;
06591    iax2_poke_peer(peer, 0);
06592    peer_unref(peer);
06593 }

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

Definition at line 4634 of file chan_iax2.c.

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

Referenced by iax2_show_peers(), and manager_iax2_show_peers().

04635 {
04636    regex_t regexbuf;
04637    int havepattern = 0;
04638    int total_peers = 0;
04639    int online_peers = 0;
04640    int offline_peers = 0;
04641    int unmonitored_peers = 0;
04642    struct ao2_iterator i;
04643 
04644 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
04645 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
04646 
04647    struct iax2_peer *peer = NULL;
04648    char name[256];
04649    int registeredonly=0;
04650    char *term = manager ? "\r\n" : "\n";
04651 
04652    switch (argc) {
04653    case 6:
04654       if (!strcasecmp(argv[3], "registered"))
04655          registeredonly = 1;
04656       else
04657          return RESULT_SHOWUSAGE;
04658       if (!strcasecmp(argv[4], "like")) {
04659          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
04660             return RESULT_SHOWUSAGE;
04661          havepattern = 1;
04662       } else
04663          return RESULT_SHOWUSAGE;
04664       break;
04665    case 5:
04666       if (!strcasecmp(argv[3], "like")) {
04667          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04668             return RESULT_SHOWUSAGE;
04669          havepattern = 1;
04670       } else
04671          return RESULT_SHOWUSAGE;
04672       break;
04673    case 4:
04674       if (!strcasecmp(argv[3], "registered"))
04675          registeredonly = 1;
04676       else
04677          return RESULT_SHOWUSAGE;
04678       break;
04679    case 3:
04680       break;
04681    default:
04682       return RESULT_SHOWUSAGE;
04683    }
04684 
04685 
04686    if (s)
04687       astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04688    else
04689       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
04690 
04691    i = ao2_iterator_init(peers, 0);
04692    for (peer = ao2_iterator_next(&i); peer; 
04693       peer_unref(peer), peer = ao2_iterator_next(&i)) {
04694       char nm[20];
04695       char status[20];
04696       char srch[2000];
04697       int retstatus;
04698 
04699       if (registeredonly && !peer->addr.sin_addr.s_addr)
04700          continue;
04701       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
04702          continue;
04703 
04704       if (!ast_strlen_zero(peer->username))
04705          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
04706       else
04707          ast_copy_string(name, peer->name, sizeof(name));
04708       
04709       retstatus = peer_status(peer, status, sizeof(status));
04710       if (retstatus > 0)
04711          online_peers++;
04712       else if (!retstatus)
04713          offline_peers++;
04714       else
04715          unmonitored_peers++;
04716       
04717       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
04718       
04719       snprintf(srch, sizeof(srch), FORMAT, name, 
04720           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04721           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04722           nm,
04723           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04724           peer->encmethods ? "(E)" : "   ", status, term);
04725       
04726       if (s)
04727          astman_append(s, FORMAT, name, 
04728                   peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)",
04729                   ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04730                   nm,
04731                   ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04732                   peer->encmethods ? "(E)" : "   ", status, term);
04733       else
04734          ast_cli(fd, FORMAT, name, 
04735             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
04736             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
04737             nm,
04738             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
04739             peer->encmethods ? "(E)" : "   ", status, term);
04740       total_peers++;
04741    }
04742 
04743    if (s)
04744       astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04745    else
04746       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
04747 
04748    if (havepattern)
04749       regfree(&regexbuf);
04750 
04751    return RESULT_SUCCESS;
04752 #undef FORMAT
04753 #undef FORMAT2
04754 }

static void __reg_module ( void   )  [static]

Definition at line 11337 of file chan_iax2.c.

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

Definition at line 957 of file chan_iax2.c.

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

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

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

Definition at line 5135 of file chan_iax2.c.

References f, and iax2_send().

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

05137 {
05138    struct ast_frame f = { 0, };
05139 
05140    f.frametype = type;
05141    f.subclass = command;
05142    f.datalen = datalen;
05143    f.src = __FUNCTION__;
05144    f.data = (void *) data;
05145 
05146    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05147 }

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

Definition at line 1042 of file chan_iax2.c.

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

Referenced by send_lagrq().

01043 {
01044    int callno = (long) data;
01045 
01046    ast_mutex_lock(&iaxsl[callno]);
01047 
01048    if (iaxs[callno]) {
01049       if (iaxs[callno]->peercallno) {
01050          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01051          iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01052       } else {
01053          /* I am the schedule, so I'm allowed to do this */
01054          iaxs[callno]->lagid = -1;
01055       }
01056    } else {
01057       ast_log(LOG_WARNING, "I was supposed to send a LAGRQ with callno %d, but no such call exists (and I cannot remove lagid, either).\n", callno);
01058    }
01059 
01060    ast_mutex_unlock(&iaxsl[callno]);
01061 }

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

Definition at line 997 of file chan_iax2.c.

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

Referenced by send_ping().

00998 {
00999    int callno = (long) data;
01000 
01001    ast_mutex_lock(&iaxsl[callno]);
01002 
01003    if (iaxs[callno]) {
01004       if (iaxs[callno]->peercallno) {
01005          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
01006          iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
01007       } else {
01008          /* I am the schedule, so I'm allowed to do this */
01009          iaxs[callno]->pingid = -1;
01010       }
01011    } else if (option_debug > 0) {
01012       ast_log(LOG_DEBUG, "I was supposed to send a PING with callno %d, but no such call exists (and I cannot remove pingid, either).\n", callno);
01013    }
01014 
01015    ast_mutex_unlock(&iaxsl[callno]);
01016 }

static int __unload_module ( void   )  [static]

Definition at line 11096 of file chan_iax2.c.

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

11097 {
11098    struct iax2_thread *thread = NULL;
11099    int x;
11100 
11101    /* Make sure threads do not hold shared resources when they are canceled */
11102    
11103    /* Grab the sched lock resource to keep it away from threads about to die */
11104    /* Cancel the network thread, close the net socket */
11105    if (netthreadid != AST_PTHREADT_NULL) {
11106       AST_LIST_LOCK(&iaxq.queue);
11107       ast_mutex_lock(&sched_lock);
11108       pthread_cancel(netthreadid);
11109       ast_cond_signal(&sched_cond);
11110       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
11111       AST_LIST_UNLOCK(&iaxq.queue);
11112       pthread_join(netthreadid, NULL);
11113    }
11114    if (schedthreadid != AST_PTHREADT_NULL) {
11115       ast_mutex_lock(&sched_lock);  
11116       pthread_cancel(schedthreadid);
11117       ast_cond_signal(&sched_cond);
11118       ast_mutex_unlock(&sched_lock);   
11119       pthread_join(schedthreadid, NULL);
11120    }
11121    
11122    /* Call for all threads to halt */
11123    AST_LIST_LOCK(&idle_list);
11124    AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
11125       AST_LIST_REMOVE_CURRENT(&idle_list, list);
11126       pthread_cancel(thread->threadid);
11127    }
11128    AST_LIST_TRAVERSE_SAFE_END
11129    AST_LIST_UNLOCK(&idle_list);
11130 
11131    AST_LIST_LOCK(&active_list);
11132    AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
11133       AST_LIST_REMOVE_CURRENT(&active_list, list);
11134       pthread_cancel(thread->threadid);
11135    }
11136    AST_LIST_TRAVERSE_SAFE_END
11137    AST_LIST_UNLOCK(&active_list);
11138 
11139    AST_LIST_LOCK(&dynamic_list);
11140         AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
11141       AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
11142       pthread_cancel(thread->threadid);
11143         }
11144    AST_LIST_TRAVERSE_SAFE_END
11145         AST_LIST_UNLOCK(&dynamic_list);
11146 
11147    AST_LIST_HEAD_DESTROY(&iaxq.queue);
11148 
11149    /* Wait for threads to exit */
11150    while(0 < iaxactivethreadcount)
11151       usleep(10000);
11152    
11153    ast_netsock_release(netsock);
11154    ast_netsock_release(outsock);
11155    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
11156       if (iaxs[x]) {
11157          iax2_destroy(x);
11158       }
11159    }
11160    ast_manager_unregister( "IAXpeers" );
11161    ast_manager_unregister( "IAXnetstats" );
11162    ast_unregister_application(papp);
11163    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11164    ast_unregister_switch(&iax2_switch);
11165    ast_channel_unregister(&iax2_tech);
11166    delete_users();
11167    iax_provision_unload();
11168    sched_context_destroy(sched);
11169    reload_firmware(1);
11170 
11171    ast_mutex_destroy(&waresl.lock);
11172 
11173    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11174       ast_mutex_destroy(&iaxsl[x]);
11175    }
11176 
11177    ao2_ref(peers, -1);
11178    ao2_ref(users, -1);
11179    ao2_ref(iax_peercallno_pvts, -1);
11180 
11181    return 0;
11182 }

static void __unreg_module ( void   )  [static]

Definition at line 11337 of file chan_iax2.c.

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

Definition at line 5188 of file chan_iax2.c.

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

Referenced by check_access().

05189 {
05190    while(con) {
05191       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05192          return -1;
05193       con = con->next;
05194    }
05195    return 0;
05196 }

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

Definition at line 4962 of file chan_iax2.c.

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

Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().

04963 {
04964    int x;
04965    int numchans = 0;
04966    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04967       ast_mutex_lock(&iaxsl[x]);
04968       if (iaxs[x]) {
04969          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
04970          char *fmt;
04971          jb_info jbinfo;
04972          
04973          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04974             jb_getinfo(iaxs[x]->jb, &jbinfo);
04975             localjitter = jbinfo.jitter;
04976             localdelay = jbinfo.current - jbinfo.min;
04977             locallost = jbinfo.frames_lost;
04978             locallosspct = jbinfo.losspct/1000;
04979             localdropped = jbinfo.frames_dropped;
04980             localooo = jbinfo.frames_ooo;
04981          } else {
04982             localjitter = -1;
04983             localdelay = 0;
04984             locallost = -1;
04985             locallosspct = -1;
04986             localdropped = 0;
04987             localooo = -1;
04988          }
04989          if (limit_fmt)
04990             fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n";
04991          else
04992             fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n";
04993          if (s)
04994             
04995             astman_append(s, fmt,
04996                      iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04997                      iaxs[x]->pingtime,
04998                      localjitter, 
04999                      localdelay,
05000                      locallost,
05001                      locallosspct,
05002                      localdropped,
05003                      localooo,
05004                      iaxs[x]->frames_received/1000,
05005                      iaxs[x]->remote_rr.jitter,
05006                      iaxs[x]->remote_rr.delay,
05007                      iaxs[x]->remote_rr.losscnt,
05008                      iaxs[x]->remote_rr.losspct,
05009                      iaxs[x]->remote_rr.dropped,
05010                      iaxs[x]->remote_rr.ooo,
05011                      iaxs[x]->remote_rr.packets/1000);
05012          else
05013             ast_cli(fd, fmt,
05014                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
05015                iaxs[x]->pingtime,
05016                localjitter, 
05017                localdelay,
05018                locallost,
05019                locallosspct,
05020                localdropped,
05021                localooo,
05022                iaxs[x]->frames_received/1000,
05023                iaxs[x]->remote_rr.jitter,
05024                iaxs[x]->remote_rr.delay,
05025                iaxs[x]->remote_rr.losscnt,
05026                iaxs[x]->remote_rr.losspct,
05027                iaxs[x]->remote_rr.dropped,
05028                iaxs[x]->remote_rr.ooo,
05029                iaxs[x]->remote_rr.packets/1000
05030                );
05031          numchans++;
05032       }
05033       ast_mutex_unlock(&iaxsl[x]);
05034    }
05035    return numchans;
05036 }

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

Create new call, interface with the PBX core.

Definition at line 3838 of file chan_iax2.c.

References chan_iax2_pvt::accountcode, chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, chan_iax2_pvt::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_channel_free(), ast_copy_string(), 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, chan_iax2_pvt::cid_name, chan_iax2_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, chan_iax2_pvt::context, chan_iax2_pvt::dnid, ast_channel::exten, chan_iax2_pvt::exten, chan_iax2_pvt::host, iax2_tech, iaxs, iaxsl, chan_iax2_pvt::language, 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::rawreadformat, ast_channel::rawwriteformat, chan_iax2_pvt::rdnis, 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().

03839 {
03840    struct ast_channel *tmp;
03841    struct chan_iax2_pvt *i;
03842    struct ast_variable *v = NULL;
03843 
03844    if (!(i = iaxs[callno])) {
03845       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
03846       return NULL;
03847    }
03848 
03849    /* Don't hold call lock */
03850    ast_mutex_unlock(&iaxsl[callno]);
03851    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);
03852    ast_mutex_lock(&iaxsl[callno]);
03853    if (i != iaxs[callno]) {
03854       if (tmp) {
03855          /* unlock and relock iaxsl[callno] to preserve locking order */
03856          ast_mutex_unlock(&iaxsl[callno]);
03857          ast_channel_free(tmp);
03858          ast_mutex_lock(&iaxsl[callno]);
03859       }
03860       return NULL;
03861    }
03862 
03863    if (!tmp)
03864       return NULL;
03865    tmp->tech = &iax2_tech;
03866    /* We can support any format by default, until we get restricted */
03867    tmp->nativeformats = capability;
03868    tmp->readformat = tmp->rawreadformat = ast_best_codec(capability);
03869    tmp->writeformat = tmp->rawwriteformat = ast_best_codec(capability);
03870    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
03871 
03872    /* Don't use ast_set_callerid() here because it will
03873     * generate a NewCallerID event before the NewChannel event */
03874    if (!ast_strlen_zero(i->ani))
03875       tmp->cid.cid_ani = ast_strdup(i->ani);
03876    else
03877       tmp->cid.cid_ani = ast_strdup(i->cid_num);
03878    tmp->cid.cid_dnid = ast_strdup(i->dnid);
03879    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
03880    tmp->cid.cid_pres = i->calling_pres;
03881    tmp->cid.cid_ton = i->calling_ton;
03882    tmp->cid.cid_tns = i->calling_tns;
03883    if (!ast_strlen_zero(i->language))
03884       ast_string_field_set(tmp, language, i->language);
03885    if (!ast_strlen_zero(i->accountcode))
03886       ast_string_field_set(tmp, accountcode, i->accountcode);
03887    if (i->amaflags)
03888       tmp->amaflags = i->amaflags;
03889    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
03890    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
03891    if (i->adsi)
03892       tmp->adsicpe = i->peeradsicpe;
03893    else
03894       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03895    i->owner = tmp;
03896    i->capability = capability;
03897 
03898    for (v = i->vars ; v ; v = v->next)
03899       pbx_builtin_setvar_helper(tmp, v->name, v->value);
03900 
03901    if (state != AST_STATE_DOWN) {
03902       if (ast_pbx_start(tmp)) {
03903          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03904          ast_hangup(tmp);
03905          i->owner = NULL;
03906          return NULL;
03907       }
03908    }
03909 
03910    ast_module_ref(ast_module_info->self);
03911    
03912    return tmp;
03913 }

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

Definition at line 2294 of file chan_iax2.c.

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02295 {
02296 #ifdef SCHED_MULTITHREADED
02297    if (schedule_action(__attempt_transmit, data))
02298 #endif      
02299       __attempt_transmit(data);
02300    return 0;
02301 }

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

Definition at line 6510 of file chan_iax2.c.

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

Referenced by socket_process().

06511 {
06512    /* Schedule sending the authentication failure in one second, to prevent
06513       guessing */
06514    if (iaxs[callno]) {
06515       iaxs[callno]->authfail = failcode;
06516       if (delayreject) {
06517          AST_SCHED_DEL(sched, iaxs[callno]->authid);
06518          iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno);
06519       } else
06520          auth_reject((void *)(long)callno);
06521    }
06522    return 0;
06523 }

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

Definition at line 6496 of file chan_iax2.c.

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

Referenced by auth_fail().

06497 {
06498    int callno = (int)(long)(data);
06499    ast_mutex_lock(&iaxsl[callno]);
06500    if (iaxs[callno])
06501       iaxs[callno]->authid = -1;
06502    ast_mutex_unlock(&iaxsl[callno]);
06503 #ifdef SCHED_MULTITHREADED
06504    if (schedule_action(__auth_reject, data))
06505 #endif      
06506       __auth_reject(data);
06507    return 0;
06508 }

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

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

05717 {
05718    int res = -1;
05719    int x;
05720    if (!ast_strlen_zero(keyn)) {
05721       if (!(authmethods & IAX_AUTH_RSA)) {
05722          if (ast_strlen_zero(secret)) 
05723             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));
05724       } else if (ast_strlen_zero(challenge)) {
05725          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
05726       } else {
05727          char sig[256];
05728          struct ast_key *key;
05729          key = ast_key_get(keyn, AST_KEY_PRIVATE);
05730          if (!key) {
05731             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
05732          } else {
05733             if (ast_sign(key, (char*)challenge, sig)) {
05734                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
05735                res = -1;
05736             } else {
05737                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
05738                res = 0;
05739             }
05740          }
05741       }
05742    } 
05743    /* Fall back */
05744    if (res && !ast_strlen_zero(secret)) {
05745       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
05746          struct MD5Context md5;
05747          unsigned char digest[16];
05748          char digres[128];
05749          MD5Init(&md5);
05750          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
05751          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
05752          MD5Final(digest, &md5);
05753          /* If they support md5, authenticate with it.  */
05754          for (x=0;x<16;x++)
05755             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
05756          if (ecx && dcx)
05757             build_enc_keys(digest, ecx, dcx);
05758          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
05759          res = 0;
05760       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
05761          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
05762          res = 0;
05763       } else
05764          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
05765    }
05766    return res;
05767 }

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

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

Referenced by socket_process().

05774 {
05775    struct iax2_peer *peer = NULL;
05776    /* Start pessimistic */
05777    int res = -1;
05778    int authmethods = 0;
05779    struct iax_ie_data ied;
05780    uint16_t callno = p->callno;
05781 
05782    memset(&ied, 0, sizeof(ied));
05783    
05784    if (ies->username)
05785       ast_string_field_set(p, username, ies->username);
05786    if (ies->challenge)
05787       ast_string_field_set(p, challenge, ies->challenge);
05788    if (ies->authmethods)
05789       authmethods = ies->authmethods;
05790    if (authmethods & IAX_AUTH_MD5)
05791       merge_encryption(p, ies->encmethods);
05792    else
05793       p->encmethods = 0;
05794 
05795    /* Check for override RSA authentication first */
05796    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
05797       /* Normal password authentication */
05798       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05799    } else {
05800       struct ao2_iterator i = ao2_iterator_init(peers, 0);
05801       while ((peer = ao2_iterator_next(&i))) {
05802          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
05803              /* No peer specified at our end, or this is the peer */
05804              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
05805              /* No username specified in peer rule, or this is the right username */
05806              && (!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)))
05807              /* No specified host, or this is our host */
05808             ) {
05809             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05810             if (!res) {
05811                peer_unref(peer);
05812                break;
05813             }
05814          }
05815          peer_unref(peer);
05816       }
05817       if (!peer) {
05818          /* We checked our list and didn't find one.  It's unlikely, but possible, 
05819             that we're trying to authenticate *to* a realtime peer */
05820          const char *peer_name = ast_strdupa(p->peer);
05821          ast_mutex_unlock(&iaxsl[callno]);
05822          if ((peer = realtime_peer(peer_name, NULL))) {
05823             ast_mutex_lock(&iaxsl[callno]);
05824             if (!(p = iaxs[callno])) {
05825                peer_unref(peer);
05826                return -1;
05827             }
05828             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
05829             peer_unref(peer);
05830          }
05831          if (!peer) {
05832             ast_mutex_lock(&iaxsl[callno]);
05833             if (!(p = iaxs[callno]))
05834                return -1;
05835          }
05836       }
05837    }
05838    if (ies->encmethods)
05839       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
05840    if (!res)
05841       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
05842    return res;
05843 }

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 5445 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, chan_iax2_pvt::challenge, iax2_user::curauthreq, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, iaxs, iax2_user::maxauthreq, send_command(), send_command_final(), user_unref(), and chan_iax2_pvt::username.

Referenced by socket_process().

05446 {
05447    struct iax_ie_data ied;
05448    int res = -1, authreq_restrict = 0;
05449    char challenge[10];
05450    struct chan_iax2_pvt *p = iaxs[call_num];
05451 
05452    memset(&ied, 0, sizeof(ied));
05453 
05454    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
05455    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05456       struct iax2_user *user, tmp_user = {
05457          .name = p->username, 
05458       };
05459 
05460       user = ao2_find(users, &tmp_user, OBJ_POINTER);
05461       if (user) {
05462          if (user->curauthreq == user->maxauthreq)
05463             authreq_restrict = 1;
05464          else
05465             user->curauthreq++;
05466          user = user_unref(user);
05467       }
05468    }
05469 
05470    /* If the AUTHREQ limit test failed, send back an error */
05471    if (authreq_restrict) {
05472       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
05473       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
05474       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
05475       return 0;
05476    }
05477 
05478    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
05479    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
05480       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
05481       ast_string_field_set(p, challenge, challenge);
05482       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
05483       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
05484    }
05485    if (p->encmethods)
05486       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
05487 
05488    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
05489 
05490    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
05491 
05492    if (p->encmethods)
05493       ast_set_flag(p, IAX_ENCRYPTED);
05494 
05495    return res;
05496 }

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

Definition at line 5498 of file chan_iax2.c.

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

Referenced by socket_process().

05499 {
05500    char requeststr[256];
05501    char md5secret[256] = "";
05502    char secret[256] = "";
05503    char rsasecret[256] = "";
05504    int res = -1; 
05505    int x;
05506    struct iax2_user *user, tmp_user = {
05507       .name = p->username, 
05508    };
05509 
05510    user = ao2_find(users, &tmp_user, OBJ_POINTER);
05511    if (user) {
05512       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
05513          ast_atomic_fetchadd_int(&user->curauthreq, -1);
05514          ast_clear_flag(p, IAX_MAXAUTHREQ);
05515       }
05516       ast_string_field_set(p, host, user->name);
05517       user = user_unref(user);
05518    }
05519 
05520    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
05521       return res;
05522    if (ies->password)
05523       ast_copy_string(secret, ies->password, sizeof(secret));
05524    if (ies->md5_result)
05525       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05526    if (ies->rsa_result)
05527       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05528    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
05529       struct ast_key *key;
05530       char *keyn;
05531       char tmpkey[256];
05532       char *stringp=NULL;
05533       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
05534       stringp=tmpkey;
05535       keyn = strsep(&stringp, ":");
05536       while(keyn) {
05537          key = ast_key_get(keyn, AST_KEY_PUBLIC);
05538          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
05539             res = 0;
05540             break;
05541          } else if (!key)
05542             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
05543          keyn = strsep(&stringp, ":");
05544       }
05545    } else if (p->authmethods & IAX_AUTH_MD5) {
05546       struct MD5Context md5;
05547       unsigned char digest[16];
05548       char *tmppw, *stringp;
05549       
05550       tmppw = ast_strdupa(p->secret);
05551       stringp = tmppw;
05552       while((tmppw = strsep(&stringp, ";"))) {
05553          MD5Init(&md5);
05554          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
05555          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05556          MD5Final(digest, &md5);
05557          /* If they support md5, authenticate with it.  */
05558          for (x=0;x<16;x++)
05559             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05560          if (!strcasecmp(requeststr, md5secret)) {
05561             res = 0;
05562             break;
05563          }
05564       }
05565    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
05566       if (!strcmp(secret, p->secret))
05567          res = 0;
05568    }
05569    return res;
05570 }

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

Definition at line 3187 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03188 {
03189 #ifdef SCHED_MULTITHREADED
03190    if (schedule_action(__auto_congest, data))
03191 #endif      
03192       __auto_congest(data);
03193    return 0;
03194 }

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

Definition at line 6540 of file chan_iax2.c.

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

Referenced by iax2_dprequest(), and iax2_provision().

06541 {
06542    int callno = (int)(long)(data);
06543    ast_mutex_lock(&iaxsl[callno]);
06544    if (iaxs[callno]) {
06545       iaxs[callno]->autoid = -1;
06546    }
06547    ast_mutex_unlock(&iaxsl[callno]);
06548 #ifdef SCHED_MULTITHREADED
06549    if (schedule_action(__auto_hangup, data))
06550 #endif      
06551       __auto_hangup(data);
06552    return 0;
06553 }

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

Definition at line 9289 of file chan_iax2.c.

References ast_calloc, and ast_copy_string().

Referenced by build_user().

09290 {
09291    struct iax2_context *con;
09292 
09293    if ((con = ast_calloc(1, sizeof(*con))))
09294       ast_copy_string(con->context, context, sizeof(con->context));
09295    
09296    return con;
09297 }

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

Definition at line 4220 of file chan_iax2.c.

References aes_decrypt_key128(), and aes_encrypt_key128().

Referenced by authenticate(), and decrypt_frame().

04221 {
04222    aes_encrypt_key128(digest, ecx);
04223    aes_decrypt_key128(digest, dcx);
04224 }

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

Create peer structure based on configuration.

Definition at line 9436 of file chan_iax2.c.

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

09437 {
09438    struct iax2_peer *peer = NULL;
09439    struct ast_ha *oldha = NULL;
09440    int maskfound=0;
09441    int found=0;
09442    int firstpass=1;
09443    struct iax2_peer tmp_peer = {
09444       .name = name,
09445    };
09446 
09447    if (!temponly) {
09448       peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
09449       if (peer && !ast_test_flag(peer, IAX_DELME))
09450          firstpass = 0;
09451    }
09452 
09453    if (peer) {
09454       found++;
09455       if (firstpass) {
09456          oldha = peer->ha;
09457          peer->ha = NULL;
09458       }
09459       unlink_peer(peer);
09460    } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
09461       peer->expire = -1;
09462       peer->pokeexpire = -1;
09463       peer->sockfd = defaultsockfd;
09464       if (ast_string_field_init(peer, 32))
09465          peer = peer_unref(peer);
09466    }
09467 
09468    if (peer) {
09469       if (firstpass) {
09470          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
09471          peer->encmethods = iax2_encryption;
09472          peer->adsi = adsi;
09473          ast_string_field_set(peer,secret,"");
09474          if (!found) {
09475             ast_string_field_set(peer, name, name);
09476             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09477             peer->expiry = min_reg_expire;
09478          }
09479          peer->prefs = prefs;
09480          peer->capability = iax2_capability;
09481          peer->smoothing = 0;
09482          peer->pokefreqok = DEFAULT_FREQ_OK;
09483          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
09484          ast_string_field_set(peer,context,"");
09485          ast_string_field_set(peer,peercontext,"");
09486          ast_clear_flag(peer, IAX_HASCALLERID);
09487          ast_string_field_set(peer, cid_name, "");
09488          ast_string_field_set(peer, cid_num, "");
09489       }
09490 
09491       if (!v) {
09492          v = alt;
09493          alt = NULL;
09494       }
09495       while(v) {
09496          if (!strcasecmp(v->name, "secret")) {
09497             ast_string_field_set(peer, secret, v->value);
09498          } else if (!strcasecmp(v->name, "mailbox")) {
09499             ast_string_field_set(peer, mailbox, v->value);
09500          } else if (!strcasecmp(v->name, "hasvoicemail")) {
09501             if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
09502                ast_string_field_set(peer, mailbox, name);
09503             }
09504          } else if (!strcasecmp(v->name, "mohinterpret")) {
09505             ast_string_field_set(peer, mohinterpret, v->value);
09506          } else if (!strcasecmp(v->name, "mohsuggest")) {
09507             ast_string_field_set(peer, mohsuggest, v->value);
09508          } else if (!strcasecmp(v->name, "dbsecret")) {
09509             ast_string_field_set(peer, dbsecret, v->value);
09510          } else if (!strcasecmp(v->name, "trunk")) {
09511             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
09512             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
09513                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without timing\n", peer->name);
09514                ast_clear_flag(peer, IAX_TRUNK);
09515             }
09516          } else if (!strcasecmp(v->name, "auth")) {
09517             peer->authmethods = get_auth_methods(v->value);
09518          } else if (!strcasecmp(v->name, "encryption")) {
09519             peer->encmethods = get_encrypt_methods(v->value);
09520          } else if (!strcasecmp(v->name, "notransfer")) {
09521             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09522             ast_clear_flag(peer, IAX_TRANSFERMEDIA);  
09523             ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 
09524          } else if (!strcasecmp(v->name, "transfer")) {
09525             if (!strcasecmp(v->value, "mediaonly")) {
09526                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09527             } else if (ast_true(v->value)) {
09528                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09529             } else 
09530                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09531          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09532             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
09533          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09534             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
09535          } else if (!strcasecmp(v->name, "host")) {
09536             if (!strcasecmp(v->value, "dynamic")) {
09537                /* They'll register with us */
09538                ast_set_flag(peer, IAX_DYNAMIC); 
09539                if (!found) {
09540                   /* Initialize stuff iff we're not found, otherwise
09541                      we keep going with what we had */
09542                   memset(&peer->addr.sin_addr, 0, 4);
09543                   if (peer->addr.sin_port) {
09544                      /* If we've already got a port, make it the default rather than absolute */
09545                      peer->defaddr.sin_port = peer->addr.sin_port;
09546                      peer->addr.sin_port = 0;
09547                   }
09548                }
09549             } else {
09550                /* Non-dynamic.  Make sure we become that way if we're not */
09551                AST_SCHED_DEL(sched, peer->expire);
09552                ast_clear_flag(peer, IAX_DYNAMIC);
09553                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr))
09554                   return peer_unref(peer);
09555                if (!peer->addr.sin_port)
09556                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
09557             }
09558             if (!maskfound)
09559                inet_aton("255.255.255.255", &peer->mask);
09560          } else if (!strcasecmp(v->name, "defaultip")) {
09561             if (ast_get_ip(&peer->defaddr, v->value))
09562                return peer_unref(peer);
09563          } else if (!strcasecmp(v->name, "sourceaddress")) {
09564             peer_set_srcaddr(peer, v->value);
09565          } else if (!strcasecmp(v->name, "permit") ||
09566                   !strcasecmp(v->name, "deny")) {
09567             peer->ha = ast_append_ha(v->name, v->value, peer->ha);
09568          } else if (!strcasecmp(v->name, "mask")) {
09569             maskfound++;
09570             inet_aton(v->value, &peer->mask);
09571          } else if (!strcasecmp(v->name, "context")) {
09572             ast_string_field_set(peer, context, v->value);
09573          } else if (!strcasecmp(v->name, "regexten")) {
09574             ast_string_field_set(peer, regexten, v->value);
09575          } else if (!strcasecmp(v->name, "peercontext")) {
09576             ast_string_field_set(peer, peercontext, v->value);
09577          } else if (!strcasecmp(v->name, "port")) {
09578             if (ast_test_flag(peer, IAX_DYNAMIC))
09579                peer->defaddr.sin_port = htons(atoi(v->value));
09580             else
09581                peer->addr.sin_port = htons(atoi(v->value));
09582          } else if (!strcasecmp(v->name, "username")) {
09583             ast_string_field_set(peer, username, v->value);
09584          } else if (!strcasecmp(v->name, "allow")) {
09585             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
09586          } else if (!strcasecmp(v->name, "disallow")) {
09587             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
09588          } else if (!strcasecmp(v->name, "callerid")) {
09589             if (!ast_strlen_zero(v->value)) {
09590                char name2[80];
09591                char num2[80];
09592                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
09593                ast_string_field_set(peer, cid_name, name2);
09594                ast_string_field_set(peer, cid_num, num2);
09595             } else {
09596                ast_string_field_set(peer, cid_name, "");
09597                ast_string_field_set(peer, cid_num, "");
09598             }
09599             ast_set_flag(peer, IAX_HASCALLERID);
09600          } else if (!strcasecmp(v->name, "fullname")) {
09601             ast_string_field_set(peer, cid_name, S_OR(v->value, ""));
09602             ast_set_flag(peer, IAX_HASCALLERID);
09603          } else if (!strcasecmp(v->name, "cid_number")) {
09604             ast_string_field_set(peer, cid_num, S_OR(v->value, ""));
09605             ast_set_flag(peer, IAX_HASCALLERID);
09606          } else if (!strcasecmp(v->name, "sendani")) {
09607             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
09608          } else if (!strcasecmp(v->name, "inkeys")) {
09609             ast_string_field_set(peer, inkeys, v->value);
09610          } else if (!strcasecmp(v->name, "outkey")) {
09611             ast_string_field_set(peer, outkey, v->value);
09612          } else if (!strcasecmp(v->name, "qualify")) {
09613             if (!strcasecmp(v->value, "no")) {
09614                peer->maxms = 0;
09615             } else if (!strcasecmp(v->value, "yes")) {
09616                peer->maxms = DEFAULT_MAXMS;
09617             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
09618                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);
09619                peer->maxms = 0;
09620             }
09621          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
09622             peer->smoothing = ast_true(v->value);
09623          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
09624             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
09625                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);
09626             }
09627          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
09628             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
09629                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);
09630             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
09631          } else if (!strcasecmp(v->name, "timezone")) {
09632             ast_string_field_set(peer, zonetag, v->value);
09633          } else if (!strcasecmp(v->name, "adsi")) {
09634             peer->adsi = ast_true(v->value);
09635          }/* else if (strcasecmp(v->name,"type")) */
09636          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09637          v = v->next;
09638          if (!v) {
09639             v = alt;
09640             alt = NULL;
09641          }
09642       }
09643       if (!peer->authmethods)
09644          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09645       ast_clear_flag(peer, IAX_DELME); 
09646       /* Make sure these are IPv4 addresses */
09647       peer->addr.sin_family = AF_INET;
09648    }
09649    if (oldha)
09650       ast_free_ha(oldha);
09651    return peer;
09652 }

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

Create in-memory user structure from configuration.

Definition at line 9668 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, iax2_user::cid_name, cid_name, iax2_user::cid_num, cid_num, cleanup(), iax2_user::contexts, iax2_user::curauthreq, iax2_user::dbsecret, iax2_user::encmethods, format, free_context(), get_auth_methods(), get_encrypt_methods(), globalflags, iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_user::inkeys, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, iax2_user::name, ast_variable::next, iax2_user::prefs, prefs, secret, iax2_user::secret, user_destructor(), user_unref(), ast_variable::value, and iax2_user::vars.

09669 {
09670    struct iax2_user *user = NULL;
09671    struct iax2_context *con, *conl = NULL;
09672    struct ast_ha *oldha = NULL;
09673    struct iax2_context *oldcon = NULL;
09674    int format;
09675    int firstpass=1;
09676    int oldcurauthreq = 0;
09677    char *varname = NULL, *varval = NULL;
09678    struct ast_variable *tmpvar = NULL;
09679    struct iax2_user tmp_user = {
09680       .name = name,
09681    };
09682 
09683    if (!temponly) {
09684       user = ao2_find(users, &tmp_user, OBJ_POINTER);
09685       if (user && !ast_test_flag(user, IAX_DELME))
09686          firstpass = 0;
09687    }
09688 
09689    if (user) {
09690       if (firstpass) {
09691          oldcurauthreq = user->curauthreq;
09692          oldha = user->ha;
09693          oldcon = user->contexts;
09694          user->ha = NULL;
09695          user->contexts = NULL;
09696       }
09697       /* Already in the list, remove it and it will be added back (or FREE'd) */
09698       ao2_unlink(users, user);
09699    } else {
09700       user = ao2_alloc(sizeof(*user), user_destructor);
09701    }
09702    
09703    if (user) {
09704       if (firstpass) {
09705          ast_string_field_free_memory(user);
09706          memset(user, 0, sizeof(struct iax2_user));
09707          if (ast_string_field_init(user, 32)) {
09708             user = user_unref(user);
09709             goto cleanup;
09710          }
09711          user->maxauthreq = maxauthreq;
09712          user->curauthreq = oldcurauthreq;
09713          user->prefs = prefs;
09714          user->capability = iax2_capability;
09715          user->encmethods = iax2_encryption;
09716          user->adsi = adsi;
09717          ast_string_field_set(user, name, name);
09718          ast_string_field_set(user, language, language);
09719          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
09720          ast_clear_flag(user, IAX_HASCALLERID);
09721          ast_string_field_set(user, cid_name, "");
09722          ast_string_field_set(user, cid_num, "");
09723       }
09724       if (!v) {
09725          v = alt;
09726          alt = NULL;
09727       }
09728       while(v) {
09729          if (!strcasecmp(v->name, "context")) {
09730             con = build_context(v->value);
09731             if (con) {
09732                if (conl)
09733                   conl->next = con;
09734                else
09735                   user->contexts = con;
09736                conl = con;
09737             }
09738          } else if (!strcasecmp(v->name, "permit") ||
09739                   !strcasecmp(v->name, "deny")) {
09740             user->ha = ast_append_ha(v->name, v->value, user->ha);
09741          } else if (!strcasecmp(v->name, "setvar")) {
09742             varname = ast_strdupa(v->value);
09743             if (varname && (varval = strchr(varname,'='))) {
09744                *varval = '\0';
09745                varval++;
09746                if((tmpvar = ast_variable_new(varname, varval))) {
09747                   tmpvar->next = user->vars; 
09748                   user->vars = tmpvar;
09749                }
09750             }
09751          } else if (!strcasecmp(v->name, "allow")) {
09752             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
09753          } else if (!strcasecmp(v->name, "disallow")) {
09754             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
09755          } else if (!strcasecmp(v->name, "trunk")) {
09756             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
09757             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
09758                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without timing\n", user->name);
09759                ast_clear_flag(user, IAX_TRUNK);
09760             }
09761          } else if (!strcasecmp(v->name, "auth")) {
09762             user->authmethods = get_auth_methods(v->value);
09763          } else if (!strcasecmp(v->name, "encryption")) {
09764             user->encmethods = get_encrypt_methods(v->value);
09765          } else if (!strcasecmp(v->name, "notransfer")) {
09766             ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
09767             ast_clear_flag(user, IAX_TRANSFERMEDIA);  
09768             ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 
09769          } else if (!strcasecmp(v->name, "transfer")) {
09770             if (!strcasecmp(v->value, "mediaonly")) {
09771                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
09772             } else if (ast_true(v->value)) {
09773                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
09774             } else 
09775                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
09776          } else if (!strcasecmp(v->name, "codecpriority")) {
09777             if(!strcasecmp(v->value, "caller"))
09778                ast_set_flag(user, IAX_CODEC_USER_FIRST);
09779             else if(!strcasecmp(v->value, "disabled"))
09780                ast_set_flag(user, IAX_CODEC_NOPREFS);
09781             else if(!strcasecmp(v->value, "reqonly")) {
09782                ast_set_flag(user, IAX_CODEC_NOCAP);
09783                ast_set_flag(user, IAX_CODEC_NOPREFS);
09784             }
09785          } else if (!strcasecmp(v->name, "jitterbuffer")) {
09786             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
09787          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
09788             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
09789          } else if (!strcasecmp(v->name, "dbsecret")) {
09790             ast_string_field_set(user, dbsecret, v->value);
09791          } else if (!strcasecmp(v->name, "secret")) {
09792             if (!ast_strlen_zero(user->secret)) {
09793                char *old = ast_strdupa(user->secret);
09794 
09795                ast_string_field_build(user, secret, "%s;%s", old, v->value);
09796             } else
09797                ast_string_field_set(user, secret, v->value);
09798          } else if (!strcasecmp(v->name, "callerid")) {
09799             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
09800                char name2[80];
09801                char num2[80];
09802                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
09803                ast_string_field_set(user, cid_name, name2);
09804                ast_string_field_set(user, cid_num, num2);
09805                ast_set_flag(user, IAX_HASCALLERID);
09806             } else {
09807                ast_clear_flag(user, IAX_HASCALLERID);
09808                ast_string_field_set(user, cid_name, "");
09809                ast_string_field_set(user, cid_num, "");
09810             }
09811          } else if (!strcasecmp(v->name, "fullname")) {
09812             if (!ast_strlen_zero(v->value)) {
09813                ast_string_field_set(user, cid_name, v->value);
09814                ast_set_flag(user, IAX_HASCALLERID);
09815             } else {
09816                ast_string_field_set(user, cid_name, "");
09817                if (ast_strlen_zero(user->cid_num))
09818                   ast_clear_flag(user, IAX_HASCALLERID);
09819             }
09820          } else if (!strcasecmp(v->name, "cid_number")) {
09821             if (!ast_strlen_zero(v->value)) {
09822                ast_string_field_set(user, cid_num, v->value);
09823                ast_set_flag(user, IAX_HASCALLERID);
09824             } else {
09825                ast_string_field_set(user, cid_num, "");
09826                if (ast_strlen_zero(user->cid_name))
09827                   ast_clear_flag(user, IAX_HASCALLERID);
09828             }
09829          } else if (!strcasecmp(v->name, "accountcode")) {
09830             ast_string_field_set(user, accountcode, v->value);
09831          } else if (!strcasecmp(v->name, "mohinterpret")) {
09832             ast_string_field_set(user, mohinterpret, v->value);
09833          } else if (!strcasecmp(v->name, "mohsuggest")) {
09834             ast_string_field_set(user, mohsuggest, v->value);
09835          } else if (!strcasecmp(v->name, "language")) {
09836             ast_string_field_set(user, language, v->value);
09837          } else if (!strcasecmp(v->name, "amaflags")) {
09838             format = ast_cdr_amaflags2int(v->value);
09839             if (format < 0) {
09840                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
09841             } else {
09842                user->amaflags = format;
09843             }
09844          } else if (!strcasecmp(v->name, "inkeys")) {
09845             ast_string_field_set(user, inkeys, v->value);
09846          } else if (!strcasecmp(v->name, "maxauthreq")) {
09847             user->maxauthreq = atoi(v->value);
09848             if (user->maxauthreq < 0)
09849                user->maxauthreq = 0;
09850          } else if (!strcasecmp(v->name, "adsi")) {
09851             user->adsi = ast_true(v->value);
09852          }/* else if (strcasecmp(v->name,"type")) */
09853          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
09854          v = v->next;
09855          if (!v) {
09856             v = alt;
09857             alt = NULL;
09858          }
09859       }
09860       if (!user->authmethods) {
09861          if (!ast_strlen_zero(user->secret)) {
09862             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09863             if (!ast_strlen_zero(user->inkeys))
09864                user->authmethods |= IAX_AUTH_RSA;
09865          } else if (!ast_strlen_zero(user->inkeys)) {
09866             user->authmethods = IAX_AUTH_RSA;
09867          } else {
09868             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
09869          }
09870       }
09871       ast_clear_flag(user, IAX_DELME);
09872    }
09873 cleanup:
09874    if (oldha)
09875       ast_free_ha(oldha);
09876    if (oldcon)
09877       free_context(oldcon);
09878    return user;
09879 }

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

Definition at line 10385 of file chan_iax2.c.

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

Referenced by find_cache().

10386 {
10387    struct sockaddr_in sin;
10388    int x;
10389    int callno;
10390    struct iax_ie_data ied;
10391    struct create_addr_info cai;
10392    struct parsed_dial_string pds;
10393    char *tmpstr;
10394 
10395    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
10396       /* Look for an *exact match* call.  Once a call is negotiated, it can only
10397          look up entries for a single context */
10398       if (!ast_mutex_trylock(&iaxsl[x])) {
10399          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
10400             return x;
10401          ast_mutex_unlock(&iaxsl[x]);
10402       }
10403    }
10404 
10405    /* No match found, we need to create a new one */
10406 
10407    memset(&cai, 0, sizeof(cai));
10408    memset(&ied, 0, sizeof(ied));
10409    memset(&pds, 0, sizeof(pds));
10410 
10411    tmpstr = ast_strdupa(data);
10412    parse_dial_string(tmpstr, &pds);
10413 
10414    if (ast_strlen_zero(pds.peer)) {
10415       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
10416       return -1;
10417    }
10418 
10419    /* Populate our address from the given */
10420    if (create_addr(pds.peer, NULL, &sin, &cai))
10421       return -1;
10422 
10423    if (option_debug)
10424       ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
10425          pds.peer, pds.username, pds.password, pds.context);
10426 
10427    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10428    if (callno < 1) {
10429       ast_log(LOG_WARNING, "Unable to create call\n");
10430       return -1;
10431    }
10432 
10433    ast_string_field_set(iaxs[callno], dproot, data);
10434    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
10435 
10436    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
10437    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
10438    /* the string format is slightly different from a standard dial string,
10439       because the context appears in the 'exten' position
10440    */
10441    if (pds.exten)
10442       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
10443    if (pds.username)
10444       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
10445    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
10446    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
10447    /* Keep password handy */
10448    if (pds.password)
10449       ast_string_field_set(iaxs[callno], secret, pds.password);
10450    if (pds.key)
10451       ast_string_field_set(iaxs[callno], outkey, pds.key);
10452    /* Start the call going */
10453    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
10454 
10455    return callno;
10456 }

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

Definition at line 4088 of file chan_iax2.c.

References ast_log(), ast_random(), ast_samp2tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), chan_iax2_pvt::callno, option_debug, and chan_iax2_pvt::rxcore.

04089 {
04090    /* Returns where in "receive time" we are.  That is, how many ms
04091       since we received (or would have received) the frame with timestamp 0 */
04092    int ms;
04093 #ifdef IAXTESTS
04094    int jit;
04095 #endif /* IAXTESTS */
04096    /* Setup rxcore if necessary */
04097    if (ast_tvzero(p->rxcore)) {
04098       p->rxcore = ast_tvnow();
04099       if (option_debug && iaxdebug)
04100          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
04101                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
04102       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
04103 #if 1
04104       if (option_debug && iaxdebug)
04105          ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
04106                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
04107 #endif
04108    }
04109 
04110    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
04111 #ifdef IAXTESTS
04112    if (test_jit) {
04113       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
04114          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
04115          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
04116             jit = -jit;
04117          ms += jit;
04118       }
04119    }
04120    if (test_late) {
04121       ms += test_late;
04122       test_late = 0;
04123    }
04124 #endif /* IAXTESTS */
04125    return ms;
04126 }

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

Definition at line 3959 of file chan_iax2.c.

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

Referenced by iax2_send(), and socket_process().

03960 {
03961    int ms;
03962    int voice = 0;
03963    int genuine = 0;
03964    int adjust;
03965    struct timeval *delivery = NULL;
03966 
03967 
03968    /* What sort of frame do we have?: voice is self-explanatory
03969       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
03970       non-genuine frames are CONTROL frames [ringing etc], DTMF
03971       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
03972       the others need a timestamp slaved to the voice frames so that they go in sequence
03973    */
03974    if (f) {
03975       if (f->frametype == AST_FRAME_VOICE) {
03976          voice = 1;
03977          delivery = &f->delivery;
03978       } else if (f->frametype == AST_FRAME_IAX) {
03979          genuine = 1;
03980       } else if (f->frametype == AST_FRAME_CNG) {
03981          p->notsilenttx = 0;  
03982       }
03983    }
03984    if (ast_tvzero(p->offset)) {
03985       gettimeofday(&p->offset, NULL);
03986       /* Round to nearest 20ms for nice looking traces */
03987       p->offset.tv_usec -= p->offset.tv_usec % 20000;
03988    }
03989    /* If the timestamp is specified, just send it as is */
03990    if (ts)
03991       return ts;
03992    /* If we have a time that the frame arrived, always use it to make our timestamp */
03993    if (delivery && !ast_tvzero(*delivery)) {
03994       ms = ast_tvdiff_ms(*delivery, p->offset);
03995       if (option_debug > 2 && iaxdebug)
03996          ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
03997    } else {
03998       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
03999       if (ms < 0)
04000          ms = 0;
04001       if (voice) {
04002          /* On a voice frame, use predicted values if appropriate */
04003          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
04004             /* Adjust our txcore, keeping voice and non-voice synchronized */
04005             /* AN EXPLANATION:
04006                When we send voice, we usually send "calculated" timestamps worked out
04007                on the basis of the number of samples sent. When we send other frames,
04008                we usually send timestamps worked out from the real clock.
04009                The problem is that they can tend to drift out of step because the 
04010                   source channel's clock and our clock may not be exactly at the same rate.
04011                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
04012                for this call.  Moving it adjusts timestamps for non-voice frames.
04013                We make the adjustment in the style of a moving average.  Each time we
04014                adjust p->offset by 10% of the difference between our clock-derived
04015                timestamp and the predicted timestamp.  That's why you see "10000"
04016                below even though IAX2 timestamps are in milliseconds.
04017                The use of a moving average avoids offset moving too radically.
04018                Generally, "adjust" roams back and forth around 0, with offset hardly
04019                changing at all.  But if a consistent different starts to develop it
04020                will be eliminated over the course of 10 frames (200-300msecs) 
04021             */
04022             adjust = (ms - p->nextpred);
04023             if (adjust < 0)
04024                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
04025             else if (adjust > 0)
04026                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
04027 
04028             if (!p->nextpred) {
04029                p->nextpred = ms; /*f->samples / 8;*/
04030                if (p->nextpred <= p->lastsent)
04031                   p->nextpred = p->lastsent + 3;
04032             }
04033             ms = p->nextpred;
04034          } else {
04035                 /* in this case, just use the actual
04036             * time, since we're either way off
04037             * (shouldn't happen), or we're  ending a
04038             * silent period -- and seed the next
04039             * predicted time.  Also, round ms to the
04040             * next multiple of frame size (so our
04041             * silent periods are multiples of
04042             * frame size too) */
04043 
04044             if (option_debug && iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
04045                ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
04046                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
04047 
04048             if (f->samples >= 8) /* check to make sure we dont core dump */
04049             {
04050                int diff = ms % (f->samples / 8);
04051                if (diff)
04052                    ms += f->samples/8 - diff;
04053             }
04054 
04055             p->nextpred = ms;
04056             p->notsilenttx = 1;
04057          }
04058       } else if ( f->frametype == AST_FRAME_VIDEO ) {
04059          /*
04060          * IAX2 draft 03 says that timestamps MUST be in order.
04061          * It does not say anything about several frames having the same timestamp
04062          * When transporting video, we can have a frame that spans multiple iax packets
04063          * (so called slices), so it would make sense to use the same timestamp for all of
04064          * them
04065          * We do want to make sure that frames don't go backwards though
04066          */
04067          if ( (unsigned int)ms < p->lastsent )
04068             ms = p->lastsent;
04069       } else {
04070          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
04071             it's a genuine frame */
04072          if (genuine) {
04073             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
04074             if (ms <= p->lastsent)
04075                ms = p->lastsent + 3;
04076          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
04077             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
04078             ms = p->lastsent + 3;
04079          }
04080       }
04081    }
04082    p->lastsent = ms;
04083    if (voice)
04084       p->nextpred = p->nextpred + f->samples / 8;
04085    return ms;
04086 }

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

Definition at line 3915 of file chan_iax2.c.

References ast_tvdiff_ms(), ast_tvzero(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lasttxtime, MAX_TIMESTAMP_SKEW, iax2_trunk_peer::trunkact, and iax2_trunk_peer::txtrunktime.

Referenced by send_trunk().

03916 {
03917    unsigned long int mssincetx; /* unsigned to handle overflows */
03918    long int ms, pred;
03919 
03920    tpeer->trunkact = *tv;
03921    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
03922    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
03923       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
03924       tpeer->txtrunktime = *tv;
03925       tpeer->lastsent = 999999;
03926    }
03927    /* Update last transmit time now */
03928    tpeer->lasttxtime = *tv;
03929    
03930    /* Calculate ms offset */
03931    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
03932    /* Predict from last value */
03933    pred = tpeer->lastsent + sampms;
03934    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
03935       ms = pred;
03936    
03937    /* We never send the same timestamp twice, so fudge a little if we must */
03938    if (ms == tpeer->lastsent)
03939       ms = tpeer->lastsent + 1;
03940    tpeer->lastsent = ms;
03941    return ms;
03942 }

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

Definition at line 5199 of file chan_iax2.c.

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

Referenced by socket_process().

05200 {
05201    /* Start pessimistic */
05202    int res = -1;
05203    int version = 2;
05204    struct iax2_user *user = NULL, *best = NULL;
05205    int bestscore = 0;
05206    int gotcapability = 0;
05207    struct ast_variable *v = NULL, *tmpvar = NULL;
05208    struct ao2_iterator i;
05209 
05210    if (!iaxs[callno])
05211       return res;
05212    if (ies->called_number)
05213       ast_string_field_set(iaxs[callno], exten, ies->called_number);
05214    if (ies->calling_number) {
05215       ast_shrink_phone_number(ies->calling_number);
05216       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
05217    }
05218    if (ies->calling_name)
05219       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
05220    if (ies->calling_ani)
05221       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
05222    if (ies->dnid)
05223       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
05224    if (ies->rdnis)
05225       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
05226    if (ies->called_context)
05227       ast_string_field_set(iaxs[callno], context, ies->called_context);
05228    if (ies->language)
05229       ast_string_field_set(iaxs[callno], language, ies->language);
05230    if (ies->username)
05231       ast_string_field_set(iaxs[callno], username, ies->username);
05232    if (ies->calling_ton > -1)
05233       iaxs[callno]->calling_ton = ies->calling_ton;
05234    if (ies->calling_tns > -1)
05235       iaxs[callno]->calling_tns = ies->calling_tns;
05236    if (ies->calling_pres > -1)
05237       iaxs[callno]->calling_pres = ies->calling_pres;
05238    if (ies->format)
05239       iaxs[callno]->peerformat = ies->format;
05240    if (ies->adsicpe)
05241       iaxs[callno]->peeradsicpe = ies->adsicpe;
05242    if (ies->capability) {
05243       gotcapability = 1;
05244       iaxs[callno]->peercapability = ies->capability;
05245    } 
05246    if (ies->version)
05247       version = ies->version;
05248 
05249    /* Use provided preferences until told otherwise for actual preferences */
05250    if(ies->codec_prefs) {
05251       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
05252       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
05253    }
05254 
05255    if (!gotcapability) 
05256       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
05257    if (version > IAX_PROTO_VERSION) {
05258       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
05259          ast_inet_ntoa(sin->sin_addr), version);
05260       return res;
05261    }
05262    /* Search the userlist for a compatible entry, and fill in the rest */
05263    i = ao2_iterator_init(users, 0);
05264    while ((user = ao2_iterator_next(&i))) {
05265       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
05266          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
05267          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
05268          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
05269               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
05270          if (!ast_strlen_zero(iaxs[callno]->username)) {
05271             /* Exact match, stop right now. */
05272             if (best)
05273                user_unref(best);
05274             best = user;
05275             break;
05276          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) {
05277             /* No required authentication */
05278             if (user->ha) {
05279                /* There was host authentication and we passed, bonus! */
05280                if (bestscore < 4) {
05281                   bestscore = 4;
05282                   if (best)
05283                      user_unref(best);
05284                   best = user;
05285                   continue;
05286                }
05287             } else {
05288                /* No host access, but no secret, either, not bad */
05289                if (bestscore < 3) {
05290                   bestscore = 3;
05291                   if (best)
05292                      user_unref(best);
05293                   best = user;
05294                   continue;
05295                }
05296             }
05297          } else {
05298             if (user->ha) {
05299                /* Authentication, but host access too, eh, it's something.. */
05300                if (bestscore < 2) {
05301                   bestscore = 2;
05302                   if (best)
05303                      user_unref(best);
05304                   best = user;
05305                   continue;
05306                }
05307             } else {
05308                /* Authentication and no host access...  This is our baseline */
05309                if (bestscore < 1) {
05310                   bestscore = 1;
05311                   if (best)
05312                      user_unref(best);
05313                   best = user;
05314                   continue;
05315                }
05316             }
05317          }
05318       }
05319       user_unref(user);
05320    }
05321    user = best;
05322    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
05323       user = realtime_user(iaxs[callno]->username, sin);
05324       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
05325           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
05326          user = user_unref(user);
05327       }
05328    }
05329    if (user) {
05330       /* We found our match (use the first) */
05331       /* copy vars */
05332       for (v = user->vars ; v ; v = v->next) {
05333          if((tmpvar = ast_variable_new(v->name, v->value))) {
05334             tmpvar->next = iaxs[callno]->vars; 
05335             iaxs[callno]->vars = tmpvar;
05336          }
05337       }
05338       /* If a max AUTHREQ restriction is in place, activate it */
05339       if (user->maxauthreq > 0)
05340          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
05341       iaxs[callno]->prefs = user->prefs;
05342       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
05343       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
05344       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
05345       iaxs[callno]->encmethods = user->encmethods;
05346       /* Store the requested username if not specified */
05347       if (ast_strlen_zero(iaxs[callno]->username))
05348          ast_string_field_set(iaxs[callno], username, user->name);
05349       /* Store whether this is a trunked call, too, of course, and move if appropriate */
05350       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
05351       iaxs[callno]->capability = user->capability;
05352       /* And use the default context */
05353       if (ast_strlen_zero(iaxs[callno]->context)) {
05354          if (user->contexts)
05355             ast_string_field_set(iaxs[callno], context, user->contexts->context);
05356          else
05357             ast_string_field_set(iaxs[callno], context, context);
05358       }
05359       /* And any input keys */
05360       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
05361       /* And the permitted authentication methods */
05362       iaxs[callno]->authmethods = user->authmethods;
05363       iaxs[callno]->adsi = user->adsi;
05364       /* If the user has callerid, override the remote caller id. */
05365       if (ast_test_flag(user, IAX_HASCALLERID)) {
05366          iaxs[callno]->calling_tns = 0;
05367          iaxs[callno]->calling_ton = 0;
05368          ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
05369          ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
05370          ast_string_field_set(iaxs[callno], ani, user->cid_num);
05371          iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
05372       } else if (ast_strlen_zero(iaxs[callno]->cid_num) && ast_strlen_zero(iaxs[callno]->cid_name)) {
05373          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
05374       } /* else user is allowed to set their own CID settings */
05375       if (!ast_strlen_zero(user->accountcode))
05376          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
05377       if (!ast_strlen_zero(user->mohinterpret))
05378          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
05379       if (!ast_strlen_zero(user->mohsuggest))
05380          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
05381       if (user->amaflags)
05382          iaxs[callno]->amaflags = user->amaflags;
05383       if (!ast_strlen_zero(user->language))
05384          ast_string_field_set(iaxs[callno], language, user->language);
05385       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
05386       /* Keep this check last */
05387       if (!ast_strlen_zero(user->dbsecret)) {
05388          char *family, *key=NULL;
05389          char buf[80];
05390          family = ast_strdupa(user->dbsecret);
05391          key = strchr(family, '/');
05392          if (key) {
05393             *key = '\0';
05394             key++;
05395          }
05396          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
05397             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
05398          else
05399             ast_string_field_set(iaxs[callno], secret, buf);
05400       } else
05401          ast_string_field_set(iaxs[callno], secret, user->secret);
05402       res = 0;
05403       user = user_unref(user);
05404    }
05405    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
05406    return res;
05407 }

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

Definition at line 6898 of file chan_iax2.c.

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

Referenced by socket_process().

06899 {
06900    unsigned int ourver;
06901    char rsi[80];
06902    snprintf(rsi, sizeof(rsi), "si-%s", si);
06903    if (iax_provision_version(&ourver, rsi, 1))
06904       return 0;
06905    if (option_debug)
06906       ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
06907    if (ourver != ver) 
06908       iax2_provision(sin, sockfd, NULL, rsi, 1);
06909    return 0;
06910 }

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

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

Referenced by peer_set_srcaddr().

09316 {
09317    int sd;
09318    int res;
09319    
09320    sd = socket(AF_INET, SOCK_DGRAM, 0);
09321    if (sd < 0) {
09322       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
09323       return -1;
09324    }
09325 
09326    res = bind(sd, sa, salen);
09327    if (res < 0) {
09328       if (option_debug)
09329          ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno));
09330       close(sd);
09331       return 1;
09332    }
09333 
09334    close(sd);
09335    return 0;
09336 }

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

Definition at line 5892 of file chan_iax2.c.

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

Referenced by socket_process().

05893 {
05894    char exten[256] = "";
05895    int status = CACHE_FLAG_UNKNOWN;
05896    int expiry = iaxdefaultdpcache;
05897    int x;
05898    int matchmore = 0;
05899    struct iax2_dpcache *dp, *prev;
05900    
05901    if (ies->called_number)
05902       ast_copy_string(exten, ies->called_number, sizeof(exten));
05903 
05904    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
05905       status = CACHE_FLAG_EXISTS;
05906    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
05907       status = CACHE_FLAG_CANEXIST;
05908    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
05909       status = CACHE_FLAG_NONEXISTENT;
05910 
05911    if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
05912       /* Don't really do anything with this */
05913    }
05914    if (ies->refresh)
05915       expiry = ies->refresh;
05916    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
05917       matchmore = CACHE_FLAG_MATCHMORE;
05918    ast_mutex_lock(&dpcache_lock);
05919    prev = NULL;
05920    dp = pvt->dpentries;
05921    while(dp) {
05922       if (!strcmp(dp->exten, exten)) {
05923          /* Let them go */
05924          if (prev)
05925             prev->peer = dp->peer;
05926          else
05927             pvt->dpentries = dp->peer;
05928          dp->peer = NULL;
05929          dp->callno = 0;
05930          dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
05931          if (dp->flags & CACHE_FLAG_PENDING) {
05932             dp->flags &= ~CACHE_FLAG_PENDING;
05933             dp->flags |= status;
05934             dp->flags |= matchmore;
05935          }
05936          /* Wake up waiters */
05937          for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
05938             if (dp->waiters[x] > -1) {
05939                if (write(dp->waiters[x], "asdf", 4) < 0) {
05940                   ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
05941                }
05942             }
05943          }
05944       }
05945       prev = dp;
05946       dp = dp->peer;
05947    }
05948    ast_mutex_unlock(&dpcache_lock);
05949    return 0;
05950 }

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

Definition at line 2456 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ast_strdup, iax2_peer::name, and peer_unref().

02457 {
02458    int which = 0;
02459    struct iax2_peer *peer;
02460    char *res = NULL;
02461    int wordlen = strlen(word);
02462    struct ao2_iterator i;
02463 
02464    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02465    if (pos != 3)
02466       return NULL;
02467 
02468    i = ao2_iterator_init(peers, 0);
02469    while ((peer = ao2_iterator_next(&i))) {
02470       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02471          res = ast_strdup(peer->name);
02472          peer_unref(peer);
02473          break;
02474       }
02475       peer_unref(peer);
02476    }
02477 
02478    return res;
02479 }

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

Definition at line 5952 of file chan_iax2.c.

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

Referenced by socket_process().

05953 {
05954    int peercallno = 0;
05955    struct chan_iax2_pvt *pvt = iaxs[callno];
05956    struct iax_frame *cur;
05957    jb_frame frame;
05958 
05959    if (ies->callno)
05960       peercallno = ies->callno;
05961 
05962    if (peercallno < 1) {
05963       ast_log(LOG_WARNING, "Invalid transfer request\n");
05964       return -1;
05965    }
05966    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
05967    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
05968    /* Reset sequence numbers */
05969    pvt->oseqno = 0;
05970    pvt->rseqno = 0;
05971    pvt->iseqno = 0;
05972    pvt->aseqno = 0;
05973 
05974    if (pvt->peercallno) {
05975       remove_by_peercallno(pvt);
05976    }
05977    pvt->peercallno = peercallno;
05978    store_by_peercallno(pvt);
05979 
05980    pvt->transferring = TRANSFER_NONE;
05981    pvt->svoiceformat = -1;
05982    pvt->voiceformat = 0;
05983    pvt->svideoformat = -1;
05984    pvt->videoformat = 0;
05985    pvt->transfercallno = -1;
05986    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
05987    memset(&pvt->offset, 0, sizeof(pvt->offset));
05988    /* reset jitterbuffer */
05989    while(jb_getall(pvt->jb,&frame) == JB_OK)
05990       iax2_frame_free(frame.data);
05991    jb_reset(pvt->jb);
05992    pvt->lag = 0;
05993    pvt->last = 0;
05994    pvt->lastsent = 0;
05995    pvt->nextpred = 0;
05996    pvt->pingtime = DEFAULT_RETRY_TIME;
05997    AST_LIST_LOCK(&iaxq.queue);
05998    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
05999       /* We must cancel any packets that would have been transmitted
06000          because now we're talking to someone new.  It's okay, they
06001          were transmitted to someone that didn't care anyway. */
06002       if (callno == cur->callno) 
06003          cur->retries = -1;
06004    }
06005    AST_LIST_UNLOCK(&iaxq.queue);
06006    return 0; 
06007 }

static unsigned char compress_subclass ( int  subclass  )  [static]

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

01074 {
01075    int x;
01076    int power=-1;
01077    /* If it's 128 or smaller, just return it */
01078    if (subclass < IAX_FLAG_SC_LOG)
01079       return subclass;
01080    /* Otherwise find its power */
01081    for (x = 0; x < IAX_MAX_SHIFT; x++) {
01082       if (subclass & (1 << x)) {
01083          if (power > -1) {
01084             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
01085             return 0;
01086          } else
01087             power = x;
01088       }
01089    }
01090    return power | IAX_FLAG_SC_LOG;
01091 }

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

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

06913 {
06914    jb_info stats;
06915    jb_getinfo(pvt->jb, &stats);
06916    
06917    memset(iep, 0, sizeof(*iep));
06918 
06919    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
06920    if(stats.frames_in == 0) stats.frames_in = 1;
06921    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
06922    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
06923    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
06924    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
06925    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
06926 }

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

Definition at line 3079 of file chan_iax2.c.

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

03080 {
03081    struct ast_hostent ahp;
03082    struct hostent *hp;
03083    struct iax2_peer *peer;
03084    int res = -1;
03085    struct ast_codec_pref ourprefs;
03086 
03087    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
03088    cai->sockfd = defaultsockfd;
03089    cai->maxtime = 0;
03090    sin->sin_family = AF_INET;
03091 
03092    if (!(peer = find_peer(peername, 1))) {
03093       cai->found = 0;
03094 
03095       hp = ast_gethostbyname(peername, &ahp);
03096       if (hp) {
03097          memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
03098          sin->sin_port = htons(IAX_DEFAULT_PORTNO);
03099          /* use global iax prefs for unknown peer/user */
03100          /* But move the calling channel's native codec to the top of the preference list */
03101          memcpy(&ourprefs, &prefs, sizeof(ourprefs));
03102          if (c)
03103             ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03104          ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03105          return 0;
03106       } else {
03107          ast_log(LOG_WARNING, "No such host: %s\n", peername);
03108          return -1;
03109       }
03110    }
03111 
03112    cai->found = 1;
03113    
03114    /* if the peer has no address (current or default), return failure */
03115    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr))
03116       goto return_unref;
03117 
03118    /* if the peer is being monitored and is currently unreachable, return failure */
03119    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
03120       goto return_unref;
03121 
03122    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
03123    cai->maxtime = peer->maxms;
03124    cai->capability = peer->capability;
03125    cai->encmethods = peer->encmethods;
03126    cai->sockfd = peer->sockfd;
03127    cai->adsi = peer->adsi;
03128    memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
03129    /* Move the calling channel's native codec to the top of the preference list */
03130    if (c) {
03131       ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
03132       ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03133    }
03134    ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03135    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
03136    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
03137    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
03138    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
03139    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
03140    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
03141    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
03142    if (ast_strlen_zero(peer->dbsecret)) {
03143       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
03144    } else {
03145       char *family;
03146       char *key = NULL;
03147 
03148       family = ast_strdupa(peer->dbsecret);
03149       key = strchr(family, '/');
03150       if (key)
03151          *key++ = '\0';
03152       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
03153          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
03154          goto return_unref;
03155       }
03156    }
03157 
03158    if (peer->addr.sin_addr.s_addr) {
03159       sin->sin_addr = peer->addr.sin_addr;
03160       sin->sin_port = peer->addr.sin_port;
03161    } else {
03162       sin->sin_addr = peer->defaddr.sin_addr;
03163       sin->sin_port = peer->defaddr.sin_port;
03164    }
03165 
03166    res = 0;
03167 
03168 return_unref:
03169    peer_unref(peer);
03170 
03171    return res;
03172 }

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

Definition at line 4274 of file chan_iax2.c.

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

Referenced by decrypt_frame().

04275 {
04276    int padding;
04277    unsigned char *workspace;
04278 
04279    workspace = alloca(*datalen);
04280    memset(f, 0, sizeof(*f));
04281    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04282       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04283       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04284          return -1;
04285       /* Decrypt */
04286       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04287 
04288       padding = 16 + (workspace[15] & 0xf);
04289       if (option_debug && iaxdebug)
04290          ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04291       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04292          return -1;
04293 
04294       *datalen -= padding;
04295       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04296       f->frametype = fh->type;
04297       if (f->frametype == AST_FRAME_VIDEO) {
04298          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04299       } else {
04300          f->subclass = uncompress_subclass(fh->csub);
04301       }
04302    } else {
04303       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04304       if (option_debug && iaxdebug)
04305          ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
04306       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04307          return -1;
04308       /* Decrypt */
04309       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04310       padding = 16 + (workspace[15] & 0x0f);
04311       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04312          return -1;
04313       *datalen -= padding;
04314       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04315    }
04316    return 0;
04317 }

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

Definition at line 4360 of file chan_iax2.c.

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

Referenced by socket_process().

04361 {
04362    int res=-1;
04363    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04364       /* Search for possible keys, given secrets */
04365       struct MD5Context md5;
04366       unsigned char digest[16];
04367       char *tmppw, *stringp;
04368       
04369       tmppw = ast_strdupa(iaxs[callno]->secret);
04370       stringp = tmppw;
04371       while ((tmppw = strsep(&stringp, ";"))) {
04372          MD5Init(&md5);
04373          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04374          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04375          MD5Final(digest, &md5);
04376          build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx);
04377          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04378          if (!res) {
04379             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04380             break;
04381          }
04382       }
04383    } else 
04384       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04385    return res;
04386 }

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 6974 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(), iax2_pkt_buf::buf, iax2_thread::buf, iax2_thread::buf_len, iax2_thread::full_frames, iax2_thread::lock, and ast_iax2_full_hdr::oseqno.

Referenced by socket_read().

06975 {
06976    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
06977    struct ast_iax2_full_hdr *fh, *cur_fh;
06978 
06979    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
06980       return;
06981 
06982    pkt_buf->len = from_here->buf_len;
06983    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
06984 
06985    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
06986    ast_mutex_lock(&to_here->lock);
06987    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
06988       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
06989       if (fh->oseqno < cur_fh->oseqno) {
06990          AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry);
06991          break;
06992       }
06993    }
06994    AST_LIST_TRAVERSE_SAFE_END
06995 
06996    if (!cur_pkt_buf)
06997       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
06998    
06999    ast_mutex_unlock(&to_here->lock);
07000 }

static void delete_users ( void   )  [static]

Definition at line 9899 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::entry, iax2_registry::expire, free, iax2_destroy(), iaxs, iaxsl, peer_delme_cb(), chan_iax2_pvt::reg, sched, and user_delme_cb().

09900 {
09901    struct iax2_registry *reg;
09902 
09903    ao2_callback(users, 0, user_delme_cb, NULL);
09904 
09905    AST_LIST_LOCK(&registrations);
09906    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
09907       ast_sched_del(sched, reg->expire);
09908       if (reg->callno) {
09909          int callno = reg->callno;
09910          ast_mutex_lock(&iaxsl[callno]);
09911          if (iaxs[callno]) {
09912             iaxs[callno]->reg = NULL;
09913             iax2_destroy(callno);
09914          }
09915          ast_mutex_unlock(&iaxsl[callno]);
09916       }
09917       if (reg->dnsmgr)
09918          ast_dnsmgr_release(reg->dnsmgr);
09919       free(reg);
09920    }
09921    AST_LIST_UNLOCK(&registrations);
09922 
09923    ao2_callback(peers, 0, peer_delme_cb, NULL);
09924 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1807 of file chan_iax2.c.

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

Referenced by reload_firmware().

01808 {
01809    /* Close firmware */
01810    if (cur->fwh) {
01811       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01812    }
01813    close(cur->fd);
01814    free(cur);
01815 }

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

Definition at line 6746 of file chan_iax2.c.

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

Referenced by dp_lookup_thread(), and socket_process().

06747 {
06748    unsigned short dpstatus = 0;
06749    struct iax_ie_data ied1;
06750    int mm;
06751 
06752    memset(&ied1, 0, sizeof(ied1));
06753    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
06754    /* Must be started */
06755    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
06756       dpstatus = IAX_DPSTATUS_EXISTS;
06757    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
06758       dpstatus = IAX_DPSTATUS_CANEXIST;
06759    } else {
06760       dpstatus = IAX_DPSTATUS_NONEXISTENT;
06761    }
06762    if (ast_ignore_pattern(context, callednum))
06763       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
06764    if (mm)
06765       dpstatus |= IAX_DPSTATUS_MATCHMORE;
06766    if (!skiplock)
06767       ast_mutex_lock(&iaxsl[callno]);
06768    if (iaxs[callno]) {
06769       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
06770       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
06771       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
06772       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
06773    }
06774    if (!skiplock)
06775       ast_mutex_unlock(&iaxsl[callno]);
06776 }

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

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

06779 {
06780    /* Look up for dpreq */
06781    struct dpreq_data *dpr = data;
06782    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
06783    if (dpr->callerid)
06784       free(dpr->callerid);
06785    free(dpr);
06786    return NULL;
06787 }

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

Definition at line 4319 of file chan_iax2.c.

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

Referenced by iax2_send().

04320 {
04321    int padding;
04322    unsigned char *workspace;
04323    workspace = alloca(*datalen + 32);
04324    if (!workspace)
04325       return -1;
04326    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04327       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04328       if (option_debug && iaxdebug)
04329          ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04330       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04331       padding = 16 + (padding & 0xf);
04332       memcpy(workspace, poo, padding);
04333       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04334       workspace[15] &= 0xf0;
04335       workspace[15] |= (padding & 0xf);
04336       if (option_debug && iaxdebug)
04337          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]);
04338       *datalen += padding;
04339       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04340       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04341          memcpy(poo, workspace + *datalen - 32, 32);
04342    } else {
04343       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04344       if (option_debug && iaxdebug)
04345          ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
04346       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04347       padding = 16 + (padding & 0xf);
04348       memcpy(workspace, poo, padding);
04349       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04350       workspace[15] &= 0xf0;
04351       workspace[15] |= (padding & 0x0f);
04352       *datalen += padding;
04353       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04354       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04355          memcpy(poo, workspace + *datalen - 32, 32);
04356    }
04357    return 0;
04358 }

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

Definition at line 6189 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

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

06190 {
06191 #ifdef SCHED_MULTITHREADED
06192    if (schedule_action(__expire_registry, data))
06193 #endif      
06194       __expire_registry(data);
06195    return 0;
06196 }

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

Definition at line 10458 of file chan_iax2.c.

References ARRAY_LEN, ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_copy_string(), ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_tvcmp(), ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, dpcache, dpcache_lock, chan_iax2_pvt::dpentries, errno, 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().

10459 {
10460    struct iax2_dpcache *dp, *prev = NULL, *next;
10461    struct timeval tv;
10462    int x;
10463    int com[2];
10464    int timeout;
10465    int old=0;
10466    int outfd;
10467    int abort;
10468    int callno;
10469    struct ast_channel *c;
10470    struct ast_frame *f;
10471    gettimeofday(&tv, NULL);
10472    dp = dpcache;
10473    while(dp) {
10474       next = dp->next;
10475       /* Expire old caches */
10476       if (ast_tvcmp(tv, dp->expiry) > 0) {
10477             /* It's expired, let it disappear */
10478             if (prev)
10479                prev->next = dp->next;
10480             else
10481                dpcache = dp->next;
10482             if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
10483                /* Free memory and go again */
10484                free(dp);
10485             } else {
10486                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);
10487             }
10488             dp = next;
10489             continue;
10490       }
10491       /* We found an entry that matches us! */
10492       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 
10493          break;
10494       prev = dp;
10495       dp = next;
10496    }
10497    if (!dp) {
10498       /* No matching entry.  Create a new one. */
10499       /* First, can we make a callno? */
10500       callno = cache_get_callno_locked(data);
10501       if (callno < 0) {
10502          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
10503          return NULL;
10504       }
10505       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
10506          ast_mutex_unlock(&iaxsl[callno]);
10507          return NULL;
10508       }
10509       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
10510       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
10511       gettimeofday(&dp->expiry, NULL);
10512       dp->orig = dp->expiry;
10513       /* Expires in 30 mins by default */
10514       dp->expiry.tv_sec += iaxdefaultdpcache;
10515       dp->next = dpcache;
10516       dp->flags = CACHE_FLAG_PENDING;
10517       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
10518          dp->waiters[x] = -1;
10519       dpcache = dp;
10520       dp->peer = iaxs[callno]->dpentries;
10521       iaxs[callno]->dpentries = dp;
10522       /* Send the request if we're already up */
10523       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
10524          iax2_dprequest(dp, callno);
10525       ast_mutex_unlock(&iaxsl[callno]);
10526    }
10527    /* By here we must have a dp */
10528    if (dp->flags & CACHE_FLAG_PENDING) {
10529       /* Okay, here it starts to get nasty.  We need a pipe now to wait
10530          for a reply to come back so long as it's pending */
10531       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) {
10532          /* Find an empty slot */
10533          if (dp->waiters[x] < 0)
10534             break;
10535       }
10536       if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) {
10537          ast_log(LOG_WARNING, "No more waiter positions available\n");
10538          return NULL;
10539       }
10540       if (pipe(com)) {
10541          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
10542          return NULL;
10543       }
10544       dp->waiters[x] = com[1];
10545       /* Okay, now we wait */
10546       timeout = iaxdefaulttimeout * 1000;
10547       /* Temporarily unlock */
10548       ast_mutex_unlock(&dpcache_lock);
10549       /* Defer any dtmf */
10550       if (chan)
10551          old = ast_channel_defer_dtmf(chan);
10552       abort = 0;
10553       while(timeout) {
10554          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
10555          if (outfd > -1) {
10556             break;
10557          }
10558          if (c) {
10559             f = ast_read(c);
10560             if (f)
10561                ast_frfree(f);
10562             else {
10563                /* Got hung up on, abort! */
10564                break;
10565                abort = 1;
10566             }
10567          }
10568       }
10569       if (!timeout) {
10570          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
10571       }
10572       ast_mutex_lock(&dpcache_lock);
10573       dp->waiters[x] = -1;
10574       close(com[1]);
10575       close(com[0]);
10576       if (abort) {
10577          /* Don't interpret anything, just abort.  Not sure what th epoint
10578            of undeferring dtmf on a hung up channel is but hey whatever */
10579          if (!old && chan)
10580             ast_channel_undefer_dtmf(chan);
10581          return NULL;
10582       }
10583       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
10584          /* Now to do non-independent analysis the results of our wait */
10585          if (dp->flags & CACHE_FLAG_PENDING) {
10586             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
10587                pending.  Don't let it take as long to timeout. */
10588             dp->flags &= ~CACHE_FLAG_PENDING;
10589             dp->flags |= CACHE_FLAG_TIMEOUT;
10590             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
10591                systems without leaving it unavailable once the server comes back online */
10592             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
10593             for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
10594                if (dp->waiters[x] > -1) {
10595                   if (write(dp->waiters[x], "asdf", 4) < 0) {
10596                      ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10597                   }
10598                }
10599             }
10600          }
10601       }
10602       /* Our caller will obtain the rest */
10603       if (!old && chan)
10604          ast_channel_undefer_dtmf(chan);
10605    }
10606    return dp;  
10607 }

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

Definition at line 1707 of file chan_iax2.c.

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

01707                                                                                                                                     {
01708 
01709    return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame);
01710 }

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

Definition at line 1712 of file chan_iax2.c.

References __find_callno().

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

01712                                                                                                                                            {
01713 
01714    return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
01715 }

static struct iax2_thread* find_idle_thread ( void   )  [static]

Definition at line 908 of file chan_iax2.c.

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

Referenced by __schedule_action(), and socket_read().

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

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

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

Definition at line 1151 of file chan_iax2.c.

References ao2_find(), iax2_peer::name, and realtime_peer().

01152 {
01153    struct iax2_peer *peer = NULL;
01154    struct iax2_peer tmp_peer = {
01155       .name = name,
01156    };
01157 
01158    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
01159 
01160    /* Now go for realtime if applicable */
01161    if(!peer && realtime)
01162       peer = realtime_peer(name, NULL);
01163 
01164    return peer;
01165 }

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

Definition at line 4128 of file chan_iax2.c.

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

Referenced by iax2_trunk_queue(), and socket_process().

04129 {
04130    struct iax2_trunk_peer *tpeer;
04131    
04132    /* Finds and locks trunk peer */
04133    ast_mutex_lock(&tpeerlock);
04134    for (tpeer = tpeers; tpeer; tpeer = tpeer->next) {
04135       /* We don't lock here because tpeer->addr *never* changes */
04136       if (!inaddrcmp(&tpeer->addr, sin)) {
04137          ast_mutex_lock(&tpeer->lock);
04138          break;
04139       }
04140    }
04141    if (!tpeer) {
04142       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
04143          ast_mutex_init(&tpeer->lock);
04144          tpeer->lastsent = 9999;
04145          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
04146          tpeer->trunkact = ast_tvnow();
04147          ast_mutex_lock(&tpeer->lock);
04148          tpeer->next = tpeers;
04149          tpeer->sockfd = fd;
04150          tpeers = tpeer;
04151 #ifdef SO_NO_CHECK
04152          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
04153 #endif
04154          if (option_debug)
04155             ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
04156       }
04157    }
04158    ast_mutex_unlock(&tpeerlock);
04159    return tpeer;
04160 }

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

Definition at line 3944 of file chan_iax2.c.

References ast_tvdiff_ms(), ast_tvzero(), iaxs, and chan_iax2_pvt::rxcore.

Referenced by socket_process().

03945 {
03946    long ms; /* NOT unsigned */
03947    if (ast_tvzero(iaxs[callno]->rxcore)) {
03948       /* Initialize rxcore time if appropriate */
03949       gettimeofday(&iaxs[callno]->rxcore, NULL);
03950       /* Round to nearest 20ms so traces look pretty */
03951       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
03952    }
03953    /* Calculate difference between trunk and channel */
03954    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
03955    /* Return as the sum of trunk time and the difference between trunk and real time */
03956    return ms + ts;
03957 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 9075 of file chan_iax2.c.

References free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

09076 {
09077    struct iax2_context *conl;
09078    while(con) {
09079       conl = con;
09080       con = con->next;
09081       free(conl);
09082    }
09083 }

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

Definition at line 10731 of file chan_iax2.c.

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

10732 {
10733    struct iax2_peer *peer;
10734    char *peername, *colname;
10735 
10736    peername = ast_strdupa(data);
10737 
10738    /* if our channel, return the IP address of the endpoint of current channel */
10739    if (!strcmp(peername,"CURRENTCHANNEL")) {
10740            unsigned short callno;
10741       if (chan->tech != &iax2_tech)
10742          return -1;
10743       callno = PTR_TO_CALLNO(chan->tech_pvt);   
10744       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
10745       return 0;
10746    }
10747 
10748    if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */
10749       *colname++ = '\0';
10750    else if ((colname = strchr(peername, '|')))
10751       *colname++ = '\0';
10752    else
10753       colname = "ip";
10754 
10755    if (!(peer = find_peer(peername, 1)))
10756       return -1;
10757 
10758    if (!strcasecmp(colname, "ip")) {
10759       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
10760    } else  if (!strcasecmp(colname, "status")) {
10761       peer_status(peer, buf, len); 
10762    } else  if (!strcasecmp(colname, "mailbox")) {
10763       ast_copy_string(buf, peer->mailbox, len);
10764    } else  if (!strcasecmp(colname, "context")) {
10765       ast_copy_string(buf, peer->context, len);
10766    } else  if (!strcasecmp(colname, "expire")) {
10767       snprintf(buf, len, "%d", peer->expire);
10768    } else  if (!strcasecmp(colname, "dynamic")) {
10769       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
10770    } else  if (!strcasecmp(colname, "callerid_name")) {
10771       ast_copy_string(buf, peer->cid_name, len);
10772    } else  if (!strcasecmp(colname, "callerid_num")) {
10773       ast_copy_string(buf, peer->cid_num, len);
10774    } else  if (!strcasecmp(colname, "codecs")) {
10775       ast_getformatname_multiple(buf, len -1, peer->capability);
10776    } else  if (!strncasecmp(colname, "codec[", 6)) {
10777       char *codecnum, *ptr;
10778       int index = 0, codec = 0;
10779       
10780       codecnum = strchr(colname, '[');
10781       *codecnum = '\0';
10782       codecnum++;
10783       if ((ptr = strchr(codecnum, ']'))) {
10784          *ptr = '\0';
10785       }
10786       index = atoi(codecnum);
10787       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
10788          ast_copy_string(buf, ast_getformatname(codec), len);
10789       } else {
10790          buf[0] = '\0';
10791       }
10792    } else {
10793       buf[0] = '\0';
10794    }
10795 
10796    peer_unref(peer);
10797 
10798    return 0;
10799 }

static int get_auth_methods ( char *  value  )  [static]

Definition at line 9299 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

09300 {
09301    int methods = 0;
09302    if (strstr(value, "rsa"))
09303       methods |= IAX_AUTH_RSA;
09304    if (strstr(value, "md5"))
09305       methods |= IAX_AUTH_MD5;
09306    if (strstr(value, "plaintext"))
09307       methods |= IAX_AUTH_PLAINTEXT;
09308    return methods;
09309 }

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

Definition at line 1028 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

01029 {
01030    int e;
01031    if (!strcasecmp(s, "aes128"))
01032       e = IAX_ENCRYPT_AES128;
01033    else if (ast_true(s))
01034       e = IAX_ENCRYPT_AES128;
01035    else
01036       e = 0;
01037    return e;
01038 }

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

Definition at line 2693 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

02694 {
02695 #ifdef SCHED_MULTITHREADED
02696    if (schedule_action(__get_from_jb, data))
02697 #endif      
02698       __get_from_jb(data);
02699    return 0;
02700 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

Definition at line 6944 of file chan_iax2.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), iax2_pkt_buf::buf, iax2_pkt_buf::entry, iax2_pkt_buf::len, socket_process(), and thread.

06945 {
06946    struct iax2_pkt_buf *pkt_buf;
06947 
06948    ast_mutex_lock(&thread->lock);
06949 
06950    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
06951       ast_mutex_unlock(&thread->lock);
06952 
06953       thread->buf = pkt_buf->buf;
06954       thread->buf_len = pkt_buf->len;
06955       thread->buf_size = pkt_buf->len + 1;
06956       
06957       socket_process(thread);
06958 
06959       thread->buf = NULL;
06960       ast_free(pkt_buf);
06961 
06962       ast_mutex_lock(&thread->lock);
06963    }
06964 
06965    ast_mutex_unlock(&thread->lock);
06966 }

static int handle_error ( void   )  [static]

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

02096 {
02097    /* XXX Ideally we should figure out why an error occured and then abort those
02098       rather than continuing to try.  Unfortunately, the published interface does
02099       not seem to work XXX */
02100 #if 0
02101    struct sockaddr_in *sin;
02102    int res;
02103    struct msghdr m;
02104    struct sock_extended_err e;
02105    m.msg_name = NULL;
02106    m.msg_namelen = 0;
02107    m.msg_iov = NULL;
02108    m.msg_control = &e;
02109    m.msg_controllen = sizeof(e);
02110    m.msg_flags = 0;
02111    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
02112    if (res < 0)
02113       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
02114    else {
02115       if (m.msg_controllen) {
02116          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
02117          if (sin) 
02118             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
02119          else
02120             ast_log(LOG_WARNING, "No address detected??\n");
02121       } else {
02122          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
02123       }
02124    }
02125 #endif
02126    return 0;
02127 }

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

Acknowledgment received for OUR registration.

Definition at line 6010 of file chan_iax2.c.

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

Referenced by socket_process().

06011 {
06012    struct iax2_registry *reg;
06013    /* Start pessimistic */
06014    char peer[256] = "";
06015    char msgstatus[60];
06016    int refresh = 60;
06017    char ourip[256] = "<Unspecified>";
06018    struct sockaddr_in oldus;
06019    struct sockaddr_in us;
06020    int oldmsgs;
06021 
06022    memset(&us, 0, sizeof(us));
06023    if (ies->apparent_addr)
06024       bcopy(ies->apparent_addr, &us, sizeof(us));
06025    if (ies->username)
06026       ast_copy_string(peer, ies->username, sizeof(peer));
06027    if (ies->refresh)
06028       refresh = ies->refresh;
06029    if (ies->calling_number) {
06030       /* We don't do anything with it really, but maybe we should */
06031    }
06032    reg = iaxs[callno]->reg;
06033    if (!reg) {
06034       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
06035       return -1;
06036    }
06037    memcpy(&oldus, &reg->us, sizeof(oldus));
06038    oldmsgs = reg->messages;
06039    if (inaddrcmp(&reg->addr, sin)) {
06040       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06041       return -1;
06042    }
06043    memcpy(&reg->us, &us, sizeof(reg->us));
06044    if (ies->msgcount >= 0)
06045       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
06046    /* always refresh the registration at the interval requested by the server
06047       we are registering to
06048    */
06049    reg->refresh = refresh;
06050    AST_SCHED_DEL(sched, reg->expire);
06051    reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
06052    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
06053       if (option_verbose > 2) {
06054          if (reg->messages > 255)
06055             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
06056          else if (reg->messages > 1)
06057             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
06058          else if (reg->messages > 0)
06059             snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n");
06060          else
06061             snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n");
06062          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
06063          ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
06064       }
06065       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
06066    }
06067    reg->regstate = REG_STATE_REGISTERED;
06068    return 0;
06069 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 3750 of file chan_iax2.c.

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

03751 {
03752    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03753    if (option_debug)
03754       ast_log(LOG_DEBUG, "Answering IAX2 call\n");
03755    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
03756 }

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

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

03597 {
03598    struct ast_channel *cs[3];
03599    struct ast_channel *who, *other;
03600    int to = -1;
03601    int res = -1;
03602    int transferstarted=0;
03603    struct ast_frame *f;
03604    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03605    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03606    struct timeval waittimer = {0, 0}, tv;
03607 
03608    lock_both(callno0, callno1);
03609    if (!iaxs[callno0] || !iaxs[callno1]) {
03610       unlock_both(callno0, callno1);
03611       return AST_BRIDGE_FAILED;
03612    }
03613    /* Put them in native bridge mode */
03614    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
03615       iaxs[callno0]->bridgecallno = callno1;
03616       iaxs[callno1]->bridgecallno = callno0;
03617    }
03618    /* If the bridge got retried, don't queue up more packets - the transfer request will be retransmitted as necessary */
03619    if (iaxs[callno0]->transferring && iaxs[callno1]->transferring) {
03620       transferstarted = 1;
03621    }
03622    unlock_both(callno0, callno1);
03623 
03624    /* If not, try to bridge until we can execute a transfer, if we can */
03625    cs[0] = c0;
03626    cs[1] = c1;
03627    for (/* ever */;;) {
03628       /* Check in case we got masqueraded into */
03629       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
03630          if (option_verbose > 2)
03631             ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
03632          /* Remove from native mode */
03633          if (c0->tech == &iax2_tech) {
03634             ast_mutex_lock(&iaxsl[callno0]);
03635             iaxs[callno0]->bridgecallno = 0;
03636             ast_mutex_unlock(&iaxsl[callno0]);
03637          }
03638          if (c1->tech == &iax2_tech) {
03639             ast_mutex_lock(&iaxsl[callno1]);
03640             iaxs[callno1]->bridgecallno = 0;
03641             ast_mutex_unlock(&iaxsl[callno1]);
03642          }
03643          return AST_BRIDGE_FAILED_NOWARN;
03644       }
03645       if (c0->nativeformats != c1->nativeformats) {
03646          if (option_verbose > 2) {
03647             char buf0[255];
03648             char buf1[255];
03649             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
03650             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
03651             ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
03652          }
03653          /* Remove from native mode */
03654          lock_both(callno0, callno1);
03655          if (iaxs[callno0])
03656             iaxs[callno0]->bridgecallno = 0;
03657          if (iaxs[callno1])
03658             iaxs[callno1]->bridgecallno = 0;
03659          unlock_both(callno0, callno1);
03660          return AST_BRIDGE_FAILED_NOWARN;
03661       }
03662       /* check if transfered and if we really want native bridging */
03663       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
03664          /* Try the transfer */
03665          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
03666                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
03667             ast_log(LOG_WARNING, "Unable to start the transfer\n");
03668          transferstarted = 1;
03669       }
03670       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
03671          /* Call has been transferred.  We're no longer involved */
03672          gettimeofday(&tv, NULL);
03673          if (ast_tvzero(waittimer)) {
03674             waittimer = tv;
03675          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
03676             c0->_softhangup |= AST_SOFTHANGUP_DEV;
03677             c1->_softhangup |= AST_SOFTHANGUP_DEV;
03678             *fo = NULL;
03679             *rc = c0;
03680             res = AST_BRIDGE_COMPLETE;
03681             break;
03682          }
03683       }
03684       to = 1000;
03685       who = ast_waitfor_n(cs, 2, &to);
03686       if (timeoutms > -1) {
03687          timeoutms -= (1000 - to);
03688          if (timeoutms < 0)
03689             timeoutms = 0;
03690       }
03691       if (!who) {
03692          if (!timeoutms) {
03693             res = AST_BRIDGE_RETRY;
03694             break;
03695          }
03696          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03697             res = AST_BRIDGE_FAILED;
03698             break;
03699          }
03700          continue;
03701       }
03702       f = ast_read(who);
03703       if (!f) {
03704          *fo = NULL;
03705          *rc = who;
03706          res = AST_BRIDGE_COMPLETE;
03707          break;
03708       }
03709       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
03710          *fo = f;
03711          *rc = who;
03712          res =  AST_BRIDGE_COMPLETE;
03713          break;
03714       }
03715       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
03716       if ((f->frametype == AST_FRAME_VOICE) ||
03717           (f->frametype == AST_FRAME_TEXT) ||
03718           (f->frametype == AST_FRAME_VIDEO) || 
03719           (f->frametype == AST_FRAME_IMAGE) ||
03720           (f->frametype == AST_FRAME_DTMF)) {
03721          /* monitored dtmf take out of the bridge.
03722           * check if we monitor the specific source.
03723           */
03724          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
03725          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
03726             *rc = who;
03727             *fo = f;
03728             res = AST_BRIDGE_COMPLETE;
03729             /* Remove from native mode */
03730             break;
03731          }
03732          /* everything else goes to the other side */
03733          ast_write(other, f);
03734       }
03735       ast_frfree(f);
03736       /* Swap who gets priority */
03737       cs[2] = cs[0];
03738       cs[0] = cs[1];
03739       cs[1] = cs[2];
03740    }
03741    lock_both(callno0, callno1);
03742    if(iaxs[callno0])
03743       iaxs[callno0]->bridgecallno = 0;
03744    if(iaxs[callno1])
03745       iaxs[callno1]->bridgecallno = 0;
03746    unlock_both(callno0, callno1);
03747    return res;
03748 }

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

Definition at line 3293 of file chan_iax2.c.

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

03294 {
03295    struct sockaddr_in sin;
03296    char *l=NULL, *n=NULL, *tmpstr;
03297    struct iax_ie_data ied;
03298    char *defaultrdest = "s";
03299    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03300    struct parsed_dial_string pds;
03301    struct create_addr_info cai;
03302 
03303    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
03304       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
03305       return -1;
03306    }
03307 
03308    memset(&cai, 0, sizeof(cai));
03309    cai.encmethods = iax2_encryption;
03310 
03311    memset(&pds, 0, sizeof(pds));
03312    tmpstr = ast_strdupa(dest);
03313    parse_dial_string(tmpstr, &pds);
03314 
03315    if (ast_strlen_zero(pds.peer)) {
03316       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest);
03317       return -1;
03318    }
03319 
03320    if (!pds.exten) {
03321       pds.exten = defaultrdest;
03322    }
03323 
03324    if (create_addr(pds.peer, c, &sin, &cai)) {
03325       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
03326       return -1;
03327    }
03328 
03329    if (!pds.username && !ast_strlen_zero(cai.username))
03330       pds.username = cai.username;
03331    if (!pds.password && !ast_strlen_zero(cai.secret))
03332       pds.password = cai.secret;
03333    if (!pds.key && !ast_strlen_zero(cai.outkey))
03334       pds.key = cai.outkey;
03335    if (!pds.context && !ast_strlen_zero(cai.peercontext))
03336       pds.context = cai.peercontext;
03337 
03338    /* Keep track of the context for outgoing calls too */
03339    ast_copy_string(c->context, cai.context, sizeof(c->context));
03340 
03341    if (pds.port)
03342       sin.sin_port = htons(atoi(pds.port));
03343 
03344    l = c->cid.cid_num;
03345    n = c->cid.cid_name;
03346 
03347    /* Now build request */ 
03348    memset(&ied, 0, sizeof(ied));
03349 
03350    /* On new call, first IE MUST be IAX version of caller */
03351    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
03352    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
03353    if (pds.options && strchr(pds.options, 'a')) {
03354       /* Request auto answer */
03355       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
03356    }
03357 
03358    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
03359 
03360    if (l) {
03361       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
03362       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03363    } else {
03364       if (n)
03365          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03366       else
03367          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
03368    }
03369 
03370    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
03371    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
03372 
03373    if (n)
03374       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
03375    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
03376       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
03377 
03378    if (!ast_strlen_zero(c->language))
03379       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
03380    if (!ast_strlen_zero(c->cid.cid_dnid))
03381       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
03382    if (!ast_strlen_zero(c->cid.cid_rdnis))
03383       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
03384 
03385    if (pds.context)
03386       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
03387 
03388    if (pds.username)
03389       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
03390 
03391    if (cai.encmethods)
03392       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
03393 
03394    ast_mutex_lock(&iaxsl[callno]);
03395 
03396    if (!ast_strlen_zero(c->context))
03397       ast_string_field_set(iaxs[callno], context, c->context);
03398 
03399    if (pds.username)
03400       ast_string_field_set(iaxs[callno], username, pds.username);
03401 
03402    iaxs[callno]->encmethods = cai.encmethods;
03403 
03404    iaxs[callno]->adsi = cai.adsi;
03405    
03406    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
03407    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
03408 
03409    if (pds.key)
03410       ast_string_field_set(iaxs[callno], outkey, pds.key);
03411    if (pds.password)
03412       ast_string_field_set(iaxs[callno], secret, pds.password);
03413 
03414    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
03415    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
03416    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
03417    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
03418 
03419    if (iaxs[callno]->maxtime) {
03420       /* Initialize pingtime and auto-congest time */
03421       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
03422       iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
03423    } else if (autokill) {
03424       iaxs[callno]->pingtime = autokill / 2;
03425       iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
03426    }
03427 
03428    /* send the command using the appropriate socket for this peer */
03429    iaxs[callno]->sockfd = cai.sockfd;
03430 
03431    /* Transmit the string in a "NEW" request */
03432    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
03433 
03434    ast_mutex_unlock(&iaxsl[callno]);
03435    ast_setstate(c, AST_STATE_RINGING);
03436    
03437    return 0;
03438 }

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

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_CANEXIST, dpcache_lock, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.

10634 {
10635    int res = 0;
10636    struct iax2_dpcache *dp;
10637 #if 0
10638    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10639 #endif
10640    if ((priority != 1) && (priority != 2))
10641       return 0;
10642    ast_mutex_lock(&dpcache_lock);
10643    dp = find_cache(chan, data, context, exten, priority);
10644    if (dp) {
10645       if (dp->flags & CACHE_FLAG_CANEXIST)
10646          res= 1;
10647    }
10648    ast_mutex_unlock(&dpcache_lock);
10649    if (!dp) {
10650       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10651    }
10652    return res;
10653 }

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

Definition at line 3196 of file chan_iax2.c.

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

Referenced by iax2_call(), and update_registry().

03197 {
03198    time_t t;
03199    struct tm tm;
03200    unsigned int tmp;
03201    time(&t);
03202    if (!ast_strlen_zero(tz))
03203       ast_localtime(&t, &tm, tz);
03204    else
03205       ast_localtime(&t, &tm, NULL);
03206    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03207    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03208    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03209    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03210    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03211    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03212    return tmp;
03213 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 1291 of file chan_iax2.c.

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

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

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

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1221 of file chan_iax2.c.

References ao2_find(), ast_atomic_fetchadd_int(), 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, iax2_user::name, chan_iax2_pvt::pingid, sched, user_unref(), and chan_iax2_pvt::username.

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

01222 {
01223    /* Decrement AUTHREQ count if needed */
01224    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01225       struct iax2_user *user;
01226       struct iax2_user tmp_user = {
01227          .name = pvt->username,
01228       };
01229 
01230       user = ao2_find(users, &tmp_user, OBJ_POINTER);
01231       if (user) {
01232          ast_atomic_fetchadd_int(&user->curauthreq, -1);
01233          user = user_unref(user);       
01234       }
01235 
01236       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01237    }
01238 
01239    /* No more pings or lagrq's */
01240    AST_SCHED_DEL(sched, pvt->pingid);
01241    AST_SCHED_DEL(sched, pvt->lagid);
01242    AST_SCHED_DEL(sched, pvt->autoid);
01243    AST_SCHED_DEL(sched, pvt->authid);
01244    AST_SCHED_DEL(sched, pvt->initid);
01245    AST_SCHED_DEL(sched, pvt->jbid);
01246 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 10824 of file chan_iax2.c.

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

10825 {
10826    struct parsed_dial_string pds;
10827    char *tmp = ast_strdupa(data);
10828    struct iax2_peer *p;
10829    int res = AST_DEVICE_INVALID;
10830 
10831    memset(&pds, 0, sizeof(pds));
10832    parse_dial_string(tmp, &pds);
10833 
10834    if (ast_strlen_zero(pds.peer)) {
10835       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10836       return res;
10837    }
10838    
10839    if (option_debug > 2)
10840       ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer);
10841 
10842    /* SLD: FIXME: second call to find_peer during registration */
10843    if (!(p = find_peer(pds.peer, 1)))
10844       return res;
10845 
10846    res = AST_DEVICE_UNAVAILABLE;
10847    if (option_debug > 2) 
10848       ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
10849          pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
10850    
10851    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
10852        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
10853       /* Peer is registered, or have default IP address
10854          and a valid registration */
10855       if (p->historicms == 0 || p->historicms <= p->maxms)
10856          /* let the core figure out whether it is in use or not */
10857          res = AST_DEVICE_UNKNOWN;  
10858    }
10859 
10860    peer_unref(p);
10861 
10862    return res;
10863 }

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

Definition at line 2812 of file chan_iax2.c.

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

02813 {
02814    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
02815 }

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

Definition at line 2817 of file chan_iax2.c.

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

02818 {
02819    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
02820 }

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

Definition at line 5050 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05051 {
05052    if (argc < 2 || argc > 3)
05053       return RESULT_SHOWUSAGE;
05054    iaxdebug = 1;
05055    ast_cli(fd, "IAX2 Debugging Enabled\n");
05056    return RESULT_SUCCESS;
05057 }

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

Definition at line 5068 of file chan_iax2.c.

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

05069 {
05070    if (argc < 3 || argc > 4)
05071       return RESULT_SHOWUSAGE;
05072    jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
05073    ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n");
05074    return RESULT_SUCCESS;
05075 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 8793 of file chan_iax2.c.

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

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

08794 {
08795    struct iax_ie_data ied;
08796    if (option_debug && iaxdebug)
08797       ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username);
08798 
08799    if (reg->dnsmgr && 
08800        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
08801       /* Maybe the IP has changed, force DNS refresh */
08802       ast_dnsmgr_refresh(reg->dnsmgr);
08803    }
08804    
08805    /*
08806     * if IP has Changed, free allocated call to create a new one with new IP
08807     * call has the pointer to IP and must be updated to the new one
08808     */
08809    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
08810       int callno = reg->callno;
08811       ast_mutex_lock(&iaxsl[callno]);
08812       iax2_destroy(callno);
08813       ast_mutex_unlock(&iaxsl[callno]);
08814       reg->callno = 0;
08815    }
08816    if (!reg->addr.sin_addr.s_addr) {
08817       if (option_debug && iaxdebug)
08818          ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username);
08819       /* Setup the next registration attempt */
08820       AST_SCHED_DEL(sched, reg->expire);
08821       reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08822       return -1;
08823    }
08824 
08825    if (!reg->callno) {
08826       if (option_debug)
08827          ast_log(LOG_DEBUG, "Allocate call number\n");
08828       reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
08829       if (reg->callno < 1) {
08830          ast_log(LOG_WARNING, "Unable to create call for registration\n");
08831          return -1;
08832       } else if (option_debug)
08833          ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno);
08834       iaxs[reg->callno]->reg = reg;
08835       ast_mutex_unlock(&iaxsl[reg->callno]);
08836    }
08837    /* Schedule the next registration attempt */
08838    AST_SCHED_DEL(sched, reg->expire);
08839    /* Setup the next registration a little early */
08840    reg->expire  = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
08841    /* Send the request */
08842    memset(&ied, 0, sizeof(ied));
08843    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
08844    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
08845    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
08846    reg->regstate = REG_STATE_REGSENT;
08847    return 0;
08848 }

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

Definition at line 5854 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

05855 {
05856 #ifdef SCHED_MULTITHREADED
05857    if (schedule_action(__iax2_do_register_s, data))
05858 #endif      
05859       __iax2_do_register_s(data);
05860    return 0;
05861 }

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

Definition at line 5059 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05060 {
05061    if (argc < 3 || argc > 4)
05062       return RESULT_SHOWUSAGE;
05063    iaxtrunkdebug = 1;
05064    ast_cli(fd, "IAX2 Trunk Debug Requested\n");
05065    return RESULT_SUCCESS;
05066 }

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

Definition at line 6555 of file chan_iax2.c.

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

Referenced by find_cache(), and socket_process().

06556 {
06557    struct iax_ie_data ied;
06558    /* Auto-hangup with 30 seconds of inactivity */
06559    AST_SCHED_DEL(sched, iaxs[callno]->autoid);
06560    iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno);
06561    memset(&ied, 0, sizeof(ied));
06562    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
06563    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
06564    dp->flags |= CACHE_FLAG_TRANSMITTED;
06565 }

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

References ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), CACHE_FLAG_EXISTS, dpcache_lock, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_3.

10680 {
10681    char odata[256];
10682    char req[256];
10683    char *ncontext;
10684    struct iax2_dpcache *dp;
10685    struct ast_app *dial;
10686 #if 0
10687    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);
10688 #endif
10689    if (priority == 2) {
10690       /* Indicate status, can be overridden in dialplan */
10691       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
10692       if (dialstatus) {
10693          dial = pbx_findapp(dialstatus);
10694          if (dial) 
10695             pbx_exec(chan, dial, "");
10696       }
10697       return -1;
10698    } else if (priority != 1)
10699       return -1;
10700    ast_mutex_lock(&dpcache_lock);
10701    dp = find_cache(chan, data, context, exten, priority);
10702    if (dp) {
10703       if (dp->flags & CACHE_FLAG_EXISTS) {
10704          ast_copy_string(odata, data, sizeof(odata));
10705          ncontext = strchr(odata, '/');
10706          if (ncontext) {
10707             *ncontext = '\0';
10708             ncontext++;
10709             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
10710          } else {
10711             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
10712          }
10713          if (option_verbose > 2)
10714             ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
10715       } else {
10716          ast_mutex_unlock(&dpcache_lock);
10717          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
10718          return -1;
10719       }
10720    }
10721    ast_mutex_unlock(&dpcache_lock);
10722    dial = pbx_findapp("Dial");
10723    if (dial) {
10724       return pbx_exec(chan, dial, req);
10725    } else {
10726       ast_log(LOG_WARNING, "No dial application registered\n");
10727    }
10728    return -1;
10729 }

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

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_EXISTS, dpcache_lock, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.

10611 {
10612    struct iax2_dpcache *dp;
10613    int res = 0;
10614 #if 0
10615    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10616 #endif
10617    if ((priority != 1) && (priority != 2))
10618       return 0;
10619    ast_mutex_lock(&dpcache_lock);
10620    dp = find_cache(chan, data, context, exten, priority);
10621    if (dp) {
10622       if (dp->flags & CACHE_FLAG_EXISTS)
10623          res= 1;
10624    }
10625    ast_mutex_unlock(&dpcache_lock);
10626    if (!dp) {
10627       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10628    }
10629    return res;
10630 }

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

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

02840 {
02841    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
02842    ast_mutex_lock(&iaxsl[callno]);
02843    if (iaxs[callno])
02844       iaxs[callno]->owner = newchan;
02845    else
02846       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
02847    ast_mutex_unlock(&iaxsl[callno]);
02848    return 0;
02849 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1285 of file chan_iax2.c.

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

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

01286 {
01287    AST_SCHED_DEL(sched, fr->retrans);
01288    iax_frame_free(fr);
01289 }

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

Definition at line 1191 of file chan_iax2.c.

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_copy_string(), iax2_peer::name, peer_unref(), and realtime_peer().

Referenced by __find_callno().

01192 {
01193    struct iax2_peer *peer = NULL;
01194    int res = 0;
01195    struct ao2_iterator i;
01196 
01197    i = ao2_iterator_init(peers, 0);
01198    while ((peer = ao2_iterator_next(&i))) {
01199       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01200           (peer->addr.sin_port == sin.sin_port)) {
01201          ast_copy_string(host, peer->name, len);
01202          peer_unref(peer);
01203          res = 1;
01204          break;
01205       }
01206       peer_unref(peer);
01207    }
01208 
01209    if (!peer) {
01210       peer = realtime_peer(NULL, &sin);
01211       if (peer) {
01212          ast_copy_string(host, peer->name, len);
01213          peer_unref(peer);
01214          res = 1;
01215       }
01216    }
01217 
01218    return res;
01219 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

Definition at line 3817 of file chan_iax2.c.

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_TRUNK, and peer_unref().

Referenced by check_access().

03818 {
03819    struct iax2_peer *peer;
03820    int res = 0;
03821    struct ao2_iterator i;
03822 
03823    i = ao2_iterator_init(peers, 0);
03824    while ((peer = ao2_iterator_next(&i))) {
03825       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
03826           (peer->addr.sin_port == sin.sin_port)) {
03827          res = ast_test_flag(peer, IAX_TRUNK);
03828          peer_unref(peer);
03829          break;
03830       }
03831       peer_unref(peer);
03832    }
03833 
03834    return res;
03835 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3440 of file chan_iax2.c.

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

03441 {
03442    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03443    struct iax_ie_data ied;
03444    int alreadygone;
03445    memset(&ied, 0, sizeof(ied));
03446    ast_mutex_lock(&iaxsl[callno]);
03447    if (callno && iaxs[callno]) {
03448       if (option_debug)
03449          ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
03450       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03451       /* Send the hangup unless we have had a transmission error or are already gone */
03452       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03453       if (!iaxs[callno]->error && !alreadygone) {
03454          if (send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1)) {
03455             ast_log(LOG_WARNING, "No final packet could be sent for callno %d\n", callno);
03456          }
03457          if (!iaxs[callno]) {
03458             ast_mutex_unlock(&iaxsl[callno]);
03459             return 0;
03460          }
03461       }
03462       /* Explicitly predestroy it */
03463       iax2_predestroy(callno);
03464       /* If we were already gone to begin with, destroy us now */
03465       if (iaxs[callno] && alreadygone) {
03466          if (option_debug)
03467             ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
03468          iax2_destroy(callno);
03469       } else if (iaxs[callno]) {
03470          ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno));
03471       }
03472    } else if (c->tech_pvt) {
03473       /* If this call no longer exists, but the channel still
03474        * references it we need to set the channel's tech_pvt to null
03475        * to avoid ast_channel_free() trying to free it.
03476        */
03477       c->tech_pvt = NULL;
03478    }
03479    ast_mutex_unlock(&iaxsl[callno]);
03480    if (option_verbose > 2) 
03481       ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
03482    return 0;
03483 }

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

Definition at line 3758 of file chan_iax2.c.

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

03759 {
03760    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03761    struct chan_iax2_pvt *pvt;
03762    int res = 0;
03763 
03764    if (option_debug && iaxdebug)
03765       ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
03766 
03767    ast_mutex_lock(&iaxsl[callno]);
03768    pvt = iaxs[callno];
03769 
03770    if (wait_for_peercallno(pvt)) {
03771       res = -1;
03772       goto done;
03773    }
03774 
03775    switch (condition) {
03776    case AST_CONTROL_HOLD:
03777       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03778          ast_moh_start(c, data, pvt->mohinterpret);
03779          goto done;
03780       }
03781       break;
03782    case AST_CONTROL_UNHOLD:
03783       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
03784          ast_moh_stop(c);
03785          goto done;
03786       }
03787    }
03788 
03789    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
03790 
03791 done:
03792    ast_mutex_unlock(&iaxsl[callno]);
03793 
03794    return res;
03795 }

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

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_MATCHMORE, dpcache_lock, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.

10657 {
10658    int res = 0;
10659    struct iax2_dpcache *dp;
10660 #if 0
10661    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
10662 #endif
10663    if ((priority != 1) && (priority != 2))
10664       return 0;
10665    ast_mutex_lock(&dpcache_lock);
10666    dp = find_cache(chan, data, context, exten, priority);
10667    if (dp) {
10668       if (dp->flags & CACHE_FLAG_MATCHMORE)
10669          res= 1;
10670    }
10671    ast_mutex_unlock(&dpcache_lock);
10672    if (!dp) {
10673       ast_log(LOG_WARNING, "Unable to make DP cache\n");
10674    }
10675    return res;
10676 }

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

Definition at line 5077 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05078 {
05079    if (argc < 3 || argc > 4)
05080       return RESULT_SHOWUSAGE;
05081    iaxdebug = 0;
05082    ast_cli(fd, "IAX2 Debugging Disabled\n");
05083    return RESULT_SUCCESS;
05084 }

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

Definition at line 5095 of file chan_iax2.c.

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

05096 {
05097    if (argc < 4 || argc > 5)
05098       return RESULT_SHOWUSAGE;
05099    jb_setoutput(jb_error_output, jb_warning_output, NULL);
05100    jb_debug_output("\n");
05101    ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n");
05102    return RESULT_SUCCESS;
05103 }

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

Definition at line 5086 of file chan_iax2.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

05087 {
05088    if (argc < 4 || argc > 5)
05089       return RESULT_SHOWUSAGE;
05090    iaxtrunkdebug = 0;
05091    ast_cli(fd, "IAX2 Trunk Debugging Disabled\n");
05092    return RESULT_SUCCESS;
05093 }

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

Definition at line 8992 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

08993 {
08994    struct iax2_peer *peer = (struct iax2_peer *)data;
08995    peer->pokeexpire = -1;
08996 #ifdef SCHED_MULTITHREADED
08997    if (schedule_action(__iax2_poke_noanswer, data))
08998 #endif      
08999       __iax2_poke_noanswer(data);
09000    peer_unref(peer);
09001    return 0;
09002 }

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

Definition at line 9013 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, iax2_peer::name, NEW_FORCE, peer_ref(), peer_unref(), chan_iax2_pvt::peerpoke, chan_iax2_pvt::pingtime, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, sched, send_command(), and iax2_peer::sockfd.

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

09014 {
09015    int callno;
09016    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
09017       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
09018         immediately after clearing things out */
09019       peer->lastms = 0;
09020       peer->historicms = 0;
09021       peer->pokeexpire = -1;
09022       peer->callno = 0;
09023       return 0;
09024    }
09025 
09026    /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */
09027    if ((callno = peer->callno) > 0) {
09028       ast_log(LOG_NOTICE, "Still have a callno...\n");
09029       ast_mutex_lock(&iaxsl[callno]);
09030       iax2_destroy(callno);
09031       ast_mutex_unlock(&iaxsl[callno]);
09032    }
09033    if (heldcall)
09034       ast_mutex_unlock(&iaxsl[heldcall]);
09035    callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
09036    if (heldcall)
09037       ast_mutex_lock(&iaxsl[heldcall]);
09038    if (peer->callno < 1) {
09039       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
09040       return -1;
09041    }
09042 
09043    /* Speed up retransmission times for this qualify call */
09044    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
09045    iaxs[peer->callno]->peerpoke = peer;
09046    
09047    /* Remove any pending pokeexpire task */
09048    if (peer->pokeexpire > -1) {
09049       if (!ast_sched_del(sched, peer->pokeexpire)) {
09050          peer->pokeexpire = -1;
09051          peer_unref(peer);
09052       }
09053    }
09054 
09055    /* Queue up a new task to handle no reply */
09056    /* If the host is already unreachable then use the unreachable interval instead */
09057    if (peer->lastms < 0) {
09058       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
09059    } else
09060       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
09061 
09062    if (peer->pokeexpire == -1)
09063       peer_unref(peer);
09064 
09065    /* And send the poke */
09066    ast_mutex_lock(&iaxsl[callno]);
09067    if (iaxs[callno]) {
09068       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
09069    }
09070    ast_mutex_unlock(&iaxsl[callno]);
09071 
09072    return 0;
09073 }

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

Definition at line 9004 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

09005 {
09006    struct iax2_peer *peer = obj;
09007 
09008    iax2_poke_peer(peer, 0);
09009 
09010    return 0;
09011 }

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

Definition at line 6595 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

06596 {
06597    struct iax2_peer *peer = (struct iax2_peer *)data;
06598    peer->pokeexpire = -1;
06599 #ifdef SCHED_MULTITHREADED
06600    if (schedule_action(__iax2_poke_peer_s, data))
06601 #endif      
06602       __iax2_poke_peer_s(data);
06603    return 0;
06604 }

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

02180 {
02181    struct ast_channel *c;
02182    struct chan_iax2_pvt *pvt = iaxs[callno];
02183 
02184    if (!pvt)
02185       return -1;
02186    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
02187       iax2_destroy_helper(pvt);
02188       ast_set_flag(pvt, IAX_ALREADYGONE); 
02189    }
02190    c = pvt->owner;
02191    if (c) {
02192       c->tech_pvt = NULL;
02193       iax2_queue_hangup(callno);
02194       pvt->owner = NULL;
02195       ast_module_unref(ast_module_info->self);
02196    }
02197    return 0;
02198 }

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

Definition at line 8668 of file chan_iax2.c.

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

Referenced by find_idle_thread(), and start_network_thread().

08669 {
08670    struct iax2_thread *thread = data;
08671    struct timeval tv;
08672    struct timespec ts;
08673    int put_into_idle = 0;
08674 
08675    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
08676    pthread_cleanup_push(iax2_process_thread_cleanup, data);
08677    for(;;) {
08678       /* Wait for something to signal us to be awake */
08679       ast_mutex_lock(&thread->lock);
08680 
08681       /* Flag that we're ready to accept signals */
08682       thread->ready_for_signal = 1;
08683       
08684       /* Put into idle list if applicable */
08685       if (put_into_idle)
08686          insert_idle_thread(thread);
08687 
08688       if (thread->type == IAX_TYPE_DYNAMIC) {
08689          struct iax2_thread *t = NULL;
08690          /* Wait to be signalled or time out */
08691          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08692          ts.tv_sec = tv.tv_sec;
08693          ts.tv_nsec = tv.tv_usec * 1000;
08694          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
08695             /* This thread was never put back into the available dynamic
08696              * thread list, so just go away. */
08697             if (!put_into_idle) {
08698                ast_mutex_unlock(&thread->lock);
08699                break;
08700             }
08701             AST_LIST_LOCK(&dynamic_list);
08702             /* Account for the case where this thread is acquired *right* after a timeout */
08703             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
08704                iaxdynamicthreadcount--;
08705             AST_LIST_UNLOCK(&dynamic_list);
08706             if (t) {
08707                /* This dynamic thread timed out waiting for a task and was
08708                 * not acquired immediately after the timeout, 
08709                 * so it's time to go away. */
08710                ast_mutex_unlock(&thread->lock);
08711                break;
08712             }
08713             /* Someone grabbed our thread *right* after we timed out.
08714              * Wait for them to set us up with something to do and signal
08715              * us to continue. */
08716             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
08717             ts.tv_sec = tv.tv_sec;
08718             ts.tv_nsec = tv.tv_usec * 1000;
08719             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
08720             {
08721                ast_mutex_unlock(&thread->lock);
08722                break;
08723             }
08724          }
08725       } else {
08726          ast_cond_wait(&thread->cond, &thread->lock);
08727       }
08728 
08729       /* Go back into our respective list */
08730       put_into_idle = 1;
08731 
08732       ast_mutex_unlock(&thread->lock);
08733 
08734       if (thread->iostate == IAX_IOSTATE_IDLE)
08735          continue;
08736 
08737       /* Add ourselves to the active list now */
08738       AST_LIST_LOCK(&active_list);
08739       AST_LIST_INSERT_HEAD(&active_list, thread, list);
08740       AST_LIST_UNLOCK(&active_list);
08741 
08742       /* See what we need to do */
08743       switch(thread->iostate) {
08744       case IAX_IOSTATE_READY:
08745          thread->actions++;
08746          thread->iostate = IAX_IOSTATE_PROCESSING;
08747          socket_process(thread);
08748          handle_deferred_full_frames(thread);
08749          break;
08750       case IAX_IOSTATE_SCHEDREADY:
08751          thread->actions++;
08752          thread->iostate = IAX_IOSTATE_PROCESSING;
08753 #ifdef SCHED_MULTITHREADED
08754          thread->schedfunc(thread->scheddata);
08755 #endif      
08756          break;
08757       }
08758       time(&thread->checktime);
08759       thread->iostate = IAX_IOSTATE_IDLE;
08760 #ifdef DEBUG_SCHED_MULTITHREAD
08761       thread->curfunc[0]='\0';
08762 #endif      
08763 
08764       /* Now... remove ourselves from the active list, and return to the idle list */
08765       AST_LIST_LOCK(&active_list);
08766       AST_LIST_REMOVE(&active_list, thread, list);
08767       AST_LIST_UNLOCK(&active_list);
08768 
08769       /* Make sure another frame didn't sneak in there after we thought we were done. */
08770       handle_deferred_full_frames(thread);
08771    }
08772 
08773    /*!\note For some reason, idle threads are exiting without being removed
08774     * from an idle list, which is causing memory corruption.  Forcibly remove
08775     * it from the list, if it's there.
08776     */
08777    AST_LIST_LOCK(&idle_list);
08778    AST_LIST_REMOVE(&idle_list, thread, list);
08779    AST_LIST_UNLOCK(&idle_list);
08780 
08781    AST_LIST_LOCK(&dynamic_list);
08782    AST_LIST_REMOVE(&dynamic_list, thread, list);
08783    AST_LIST_UNLOCK(&dynamic_list);
08784 
08785    /* I am exiting here on my own volition, I need to clean up my own data structures
08786    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
08787    */
08788    pthread_cleanup_pop(1);
08789 
08790    return NULL;
08791 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 8659 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

08660 {
08661    struct iax2_thread *thread = data;
08662    ast_mutex_destroy(&thread->lock);
08663    ast_cond_destroy(&thread->cond);
08664    free(thread);
08665    ast_atomic_dec_and_test(&iaxactivethreadcount);
08666 }

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

Definition at line 8947 of file chan_iax2.c.

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

08948 {
08949    int force = 0;
08950    int res;
08951    if (argc < 4)
08952       return RESULT_SHOWUSAGE;
08953    if ((argc > 4)) {
08954       if (!strcasecmp(argv[4], "forced"))
08955          force = 1;
08956       else
08957          return RESULT_SHOWUSAGE;
08958    }
08959    res = iax2_provision(NULL, -1, argv[2], argv[3], force);
08960    if (res < 0)
08961       ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]);
08962    else if (res < 1)
08963       ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]);
08964    else
08965       ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : "");
08966    return RESULT_SUCCESS;
08967 }

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

Definition at line 8850 of file chan_iax2.c.

References iax_prov_complete_template().

08851 {
08852    if (pos != 3)
08853       return NULL;
08854    return iax_prov_complete_template(line, word, pos, state);
08855 }

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

Definition at line 8857 of file chan_iax2.c.

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

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

08858 {
08859    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
08860       is found for template */
08861    struct iax_ie_data provdata;
08862    struct iax_ie_data ied;
08863    unsigned int sig;
08864    struct sockaddr_in sin;
08865    int callno;
08866    struct create_addr_info cai;
08867 
08868    memset(&cai, 0, sizeof(cai));
08869 
08870    if (option_debug)
08871       ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template);
08872 
08873    if (iax_provision_build(&provdata, &sig, template, force)) {
08874       if (option_debug)
08875          ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template);
08876       return 0;
08877    }
08878 
08879    if (end) {
08880       memcpy(&sin, end, sizeof(sin));
08881       cai.sockfd = sockfd;
08882    } else if (create_addr(dest, NULL, &sin, &cai))
08883       return -1;
08884 
08885    /* Build the rest of the message */
08886    memset(&ied, 0, sizeof(ied));
08887    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
08888 
08889    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
08890    if (!callno)
08891       return -1;
08892 
08893    if (iaxs[callno]) {
08894       /* Schedule autodestruct in case they don't ever give us anything back */
08895       AST_SCHED_DEL(sched, iaxs[callno]->autoid);
08896       iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno);
08897       ast_set_flag(iaxs[callno], IAX_PROVISION);
08898       /* Got a call number now, so go ahead and send the provisioning information */
08899       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
08900    }
08901    ast_mutex_unlock(&iaxsl[callno]);
08902 
08903    return 1;
08904 }

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

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

02304 {
02305    struct iax2_peer *peer;
02306 
02307    if (argc != 4)
02308         return RESULT_SHOWUSAGE;
02309    if (!strcmp(argv[3],"all")) {
02310       reload_config();
02311       ast_cli(fd, "OK cache is flushed.\n");
02312    } else if ((peer = find_peer(argv[3], 0))) {
02313       if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02314          ast_set_flag(peer, IAX_RTAUTOCLEAR);
02315          expire_registry(peer_ref(peer));
02316          ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]);
02317       } else {
02318          ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
02319       }
02320       peer_unref(peer);
02321    } else {
02322       ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
02323    }
02324    
02325    return RESULT_SUCCESS;
02326 }

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

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

Referenced by socket_process().

01791 {
01792    for (;;) {
01793       if (iaxs[callno] && iaxs[callno]->owner) {
01794          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01795             /* Avoid deadlock by pausing and trying again */
01796             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01797          } else {
01798             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01799             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01800             break;
01801          }
01802       } else
01803          break;
01804    }
01805    return 0;
01806 }

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

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

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

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

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

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

Referenced by iax2_predestroy().

01759 {
01760    for (;;) {
01761       if (iaxs[callno] && iaxs[callno]->owner) {
01762          if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) {
01763             /* Avoid deadlock by pausing and trying again */
01764             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01765          } else {
01766             ast_queue_hangup(iaxs[callno]->owner);
01767             ast_mutex_unlock(&iaxs[callno]->owner->lock);
01768             break;
01769          }
01770       } else
01771          break;
01772    }
01773    return 0;
01774 }

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

Definition at line 3549 of file chan_iax2.c.

References ast_log(), and LOG_NOTICE.

03550 {
03551    ast_log(LOG_NOTICE, "I should never be called! Hanging up.\n");
03552    return NULL;
03553 }

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

Definition at line 6071 of file chan_iax2.c.

References ast_calloc, ast_copy_string(), ast_dnsmgr_lookup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), copy(), iax2_registry::entry, free, hostname, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, and secret.

Referenced by set_config().

06072 {
06073    struct iax2_registry *reg;
06074    char copy[256];
06075    char *username, *hostname, *secret;
06076    char *porta;
06077    char *stringp=NULL;
06078    
06079    if (!value)
06080       return -1;
06081    ast_copy_string(copy, value, sizeof(copy));
06082    stringp=copy;
06083    username = strsep(&stringp, "@");
06084    hostname = strsep(&stringp, "@");
06085    if (!hostname) {
06086       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
06087       return -1;
06088    }
06089    stringp=username;
06090    username = strsep(&stringp, ":");
06091    secret = strsep(&stringp, ":");
06092    stringp=hostname;
06093    hostname = strsep(&stringp, ":");
06094    porta = strsep(&stringp, ":");
06095    
06096    if (porta && !atoi(porta)) {
06097       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
06098       return -1;
06099    }
06100    if (!(reg = ast_calloc(1, sizeof(*reg))))
06101       return -1;
06102    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
06103       free(reg);
06104       return -1;
06105    }
06106    ast_copy_string(reg->username, username, sizeof(reg->username));
06107    if (secret)
06108       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
06109    reg->expire = -1;
06110    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
06111    reg->addr.sin_family = AF_INET;
06112    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
06113    AST_LIST_LOCK(&registrations);
06114    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
06115    AST_LIST_UNLOCK(&registrations);
06116    
06117    return 0;
06118 }

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

Definition at line 10375 of file chan_iax2.c.

References reload_config().

10376 {
10377    return reload_config();
10378 }

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

Definition at line 9085 of file chan_iax2.c.

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

09086 {
09087    int callno;
09088    int res;
09089    int fmt, native;
09090    struct sockaddr_in sin;
09091    struct ast_channel *c;
09092    struct parsed_dial_string pds;
09093    struct create_addr_info cai;
09094    char *tmpstr;
09095 
09096    memset(&pds, 0, sizeof(pds));
09097    tmpstr = ast_strdupa(data);
09098    parse_dial_string(tmpstr, &pds);
09099 
09100    if (ast_strlen_zero(pds.peer)) {
09101       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
09102       return NULL;
09103    }
09104           
09105    memset(&cai, 0, sizeof(cai));
09106    cai.capability = iax2_capability;
09107 
09108    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
09109    
09110    /* Populate our address from the given */
09111    if (create_addr(pds.peer, NULL, &sin, &cai)) {
09112       *cause = AST_CAUSE_UNREGISTERED;
09113       return NULL;
09114    }
09115 
09116    if (pds.port)
09117       sin.sin_port = htons(atoi(pds.port));
09118 
09119    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
09120    if (callno < 1) {
09121       ast_log(LOG_WARNING, "Unable to create call\n");
09122       *cause = AST_CAUSE_CONGESTION;
09123       return NULL;
09124    }
09125 
09126    /* If this is a trunk, update it now */
09127    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
09128    if (ast_test_flag(&cai, IAX_TRUNK)) {
09129       int new_callno;
09130       if ((new_callno = make_trunk(callno, 1)) != -1)
09131          callno = new_callno;
09132    }
09133    iaxs[callno]->maxtime = cai.maxtime;
09134    if (cai.found)
09135       ast_string_field_set(iaxs[callno], host, pds.peer);
09136 
09137    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
09138 
09139    ast_mutex_unlock(&iaxsl[callno]);
09140 
09141    if (c) {
09142       /* Choose a format we can live with */
09143       if (c->nativeformats & format) 
09144          c->nativeformats &= format;
09145       else {
09146          native = c->nativeformats;
09147          fmt = format;
09148          res = ast_translator_best_choice(&fmt, &native);
09149          if (res < 0) {
09150             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
09151                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
09152             ast_hangup(c);
09153             return NULL;
09154          }
09155          c->nativeformats = native;
09156       }
09157       c->readformat = ast_best_codec(c->nativeformats);
09158       c->writeformat = c->readformat;
09159    }
09160 
09161    return c;
09162 }

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

Definition at line 985 of file chan_iax2.c.

References ast_sched_add(), sched_lock, and signal_condition().

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

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

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

Definition at line 4388 of file chan_iax2.c.

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

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

04389 {
04390    /* Queue a packet for delivery on a given private structure.  Use "ts" for
04391       timestamp, or calculate if ts is 0.  Send immediately without retransmission
04392       or delayed, with retransmission */
04393    struct ast_iax2_full_hdr *fh;
04394    struct ast_iax2_mini_hdr *mh;
04395    struct ast_iax2_video_hdr *vh;
04396    struct {
04397       struct iax_frame fr2;
04398       unsigned char buffer[4096];
04399    } frb;
04400    struct iax_frame *fr;
04401    int res;
04402    int sendmini=0;
04403    unsigned int lastsent;
04404    unsigned int fts;
04405 
04406    frb.fr2.afdatalen = sizeof(frb.buffer);
04407 
04408    if (!pvt) {
04409       ast_log(LOG_WARNING, "No private structure for packet?\n");
04410       return -1;
04411    }
04412    
04413    lastsent = pvt->lastsent;
04414 
04415    /* Calculate actual timestamp */
04416    fts = calc_timestamp(pvt, ts, f);
04417 
04418    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
04419     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
04420     * increment the "predicted timestamps" for voice, if we're predecting */
04421    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
04422        return 0;
04423 
04424 
04425    if ((ast_test_flag(pvt, IAX_TRUNK) || 
04426          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
04427          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
04428       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
04429        (f->frametype == AST_FRAME_VOICE) 
04430       /* is a voice frame */ &&
04431       (f->subclass == pvt->svoiceformat) 
04432       /* is the same type */ ) {
04433          /* Force immediate rather than delayed transmission */
04434          now = 1;
04435          /* Mark that mini-style frame is appropriate */
04436          sendmini = 1;
04437    }
04438    if ( f->frametype == AST_FRAME_VIDEO ) {
04439       /*
04440        * If the lower 15 bits of the timestamp roll over, or if
04441        * the video format changed then send a full frame.
04442        * Otherwise send a mini video frame
04443        */
04444       if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
04445           ((f->subclass & ~0x1) == pvt->svideoformat)
04446          ) {
04447          now = 1;
04448          sendmini = 1;
04449       } else {
04450          now = 0;
04451          sendmini = 0;
04452       }
04453       pvt->lastvsent = fts;
04454    }
04455    /* Allocate an iax_frame */
04456    if (now) {
04457       fr = &frb.fr2;
04458    } else
04459       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));
04460    if (!fr) {
04461       ast_log(LOG_WARNING, "Out of memory\n");
04462       return -1;
04463    }
04464    /* Copy our prospective frame into our immediate or retransmitted wrapper */
04465    iax_frame_wrap(fr, f);
04466 
04467    fr->ts = fts;
04468    fr->callno = pvt->callno;
04469    fr->transfer = transfer;
04470    fr->final = final;
04471    if (!sendmini) {
04472       /* We need a full frame */
04473       if (seqno > -1)
04474          fr->oseqno = seqno;
04475       else
04476          fr->oseqno = pvt->oseqno++;
04477       fr->iseqno = pvt->iseqno;
04478       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
04479       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
04480       fh->ts = htonl(fr->ts);
04481       fh->oseqno = fr->oseqno;
04482       if (transfer) {
04483          fh->iseqno = 0;
04484       } else
04485          fh->iseqno = fr->iseqno;
04486       /* Keep track of the last thing we've acknowledged */
04487       if (!transfer)
04488          pvt->aseqno = fr->iseqno;
04489       fh->type = fr->af.frametype & 0xFF;
04490       if (fr->af.frametype == AST_FRAME_VIDEO)
04491          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
04492       else
04493          fh->csub = compress_subclass(fr->af.subclass);
04494       if (transfer) {
04495          fr->dcallno = pvt->transfercallno;
04496       } else
04497          fr->dcallno = pvt->peercallno;
04498       fh->dcallno = htons(fr->dcallno);
04499       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
04500       fr->data = fh;
04501       fr->retries = 0;
04502       /* Retry after 2x the ping time has passed */
04503       fr->retrytime = pvt->pingtime * 2;
04504       if (fr->retrytime < MIN_RETRY_TIME)
04505          fr->retrytime = MIN_RETRY_TIME;
04506       if (fr->retrytime > MAX_RETRY_TIME)
04507          fr->retrytime = MAX_RETRY_TIME;
04508       /* Acks' don't get retried */
04509       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
04510          fr->retries = -1;
04511       else if (f->frametype == AST_FRAME_VOICE)
04512          pvt->svoiceformat = f->subclass;
04513       else if (f->frametype == AST_FRAME_VIDEO)
04514          pvt->svideoformat = f->subclass & ~0x1;
04515       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04516          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04517             if (iaxdebug) {
04518                if (fr->transfer)
04519                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04520                else
04521                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
04522             }
04523             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
04524          } else
04525             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04526       }
04527    
04528       if (now) {
04529          res = send_packet(fr);
04530       } else
04531          res = iax2_transmit(fr);
04532    } else {
04533       if (ast_test_flag(pvt, IAX_TRUNK)) {
04534          iax2_trunk_queue(pvt, fr);
04535          res = 0;
04536       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
04537          /* Video frame have no sequence number */
04538          fr->oseqno = -1;
04539          fr->iseqno = -1;
04540          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
04541          vh->zeros = 0;
04542          vh->callno = htons(0x8000 | fr->callno);
04543          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
04544          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
04545          fr->data = vh;
04546          fr->retries = -1;
04547          res = send_packet(fr);        
04548       } else {
04549          /* Mini-frames have no sequence number */
04550          fr->oseqno = -1;
04551          fr->iseqno = -1;
04552          /* Mini frame will do */
04553          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
04554          mh->callno = htons(fr->callno);
04555          mh->ts = htons(fr->ts & 0xFFFF);
04556          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
04557          fr->data = mh;
04558          fr->retries = -1;
04559          if (pvt->transferring == TRANSFER_MEDIAPASS)
04560             fr->transfer = 1;
04561          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
04562             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
04563                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
04564             } else
04565                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
04566          }
04567          res = send_packet(fr);
04568       }
04569    }
04570    return res;
04571 }

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

Definition at line 2834 of file chan_iax2.c.

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

02835 {
02836    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
02837 }

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

Definition at line 2829 of file chan_iax2.c.

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

02830 {
02831    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
02832 }

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

Definition at line 2822 of file chan_iax2.c.

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

02823 {
02824    
02825    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
02826       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
02827 }

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

Definition at line 3507 of file chan_iax2.c.

References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, errno, free, iaxs, iaxsl, PTR_TO_CALLNO, send_command_locked(), ast_channel::tech_pvt, and wait_for_peercallno().

03508 {
03509    struct ast_option_header *h;
03510    int res;
03511 
03512    switch (option) {
03513    case AST_OPTION_TXGAIN:
03514    case AST_OPTION_RXGAIN:
03515       /* these two cannot be sent, because they require a result */
03516       errno = ENOSYS;
03517       return -1;
03518    default:
03519    {
03520       unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03521       struct chan_iax2_pvt *pvt;
03522 
03523       ast_mutex_lock(&iaxsl[callno]);
03524       pvt = iaxs[callno];
03525 
03526       if (wait_for_peercallno(pvt)) {
03527          ast_mutex_unlock(&iaxsl[callno]);
03528          return -1;
03529       }
03530 
03531       ast_mutex_unlock(&iaxsl[callno]);
03532 
03533       if (!(h = ast_malloc(datalen + sizeof(*h)))) {
03534          return -1;
03535       }
03536 
03537       h->flag = AST_OPTION_FLAG_REQUEST;
03538       h->option = htons(option);
03539       memcpy(h->data, data, datalen);
03540       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03541                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03542                  datalen + sizeof(*h), -1);
03543       free(h);
03544       return res;
03545    }
03546    }
03547 }

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

Definition at line 2507 of file chan_iax2.c.

References ast_cli(), ast_copy_string(), 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, dpcache_lock, iax2_dpcache::expiry, iax2_dpcache::exten, iax2_dpcache::flags, iax2_dpcache::next, iax2_dpcache::peercontext, RESULT_SUCCESS, s, and iax2_dpcache::waiters.

02508 {
02509    struct iax2_dpcache *dp;
02510    char tmp[1024], *pc;
02511    int s;
02512    int x,y;
02513    struct timeval tv;
02514    gettimeofday(&tv, NULL);
02515    ast_mutex_lock(&dpcache_lock);
02516    dp = dpcache;
02517    ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02518    while(dp) {
02519       s = dp->expiry.tv_sec - tv.tv_sec;
02520       tmp[0] = '\0';
02521       if (dp->flags & CACHE_FLAG_EXISTS)
02522          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02523       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02524          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02525       if (dp->flags & CACHE_FLAG_CANEXIST)
02526          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02527       if (dp->flags & CACHE_FLAG_PENDING)
02528          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02529       if (dp->flags & CACHE_FLAG_TIMEOUT)
02530          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02531       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02532          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02533       if (dp->flags & CACHE_FLAG_MATCHMORE)
02534          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02535       if (dp->flags & CACHE_FLAG_UNKNOWN)
02536          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02537       /* Trim trailing pipe */
02538       if (!ast_strlen_zero(tmp))
02539          tmp[strlen(tmp) - 1] = '\0';
02540       else
02541          ast_copy_string(tmp, "(none)", sizeof(tmp));
02542       y=0;
02543       pc = strchr(dp->peercontext, '@');
02544       if (!pc)
02545          pc = dp->peercontext;
02546       else
02547          pc++;
02548       for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
02549          if (dp->waiters[x] > -1)
02550             y++;
02551       if (s > 0)
02552          ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02553       else
02554          ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02555       dp = dp->next;
02556    }
02557    ast_mutex_unlock(&dpcache_lock);
02558    return RESULT_SUCCESS;
02559 }

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

Definition at line 4915 of file chan_iax2.c.

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

04916 {
04917 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s\n"
04918 #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"
04919 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
04920    int x;
04921    int numchans = 0;
04922 
04923    if (argc != 3)
04924       return RESULT_SHOWUSAGE;
04925    ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
04926    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
04927       ast_mutex_lock(&iaxsl[x]);
04928       if (iaxs[x]) {
04929          int lag, jitter, localdelay;
04930          jb_info jbinfo;
04931          
04932          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
04933             jb_getinfo(iaxs[x]->jb, &jbinfo);
04934             jitter = jbinfo.jitter;
04935             localdelay = jbinfo.current - jbinfo.min;
04936          } else {
04937             jitter = -1;
04938             localdelay = 0;
04939          }
04940          lag = iaxs[x]->remote_rr.delay;
04941          ast_cli(fd, FORMAT,
04942             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
04943             ast_inet_ntoa(iaxs[x]->addr.sin_addr), 
04944             S_OR(iaxs[x]->username, "(None)"),
04945             iaxs[x]->callno, iaxs[x]->peercallno,
04946             iaxs[x]->oseqno, iaxs[x]->iseqno,
04947             lag,
04948             jitter,
04949             localdelay,
04950             ast_getformatname(iaxs[x]->voiceformat) );
04951          numchans++;
04952       }
04953       ast_mutex_unlock(&iaxsl[x]);
04954    }
04955    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
04956    return RESULT_SUCCESS;
04957 #undef FORMAT
04958 #undef FORMAT2
04959 #undef FORMATB
04960 }

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

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

04827 {
04828 #define FORMAT2 "%-15.15s  %-15.15s %-15.15s\n"
04829 #if !defined(__FreeBSD__)
04830 #define FORMAT "%-15.15s  %-15d %-15d\n"
04831 #else /* __FreeBSD__ */
04832 #define FORMAT "%-15.15s  %-15d %-15d\n" /* XXX 2.95 ? */
04833 #endif /* __FreeBSD__ */
04834    struct iax_firmware *cur;
04835    if ((argc != 3) && (argc != 4))
04836       return RESULT_SHOWUSAGE;
04837    ast_mutex_lock(&waresl.lock);
04838    
04839    ast_cli(fd, FORMAT2, "Device", "Version", "Size");
04840    for (cur = waresl.wares;cur;cur = cur->next) {
04841       if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 
04842          ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
04843             (int)ntohl(cur->fwh->datalen));
04844    }
04845    ast_mutex_unlock(&waresl.lock);
04846    return RESULT_SUCCESS;
04847 #undef FORMAT
04848 #undef FORMAT2
04849 }

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

Definition at line 5038 of file chan_iax2.c.

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

05039 {
05040    int numchans = 0;
05041    if (argc != 3)
05042       return RESULT_SHOWUSAGE;
05043    ast_cli(fd, "                                -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
05044    ast_cli(fd, "Channel                    RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts\n");
05045    numchans = ast_cli_netstats(NULL, fd, 1);
05046    ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
05047    return RESULT_SUCCESS;
05048 }

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

Show one peer in detail.

Definition at line 2397 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::cid_name, iax2_peer::cid_num, iax2_peer::context, iax2_peer::defaddr, iax2_peer::expire, find_peer(), iax2_peer::ha, IAX_DYNAMIC, iax2_peer::mailbox, iax2_peer::name, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_peer::prefs, RESULT_SHOWUSAGE, RESULT_SUCCESS, iax2_peer::secret, iax2_peer::smoothing, and iax2_peer::username.

02398 {
02399    char status[30];
02400    char cbuf[256];
02401    struct iax2_peer *peer;
02402    char codec_buf[512];
02403    int x = 0, codec = 0, load_realtime = 0;
02404 
02405    if (argc < 4)
02406       return RESULT_SHOWUSAGE;
02407 
02408    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0;
02409 
02410    peer = find_peer(argv[3], load_realtime);
02411    if (peer) {
02412       ast_cli(fd,"\n\n");
02413       ast_cli(fd, "  * Name       : %s\n", peer->name);
02414       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
02415       ast_cli(fd, "  Context      : %s\n", peer->context);
02416       ast_cli(fd, "  Mailbox      : %s\n", peer->mailbox);
02417       ast_cli(fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No");
02418       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02419       ast_cli(fd, "  Expire       : %d\n", peer->expire);
02420       ast_cli(fd, "  ACL          : %s\n", (peer->ha?"Yes":"No"));
02421       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));
02422       ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02423       ast_cli(fd, "  Username     : %s\n", peer->username);
02424       ast_cli(fd, "  Codecs       : ");
02425       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02426       ast_cli(fd, "%s\n", codec_buf);
02427 
02428       ast_cli(fd, "  Codec Order  : (");
02429       for(x = 0; x < 32 ; x++) {
02430          codec = ast_codec_pref_index(&peer->prefs,x);
02431          if(!codec)
02432             break;
02433          ast_cli(fd, "%s", ast_getformatname(codec));
02434          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02435             ast_cli(fd, "|");
02436       }
02437 
02438       if (!x)
02439          ast_cli(fd, "none");
02440       ast_cli(fd, ")\n");
02441 
02442       ast_cli(fd, "  Status       : ");
02443       peer_status(peer, status, sizeof(status));   
02444       ast_cli(fd, "%s\n",status);
02445       ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02446       ast_cli(fd,"\n");
02447       peer_unref(peer);
02448    } else {
02449       ast_cli(fd,"Peer %s not found.\n", argv[3]);
02450       ast_cli(fd,"\n");
02451    }
02452 
02453    return RESULT_SUCCESS;
02454 }

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

Definition at line 4815 of file chan_iax2.c.

References __iax2_show_peers().

04816 {
04817    return __iax2_show_peers(0, fd, NULL, argc, argv);
04818 }

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

Definition at line 4887 of file chan_iax2.c.

References iax2_registry::addr, ast_cli(), ast_copy_string(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax2_registry::dnsmgr, iax2_registry::entry, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), RESULT_SHOWUSAGE, RESULT_SUCCESS, iax2_registry::us, and iax2_registry::username.

04888 {
04889 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
04890 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
04891    struct iax2_registry *reg = NULL;
04892 
04893    char host[80];
04894    char perceived[80];
04895    if (argc != 3)
04896       return RESULT_SHOWUSAGE;
04897    ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
04898    AST_LIST_LOCK(&registrations);
04899    AST_LIST_TRAVERSE(&registrations, reg, entry) {
04900       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
04901       if (reg->us.sin_addr.s_addr) 
04902          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
04903       else
04904          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
04905       ast_cli(fd, FORMAT, host, 
04906                (reg->dnsmgr) ? "Y" : "N", 
04907                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
04908    }
04909    AST_LIST_UNLOCK(&registrations);
04910    return RESULT_SUCCESS;
04911 #undef FORMAT
04912 #undef FORMAT2
04913 }

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

Definition at line 2481 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, iax_frame::list, ast_iax2_queue::queue, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax_frame::retries.

02482 {
02483    struct iax_frame *cur;
02484    int cnt = 0, dead=0, final=0;
02485 
02486    if (argc != 3)
02487       return RESULT_SHOWUSAGE;
02488 
02489    AST_LIST_LOCK(&iaxq.queue);
02490    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
02491       if (cur->retries < 0)
02492          dead++;
02493       if (cur->final)
02494          final++;
02495       cnt++;
02496    }
02497    AST_LIST_UNLOCK(&iaxq.queue);
02498 
02499    ast_cli(fd, "    IAX Statistics\n");
02500    ast_cli(fd, "---------------------\n");
02501    ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02502    ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02503    
02504    return RESULT_SUCCESS;
02505 }

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

Definition at line 4756 of file chan_iax2.c.

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

04757 {
04758    struct iax2_thread *thread = NULL;
04759    time_t t;
04760    int threadcount = 0, dynamiccount = 0;
04761    char type;
04762 
04763    if (argc != 3)
04764       return RESULT_SHOWUSAGE;
04765       
04766    ast_cli(fd, "IAX2 Thread Information\n");
04767    time(&t);
04768    ast_cli(fd, "Idle Threads:\n");
04769    AST_LIST_LOCK(&idle_list);
04770    AST_LIST_TRAVERSE(&idle_list, thread, list) {
04771 #ifdef DEBUG_SCHED_MULTITHREAD
04772       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04773          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04774 #else
04775       ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
04776          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04777 #endif
04778       threadcount++;
04779    }
04780    AST_LIST_UNLOCK(&idle_list);
04781    ast_cli(fd, "Active Threads:\n");
04782    AST_LIST_LOCK(&active_list);
04783    AST_LIST_TRAVERSE(&active_list, thread, list) {
04784       if (thread->type == IAX_TYPE_DYNAMIC)
04785          type = 'D';
04786       else
04787          type = 'P';
04788 #ifdef DEBUG_SCHED_MULTITHREAD
04789       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 
04790          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04791 #else
04792       ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
04793          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04794 #endif
04795       threadcount++;
04796    }
04797    AST_LIST_UNLOCK(&active_list);
04798    ast_cli(fd, "Dynamic Threads:\n");
04799         AST_LIST_LOCK(&dynamic_list);
04800         AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
04801 #ifdef DEBUG_SCHED_MULTITHREAD
04802                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n",
04803                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
04804 #else
04805                 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n",
04806                         thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
04807 #endif
04808       dynamiccount++;
04809         }
04810         AST_LIST_UNLOCK(&dynamic_list);
04811    ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
04812    return RESULT_SUCCESS;
04813 }

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

Definition at line 4573 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_copy_string(), 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, iax2_user::inkeys, iax2_user::name, RESULT_SHOWUSAGE, RESULT_SUCCESS, iax2_user::secret, and user_unref().

04574 {
04575    regex_t regexbuf;
04576    int havepattern = 0;
04577 
04578 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
04579 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
04580 
04581    struct iax2_user *user = NULL;
04582    char auth[90];
04583    char *pstr = "";
04584    struct ao2_iterator i;
04585 
04586    switch (argc) {
04587    case 5:
04588       if (!strcasecmp(argv[3], "like")) {
04589          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
04590             return RESULT_SHOWUSAGE;
04591          havepattern = 1;
04592       } else
04593          return RESULT_SHOWUSAGE;
04594    case 3:
04595       break;
04596    default:
04597       return RESULT_SHOWUSAGE;
04598    }
04599 
04600    ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
04601    i = ao2_iterator_init(users, 0);
04602    for (user = ao2_iterator_next(&i); user; 
04603       user_unref(user), user = ao2_iterator_next(&i)) {
04604       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
04605          continue;
04606       
04607       if (!ast_strlen_zero(user->secret)) {
04608          ast_copy_string(auth,user->secret,sizeof(auth));
04609       } else if (!ast_strlen_zero(user->inkeys)) {
04610          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
04611       } else
04612          ast_copy_string(auth, "-no secret-", sizeof(auth));
04613       
04614       if(ast_test_flag(user,IAX_CODEC_NOCAP))
04615          pstr = "REQ Only";
04616       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
04617          pstr = "Disabled";
04618       else
04619          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
04620       
04621       ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
04622          user->contexts ? user->contexts->context : context,
04623          user->ha ? "Yes" : "No", pstr);
04624    }
04625 
04626    if (havepattern)
04627       regfree(&regexbuf);
04628 
04629    return RESULT_SUCCESS;
04630 #undef FORMAT
04631 #undef FORMAT2
04632 }

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

Definition at line 3555 of file chan_iax2.c.

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

03556 {
03557    int res;
03558    struct iax_ie_data ied0;
03559    struct iax_ie_data ied1;
03560    unsigned int transferid = (unsigned int)ast_random();
03561    memset(&ied0, 0, sizeof(ied0));
03562    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03563    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03564    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03565 
03566    memset(&ied1, 0, sizeof(ied1));
03567    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03568    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03569    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03570    
03571    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03572    if (res)
03573       return -1;
03574    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03575    if (res)
03576       return -1;
03577    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03578    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03579    return 0;
03580 }

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

Definition at line 2328 of file chan_iax2.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02329 {
02330        if (argc != 4)
02331                return RESULT_SHOWUSAGE;
02332 
02333        test_losspct = atoi(argv[3]);
02334 
02335        return RESULT_SUCCESS;
02336 }

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

Definition at line 3797 of file chan_iax2.c.

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

03798 {
03799    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03800    struct iax_ie_data ied;
03801    char tmp[256], *context;
03802    ast_copy_string(tmp, dest, sizeof(tmp));
03803    context = strchr(tmp, '@');
03804    if (context) {
03805       *context = '\0';
03806       context++;
03807    }
03808    memset(&ied, 0, sizeof(ied));
03809    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
03810    if (context)
03811       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
03812    if (option_debug)
03813       ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
03814    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
03815 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

Definition at line 2793 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, ast_iax2_queue::count, iaxq, ast_iax2_queue::queue, sched_lock, iax_frame::sentyet, and signal_condition().

Referenced by iax2_send().

02794 {
02795    /* Lock the queue and place this packet at the end */
02796    /* By setting this to 0, the network thread will send it for us, and
02797       queue retransmission if necessary */
02798    fr->sentyet = 0;
02799    AST_LIST_LOCK(&iaxq.queue);
02800    AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list);
02801    iaxq.count++;
02802    AST_LIST_UNLOCK(&iaxq.queue);
02803    /* Wake up the network and scheduler thread */
02804    if (netthreadid != AST_PTHREADT_NULL)
02805       pthread_kill(netthreadid, SIGURG);
02806    signal_condition(&sched_lock, &sched_cond);
02807    return 0;
02808 }

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

Definition at line 6650 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

06651 {
06652    /* Drop when trunk is about 5 seconds idle */
06653    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
06654       return 1;
06655    return 0;
06656 }

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

Definition at line 4162 of file chan_iax2.c.

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

Referenced by iax2_send().

04163 {
04164    struct ast_frame *f;
04165    struct iax2_trunk_peer *tpeer;
04166    void *tmp, *ptr;
04167    struct ast_iax2_meta_trunk_entry *met;
04168    struct ast_iax2_meta_trunk_mini *mtm;
04169 
04170    f = &fr->af;
04171    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
04172    if (tpeer) {
04173       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
04174          /* Need to reallocate space */
04175          if (tpeer->trunkdataalloc < MAX_TRUNKDATA) {
04176             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
04177                ast_mutex_unlock(&tpeer->lock);
04178                return -1;
04179             }
04180             
04181             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
04182             tpeer->trunkdata = tmp;
04183             if (option_debug)
04184                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);
04185          } else {
04186             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));
04187             ast_mutex_unlock(&tpeer->lock);
04188             return -1;
04189          }
04190       }
04191 
04192       /* Append to meta frame */
04193       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
04194       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
04195          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
04196          mtm->len = htons(f->datalen);
04197          mtm->mini.callno = htons(pvt->callno);
04198          mtm->mini.ts = htons(0xffff & fr->ts);
04199          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
04200          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
04201       } else {
04202          met = (struct ast_iax2_meta_trunk_entry *)ptr;
04203          /* Store call number and length in meta header */
04204          met->callno = htons(pvt->callno);
04205          met->len = htons(f->datalen);
04206          /* Advance pointers/decrease length past trunk entry header */
04207          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
04208          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
04209       }
04210       /* Copy actual trunk data */
04211       memcpy(ptr, f->data, f->datalen);
04212       tpeer->trunkdatalen += f->datalen;
04213 
04214       tpeer->calls++;
04215       ast_mutex_unlock(&tpeer->lock);
04216    }
04217    return 0;
04218 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 6567 of file chan_iax2.c.

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

Referenced by socket_process().

06568 {
06569    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
06570 }

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

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

05106 {
05107    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
05108    int res = -1;
05109    ast_mutex_lock(&iaxsl[callno]);
05110    if (iaxs[callno]) {
05111    /* If there's an outstanding error, return failure now */
05112       if (!iaxs[callno]->error) {
05113          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
05114             res = 0;
05115             /* Don't waste bandwidth sending null frames */
05116          else if (f->frametype == AST_FRAME_NULL)
05117             res = 0;
05118          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
05119             res = 0;
05120          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
05121             res = 0;
05122          else
05123          /* Simple, just queue for transmission */
05124             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
05125       } else {
05126          if (option_debug)
05127             ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
05128       }
05129    }
05130    /* If it's already gone, just return */
05131    ast_mutex_unlock(&iaxsl[callno]);
05132    return res;
05133 }

static int iax_check_version ( char *  dev  )  [static]

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

01963 {
01964    int res = 0;
01965    struct iax_firmware *cur;
01966    if (!ast_strlen_zero(dev)) {
01967       ast_mutex_lock(&waresl.lock);
01968       cur = waresl.wares;
01969       while(cur) {
01970          if (!strcmp(dev, (char *)cur->fwh->devname)) {
01971             res = ntohs(cur->fwh->version);
01972             break;
01973          }
01974          cur = cur->next;
01975       }
01976       ast_mutex_unlock(&waresl.lock);
01977    }
01978    return res;
01979 }

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

Definition at line 763 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

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

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

Definition at line 769 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

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

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

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

01982 {
01983    int res = -1;
01984    unsigned int bs = desc & 0xff;
01985    unsigned int start = (desc >> 8) & 0xffffff;
01986    unsigned int bytes;
01987    struct iax_firmware *cur;
01988    if (!ast_strlen_zero((char *)dev) && bs) {
01989       start *= bs;
01990       ast_mutex_lock(&waresl.lock);
01991       cur = waresl.wares;
01992       while(cur) {
01993          if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
01994             iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
01995             if (start < ntohl(cur->fwh->datalen)) {
01996                bytes = ntohl(cur->fwh->datalen) - start;
01997                if (bytes > bs)
01998                   bytes = bs;
01999                iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
02000             } else {
02001                bytes = 0;
02002                iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
02003             }
02004             if (bytes == bs)
02005                res = 0;
02006             else
02007                res = 1;
02008             break;
02009          }
02010          cur = cur->next;
02011       }
02012       ast_mutex_unlock(&waresl.lock);
02013    }
02014    return res;
02015 }

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

Definition at line 6838 of file chan_iax2.c.

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

Referenced by socket_process().

06839 {
06840    struct iax_dual *d;
06841    struct ast_channel *chan1m, *chan2m;
06842    pthread_t th;
06843    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
06844    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
06845    if (chan2m && chan1m) {
06846       /* Make formats okay */
06847       chan1m->readformat = chan1->readformat;
06848       chan1m->writeformat = chan1->writeformat;
06849       ast_channel_masquerade(chan1m, chan1);
06850       /* Setup the extensions and such */
06851       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
06852       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
06853       chan1m->priority = chan1->priority;
06854       
06855       /* We make a clone of the peer channel too, so we can play
06856          back the announcement */
06857       /* Make formats okay */
06858       chan2m->readformat = chan2->readformat;
06859       chan2m->writeformat = chan2->writeformat;
06860       ast_channel_masquerade(chan2m, chan2);
06861       /* Setup the extensions and such */
06862       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
06863       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
06864       chan2m->priority = chan2->priority;
06865       if (ast_do_masquerade(chan2m)) {
06866          ast_log(LOG_WARNING, "Masquerade failed :(\n");
06867          ast_hangup(chan2m);
06868          return -1;
06869       }
06870    } else {
06871       if (chan1m)
06872          ast_hangup(chan1m);
06873       if (chan2m)
06874          ast_hangup(chan2m);
06875       return -1;
06876    }
06877    if ((d = ast_calloc(1, sizeof(*d)))) {
06878       pthread_attr_t attr;
06879 
06880       pthread_attr_init(&attr);
06881       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
06882 
06883       d->chan1 = chan1m;
06884       d->chan2 = chan2m;
06885       if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
06886          pthread_attr_destroy(&attr);
06887          return 0;
06888       }
06889       pthread_attr_destroy(&attr);
06890       free(d);
06891    }
06892    return -1;
06893 }

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

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

06819 {
06820    struct ast_channel *chan1, *chan2;
06821    struct iax_dual *d;
06822    struct ast_frame *f;
06823    int ext;
06824    int res;
06825    d = stuff;
06826    chan1 = d->chan1;
06827    chan2 = d->chan2;
06828    free(d);
06829    f = ast_read(chan1);
06830    if (f)
06831       ast_frfree(f);
06832    res = ast_park_call(chan1, chan2, 0, &ext);
06833    ast_hangup(chan2);
06834    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
06835    return NULL;
06836 }

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

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

01438 {
01439    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01440    if (new) {
01441       size_t afdatalen = new->afdatalen;
01442       memcpy(new, fr, sizeof(*new));
01443       iax_frame_wrap(new, &fr->af);
01444       new->afdatalen = afdatalen;
01445       new->data = NULL;
01446       new->datalen = 0;
01447       new->direction = DIRECTION_INGRESS;
01448       new->retrans = -1;
01449    }
01450    return new;
01451 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 893 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

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

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

Definition at line 798 of file chan_iax2.c.

References ast_verbose().

Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().

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

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

Definition at line 774 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

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

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

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

Definition at line 786 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

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

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

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 11219 of file chan_iax2.c.

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

11220 {
11221    char *config = "iax.conf";
11222    int res = 0;
11223    int x;
11224    struct iax2_registry *reg = NULL;
11225 
11226    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
11227    if (!peers)
11228       return AST_MODULE_LOAD_FAILURE;
11229    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
11230    if (!users) {
11231       ao2_ref(peers, -1);
11232       return AST_MODULE_LOAD_FAILURE;
11233    }
11234    iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
11235    if (!iax_peercallno_pvts) {
11236       ao2_ref(peers, -1);
11237       ao2_ref(users, -1);
11238       return AST_MODULE_LOAD_FAILURE;
11239    }
11240 
11241    ast_custom_function_register(&iaxpeer_function);
11242 
11243    iax_set_output(iax_debug_output);
11244    iax_set_error(iax_error_output);
11245    jb_setoutput(jb_error_output, jb_warning_output, NULL);
11246    
11247 #ifdef HAVE_DAHDI
11248 #ifdef DAHDI_TIMERACK
11249    timingfd = open(DAHDI_FILE_TIMER, O_RDWR);
11250    if (timingfd < 0)
11251 #endif
11252       timingfd = open(DAHDI_FILE_PSEUDO, O_RDWR);
11253    if (timingfd < 0) 
11254       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
11255 #endif
11256 
11257    memset(iaxs, 0, sizeof(iaxs));
11258 
11259    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
11260       ast_mutex_init(&iaxsl[x]);
11261    }
11262    
11263    ast_cond_init(&sched_cond, NULL);
11264 
11265    io = io_context_create();
11266    sched = sched_context_create();
11267    
11268    if (!io || !sched) {
11269       ast_log(LOG_ERROR, "Out of memory\n");
11270       return -1;
11271    }
11272 
11273    netsock = ast_netsock_list_alloc();
11274    if (!netsock) {
11275       ast_log(LOG_ERROR, "Could not allocate netsock list.\n");
11276       return -1;
11277    }
11278    ast_netsock_init(netsock);
11279 
11280    outsock = ast_netsock_list_alloc();
11281    if (!outsock) {
11282       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
11283       return -1;
11284    }
11285    ast_netsock_init(outsock);
11286 
11287    ast_mutex_init(&waresl.lock);
11288 
11289    AST_LIST_HEAD_INIT(&iaxq.queue);
11290    
11291    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
11292 
11293    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
11294    
11295    ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" );
11296    ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" );
11297 
11298    if(set_config(config, 0) == -1)
11299       return AST_MODULE_LOAD_DECLINE;
11300 
11301    if (ast_channel_register(&iax2_tech)) {
11302       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
11303       __unload_module();
11304       return -1;
11305    }
11306 
11307    if (ast_register_switch(&iax2_switch)) 
11308       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
11309 
11310    res = start_network_thread();
11311    if (!res) {
11312       if (option_verbose > 1) 
11313          ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n");
11314    } else {
11315       ast_log(LOG_ERROR, "Unable to start network thread\n");
11316       ast_netsock_release(netsock);
11317       ast_netsock_release(outsock);
11318    }
11319 
11320    AST_LIST_LOCK(&registrations);
11321    AST_LIST_TRAVERSE(&registrations, reg, entry)
11322       iax2_do_register(reg);
11323    AST_LIST_UNLOCK(&registrations); 
11324 
11325    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
11326    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
11327 
11328    reload_firmware(0);
11329    iax_provision_reload();
11330    return res;
11331 }

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

Definition at line 3582 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03583 {
03584    ast_mutex_lock(&iaxsl[callno0]);
03585    while (ast_mutex_trylock(&iaxsl[callno1])) {
03586       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03587    }
03588 }

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

Definition at line 1491 of file chan_iax2.c.

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

Referenced by iax2_request(), and socket_process().

01492 {
01493    int x;
01494    int res= 0;
01495    struct timeval now;
01496    if (iaxs[callno]->oseqno) {
01497       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01498       return -1;
01499    }
01500    if (callno & TRUNK_CALL_START) {
01501       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01502       return -1;
01503    }
01504    gettimeofday(&now, NULL);
01505    for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
01506       ast_mutex_lock(&iaxsl[x]);
01507       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01508          /* Update the two timers that should have been started */
01509          /*!
01510           * \note We delete these before switching the slot, because if
01511           * they fire in the meantime, they will generate a warning.
01512           */
01513          AST_SCHED_DEL(sched, iaxs[callno]->pingid);
01514          AST_SCHED_DEL(sched, iaxs[callno]->lagid);
01515          iaxs[x] = iaxs[callno];
01516          iaxs[x]->callno = x;
01517          iaxs[callno] = NULL;
01518          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01519          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01520          if (locked)
01521             ast_mutex_unlock(&iaxsl[callno]);
01522          res = x;
01523          if (!locked)
01524             ast_mutex_unlock(&iaxsl[x]);
01525          break;
01526       }
01527       ast_mutex_unlock(&iaxsl[x]);
01528    }
01529    if (x >= ARRAY_LEN(iaxs) - 1) {
01530       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01531       return -1;
01532    }
01533    if (option_debug)
01534       ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x);
01535    /* We move this call from a non-trunked to a trunked call */
01536    update_max_trunk();
01537    update_max_nontrunk();
01538    return res;
01539 }

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

Definition at line 4819 of file chan_iax2.c.

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

Referenced by load_module().

04820 {
04821    ast_cli_netstats(s, -1, 0);
04822    astman_append(s, "\r\n");
04823    return RESULT_SUCCESS;
04824 }

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

Definition at line 4852 of file chan_iax2.c.

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

Referenced by load_module().

04853 {
04854    char *a[] = { "iax2", "show", "users" };
04855    int ret;
04856    const char *id = astman_get_header(m,"ActionID");
04857 
04858    if (!ast_strlen_zero(id))
04859       astman_append(s, "ActionID: %s\r\n",id);
04860    ret = __iax2_show_peers(1, -1, s, 3, a );
04861    astman_append(s, "\r\n\r\n" );
04862    return ret;
04863 } /* /JDG */

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

Definition at line 1457 of file chan_iax2.c.

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

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

01458 {
01459    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01460       (cur->addr.sin_port == sin->sin_port)) {
01461       /* This is the main host */
01462       if ( (cur->peercallno == 0 || cur->peercallno == callno) &&
01463           (check_dcallno ? dcallno == cur->callno : 1) ) {
01464          /* That's us.  Be sure we keep track of the peer call number */
01465          return 1;
01466       }
01467    }
01468    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01469        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01470       /* We're transferring */
01471       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01472          return 1;
01473    }
01474    return 0;
01475 }

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

Definition at line 4226 of file chan_iax2.c.

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

Referenced by decode_frame().

04227 {
04228 #if 0
04229    /* Debug with "fake encryption" */
04230    int x;
04231    if (len % 16)
04232       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04233    for (x=0;x<len;x++)
04234       dst[x] = src[x] ^ 0xff;
04235 #else 
04236    unsigned char lastblock[16] = { 0 };
04237    int x;
04238    while(len > 0) {
04239       aes_decrypt(src, dst, dcx);
04240       for (x=0;x<16;x++)
04241          dst[x] ^= lastblock[x];
04242       memcpy(lastblock, src, sizeof(lastblock));
04243       dst += 16;
04244       src += 16;
04245       len -= 16;
04246    }
04247 #endif
04248 }

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

Definition at line 4250 of file chan_iax2.c.

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

Referenced by encrypt_frame().

04251 {
04252 #if 0
04253    /* Debug with "fake encryption" */
04254    int x;
04255    if (len % 16)
04256       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04257    for (x=0;x<len;x++)
04258       dst[x] = src[x] ^ 0xff;
04259 #else
04260    unsigned char curblock[16] = { 0 };
04261    int x;
04262    while(len > 0) {
04263       for (x=0;x<16;x++)
04264          curblock[x] ^= src[x];
04265       aes_encrypt(curblock, dst, ecx);
04266       memcpy(curblock, dst, sizeof(curblock)); 
04267       dst += 16;
04268       src += 16;
04269       len -= 16;
04270    }
04271 #endif
04272 }

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

Definition at line 5427 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

05428 {
05429    /* Select exactly one common encryption if there are any */
05430    p->encmethods &= enc;
05431    if (p->encmethods) {
05432       if (p->encmethods & IAX_ENCRYPT_AES128)
05433          p->encmethods = IAX_ENCRYPT_AES128;
05434       else
05435          p->encmethods = 0;
05436    }
05437 }

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

Definition at line 9191 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(), ast_iax2_queue::count, f, iax2_sched_add(), iax_frame_free(), iaxq, iaxs, iaxsl, io, iax_frame::list, option_debug, ast_iax2_queue::queue, sched, send_packet(), and timing_read().

Referenced by start_network_thread().

09192 {
09193    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
09194       from the network, and queue them for delivery to the channels */
09195    int res, count, wakeup;
09196    struct iax_frame *f;
09197 
09198    if (timingfd > -1)
09199       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
09200    
09201    for(;;) {
09202       pthread_testcancel();
09203 
09204       /* Go through the queue, sending messages which have not yet been
09205          sent, and scheduling retransmissions if appropriate */
09206       AST_LIST_LOCK(&iaxq.queue);
09207       count = 0;
09208       wakeup = -1;
09209       AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) {
09210          if (f->sentyet)
09211             continue;
09212          
09213          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
09214          if (ast_mutex_trylock(&iaxsl[f->callno])) {
09215             wakeup = 1;
09216             continue;
09217          }
09218 
09219          f->sentyet++;
09220 
09221          if (iaxs[f->callno]) {
09222             send_packet(f);
09223             count++;
09224          } 
09225 
09226          ast_mutex_unlock(&iaxsl[f->callno]);
09227 
09228          if (f->retries < 0) {
09229             /* This is not supposed to be retransmitted */
09230             AST_LIST_REMOVE_CURRENT(&iaxq.queue, list);
09231             iaxq.count--;
09232             /* Free the iax frame */
09233             iax_frame_free(f);
09234          } else {
09235             /* We need reliable delivery.  Schedule a retransmission */
09236             f->retries++;
09237             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
09238          }
09239       }
09240       AST_LIST_TRAVERSE_SAFE_END
09241       AST_LIST_UNLOCK(&iaxq.queue);
09242 
09243       pthread_testcancel();
09244 
09245       if (option_debug && count >= 20)
09246          ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
09247 
09248       /* Now do the IO, and run scheduled tasks */
09249       res = ast_io_wait(io, wakeup);
09250       if (res >= 0) {
09251          if (option_debug && res >= 20)
09252             ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
09253       }
09254    }
09255    return NULL;
09256 }

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

Definition at line 1398 of file chan_iax2.c.

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

Referenced by __find_callno().

01399 {
01400    struct chan_iax2_pvt *tmp;
01401    jb_conf jbconf;
01402 
01403    if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) {
01404       return NULL;
01405    }
01406 
01407    if (ast_string_field_init(tmp, 32)) {
01408       ao2_ref(tmp, -1);
01409       tmp = NULL;
01410       return NULL;
01411    }
01412       
01413    tmp->prefs = prefs;
01414    tmp->callno = 0;
01415    tmp->peercallno = 0;
01416    tmp->transfercallno = 0;
01417    tmp->bridgecallno = 0;
01418    tmp->pingid = -1;
01419    tmp->lagid = -1;
01420    tmp->autoid = -1;
01421    tmp->authid = -1;
01422    tmp->initid = -1;
01423 
01424    ast_string_field_set(tmp,exten, "s");
01425    ast_string_field_set(tmp,host, host);
01426 
01427    tmp->jb = jb_new();
01428    tmp->jbid = -1;
01429    jbconf.max_jitterbuf = maxjitterbuffer;
01430    jbconf.resync_threshold = resyncthreshold;
01431    jbconf.max_contig_interp = maxjitterinterps;
01432    jb_setconf(tmp->jb,&jbconf);
01433 
01434    return tmp;
01435 }

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 3253 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, and parsed_dial_string::username.

Referenced by cache_get_callno_locked(), iax2_call(), iax2_devicestate(), and iax2_request().

03254 {
03255    if (ast_strlen_zero(data))
03256       return;
03257 
03258    pds->peer = strsep(&data, "/");
03259    pds->exten = strsep(&data, "/");
03260    pds->options = data;
03261 
03262    if (pds->exten) {
03263       data = pds->exten;
03264       pds->exten = strsep(&data, "@");
03265       pds->context = data;
03266    }
03267 
03268    if (strchr(pds->peer, '@')) {
03269       data = pds->peer;
03270       pds->username = strsep(&data, "@");
03271       pds->peer = data;
03272    }
03273 
03274    if (pds->username) {
03275       data = pds->username;
03276       pds->username = strsep(&data, ":");
03277       pds->password = data;
03278    }
03279 
03280    data = pds->peer;
03281    pds->peer = strsep(&data, ":");
03282    pds->port = data;
03283 
03284    /* check for a key name wrapped in [] in the secret position, if found,
03285       move it to the key field instead
03286    */
03287    if (pds->password && (pds->password[0] == '[')) {
03288       pds->key = ast_strip_quoted(pds->password, "[", "]");
03289       pds->password = NULL;
03290    }
03291 }

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

References iax2_peer::name.

Referenced by load_module().

01121 {
01122    struct iax2_peer *peer = obj, *peer2 = arg;
01123 
01124    return !strcmp(peer->name, peer2->name) ? CMP_MATCH | CMP_STOP : 0;
01125 }

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

Definition at line 9881 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09882 {
09883    struct iax2_peer *peer = obj;
09884 
09885    ast_set_flag(peer, IAX_DELME);
09886 
09887    return 0;
09888 }

static void peer_destructor ( void *  obj  )  [static]

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

09415 {
09416    struct iax2_peer *peer = obj;
09417    int callno = peer->callno;
09418 
09419    ast_free_ha(peer->ha);
09420 
09421    if (callno > 0) {
09422       ast_mutex_lock(&iaxsl[callno]);
09423       iax2_destroy(callno);
09424       ast_mutex_unlock(&iaxsl[callno]);
09425    }
09426 
09427    register_peer_exten(peer, 0);
09428 
09429    if (peer->dnsmgr)
09430       ast_dnsmgr_release(peer->dnsmgr);
09431 
09432    ast_string_field_free_memory(peer);
09433 }

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

References ast_str_hash(), and iax2_peer::name.

Referenced by load_module().

01111 {
01112    const struct iax2_peer *peer = obj;
01113 
01114    return ast_str_hash(peer->name);
01115 }

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

Definition at line 1167 of file chan_iax2.c.

References ao2_ref().

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

01168 {
01169    ao2_ref(peer, +1);
01170    return peer;
01171 }

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

Definition at line 11190 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

11191 {
11192    struct iax2_peer *peer = obj;
11193 
11194    if (peer->sockfd < 0)
11195       peer->sockfd = defaultsockfd;
11196 
11197    return 0;
11198 }

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

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

Referenced by build_peer().

09342 {
09343    struct sockaddr_in sin;
09344    int nonlocal = 1;
09345    int port = IAX_DEFAULT_PORTNO;
09346    int sockfd = defaultsockfd;
09347    char *tmp;
09348    char *addr;
09349    char *portstr;
09350 
09351    if (!(tmp = ast_strdupa(srcaddr)))
09352       return -1;
09353 
09354    addr = strsep(&tmp, ":");
09355    portstr = tmp;
09356 
09357    if (portstr) {
09358       port = atoi(portstr);
09359       if (port < 1)
09360          port = IAX_DEFAULT_PORTNO;
09361    }
09362    
09363    if (!ast_get_ip(&sin, addr)) {
09364       struct ast_netsock *sock;
09365       int res;
09366 
09367       sin.sin_port = 0;
09368       sin.sin_family = AF_INET;
09369       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
09370       if (res == 0) {
09371          /* ip address valid. */
09372          sin.sin_port = htons(port);
09373          if (!(sock = ast_netsock_find(netsock, &sin)))
09374             sock = ast_netsock_find(outsock, &sin);
09375          if (sock) {
09376             sockfd = ast_netsock_sockfd(sock);
09377             nonlocal = 0;
09378          } else {
09379             unsigned int orig_saddr = sin.sin_addr.s_addr;
09380             /* INADDR_ANY matches anyway! */
09381             sin.sin_addr.s_addr = INADDR_ANY;
09382             if (ast_netsock_find(netsock, &sin)) {
09383                sin.sin_addr.s_addr = orig_saddr;
09384                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL);
09385                if (sock) {
09386                   sockfd = ast_netsock_sockfd(sock);
09387                   ast_netsock_unref(sock);
09388                   nonlocal = 0;
09389                } else {
09390                   nonlocal = 2;
09391                }
09392             }
09393          }
09394       }
09395    }
09396       
09397    peer->sockfd = sockfd;
09398 
09399    if (nonlocal == 1) {
09400       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
09401          srcaddr, peer->name);
09402       return -1;
09403         } else if (nonlocal == 2) {
09404       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
09405          srcaddr, peer->name);
09406          return -1;
09407    } else {
09408       if (option_debug)
09409          ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
09410       return 0;
09411    }
09412 }

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

peer_status: Report Peer status in character string

Definition at line 2374 of file chan_iax2.c.

References ast_copy_string(), 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().

02375 {
02376    int res = 0;
02377    if (peer->maxms) {
02378       if (peer->lastms < 0) {
02379          ast_copy_string(status, "UNREACHABLE", statuslen);
02380       } else if (peer->lastms > peer->maxms) {
02381          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02382          res = 1;
02383       } else if (peer->lastms) {
02384          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02385          res = 1;
02386       } else {
02387          ast_copy_string(status, "UNKNOWN", statuslen);
02388       }
02389    } else { 
02390       ast_copy_string(status, "Unmonitored", statuslen);
02391       res = -1;
02392    }
02393    return res;
02394 }

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

Definition at line 1173 of file chan_iax2.c.

References ao2_ref().

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

01174 {
01175    ao2_ref(peer, -1);
01176    return NULL;
01177 }

static void poke_all_peers ( void   )  [static]

Definition at line 10343 of file chan_iax2.c.

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

Referenced by reload_config().

10344 {
10345    struct ao2_iterator i;
10346    struct iax2_peer *peer;
10347 
10348    i = ao2_iterator_init(peers, 0);
10349    while ((peer = ao2_iterator_next(&i))) {
10350       iax2_poke_peer(peer, 0);
10351       peer_unref(peer);
10352    }
10353 }

static void prune_peers ( void   )  [static]

Definition at line 9940 of file chan_iax2.c.

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

09941 {
09942    struct iax2_peer *peer;
09943    struct ao2_iterator i;
09944 
09945    i = ao2_iterator_init(peers, 0);
09946    while ((peer = ao2_iterator_next(&i))) {
09947       if (ast_test_flag(peer, IAX_DELME))
09948          unlink_peer(peer);
09949       peer_unref(peer);
09950    }
09951 }

static void prune_users ( void   )  [static]

Definition at line 9926 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ao2_unlink(), ast_test_flag, IAX_DELME, and user_unref().

Referenced by reload_config().

09927 {
09928    struct iax2_user *user;
09929    struct ao2_iterator i;
09930 
09931    i = ao2_iterator_init(users, 0);
09932    while ((user = ao2_iterator_next(&i))) {
09933       if (ast_test_flag(user, IAX_DELME))
09934          ao2_unlink(users, user);
09935       user_unref(user);
09936    }
09937 }

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

Definition at line 11207 of file chan_iax2.c.

References chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

11208 {
11209    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
11210 
11211    /* The frames_received field is used to hold whether we're matching
11212     * against a full frame or not ... */
11213 
11214    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
11215       pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0;
11216 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1359 of file chan_iax2.c.

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

Referenced by new_iax().

01360 {
01361    struct chan_iax2_pvt *pvt = obj;
01362    struct iax_frame *cur = NULL;
01363 
01364    iax2_destroy_helper(pvt);
01365 
01366    /* Already gone */
01367    ast_set_flag(pvt, IAX_ALREADYGONE); 
01368 
01369    AST_LIST_LOCK(&iaxq.queue);
01370    AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
01371       /* Cancel any pending transmissions */
01372       if (cur->callno == pvt->callno) { 
01373          cur->retries = -1;
01374       }
01375    }
01376    AST_LIST_UNLOCK(&iaxq.queue);
01377 
01378    if (pvt->reg) {
01379       pvt->reg->callno = 0;
01380    }
01381 
01382    if (!pvt->owner) {
01383       jb_frame frame;
01384       if (pvt->vars) {
01385           ast_variables_destroy(pvt->vars);
01386           pvt->vars = NULL;
01387       }
01388 
01389       while (jb_getall(pvt->jb, &frame) == JB_OK) {
01390          iax2_frame_free(frame.data);
01391       }
01392 
01393       jb_destroy(pvt->jb);
01394       ast_string_field_free_memory(pvt);
01395    }
01396 }

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

Definition at line 11200 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

Referenced by load_module().

11201 {
11202    const struct chan_iax2_pvt *pvt = obj;
11203 
11204    return pvt->peercallno;
11205 }

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

Definition at line 5409 of file chan_iax2.c.

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

Referenced by socket_process().

05410 {
05411    struct ast_iax2_full_hdr fh;
05412    fh.scallno = htons(src | IAX_FLAG_FULL);
05413    fh.dcallno = htons(dst);
05414    fh.ts = 0;
05415    fh.oseqno = 0;
05416    fh.iseqno = 0;
05417    fh.type = AST_FRAME_IAX;
05418    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
05419    if (iaxdebug)
05420        iax_showframe(NULL, &fh, 0, sin, 0);
05421    if (option_debug)
05422       ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n",
05423          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
05424    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
05425 }

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

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

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

Definition at line 2855 of file chan_iax2.c.

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

02856 {
02857    struct ast_variable *var = NULL;
02858    struct ast_variable *tmp;
02859    struct iax2_peer *peer=NULL;
02860    time_t regseconds = 0, nowtime;
02861    int dynamic=0;
02862 
02863    if (peername) {
02864       var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL);
02865       if (!var && sin)
02866          var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02867    } else if (sin) {
02868       char porta[25];
02869       sprintf(porta, "%d", ntohs(sin->sin_port));
02870       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02871       if (var) {
02872          /* We'll need the peer name in order to build the structure! */
02873          for (tmp = var; tmp; tmp = tmp->next) {
02874             if (!strcasecmp(tmp->name, "name"))
02875                peername = tmp->value;
02876          }
02877       }
02878    }
02879    if (!var && peername) { /* Last ditch effort */
02880       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
02881       /*!\note
02882        * If this one loaded something, then we need to ensure that the host
02883        * field matched.  The only reason why we can't have this as a criteria
02884        * is because we only have the IP address and the host field might be
02885        * set as a name (and the reverse PTR might not match).
02886        */
02887       if (var && sin) {
02888          for (tmp = var; tmp; tmp = tmp->next) {
02889             if (!strcasecmp(tmp->name, "host")) {
02890                struct ast_hostent ahp;
02891                struct hostent *hp;
02892                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
02893                   /* No match */
02894                   ast_variables_destroy(var);
02895                   var = NULL;
02896                }
02897                break;
02898             }
02899          }
02900       }
02901    }
02902    if (!var)
02903       return NULL;
02904 
02905    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
02906    
02907    if (!peer) {
02908       ast_variables_destroy(var);
02909       return NULL;
02910    }
02911 
02912    for (tmp = var; tmp; tmp = tmp->next) {
02913       /* Make sure it's not a user only... */
02914       if (!strcasecmp(tmp->name, "type")) {
02915          if (strcasecmp(tmp->value, "friend") &&
02916              strcasecmp(tmp->value, "peer")) {
02917             /* Whoops, we weren't supposed to exist! */
02918             peer = peer_unref(peer);
02919             break;
02920          } 
02921       } else if (!strcasecmp(tmp->name, "regseconds")) {
02922          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
02923       } else if (!strcasecmp(tmp->name, "ipaddr")) {
02924          inet_aton(tmp->value, &(peer->addr.sin_addr));
02925       } else if (!strcasecmp(tmp->name, "port")) {
02926          peer->addr.sin_port = htons(atoi(tmp->value));
02927       } else if (!strcasecmp(tmp->name, "host")) {
02928          if (!strcasecmp(tmp->value, "dynamic"))
02929             dynamic = 1;
02930       }
02931    }
02932 
02933    ast_variables_destroy(var);
02934 
02935    if (!peer)
02936       return NULL;
02937 
02938    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
02939       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
02940       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
02941          if (peer->expire > -1) {
02942             if (!ast_sched_del(sched, peer->expire)) {
02943                peer->expire = -1;
02944                peer_unref(peer);
02945             }
02946          }
02947          peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
02948          if (peer->expire == -1)
02949             peer_unref(peer);
02950       }
02951       ao2_link(peers, peer);
02952       if (ast_test_flag(peer, IAX_DYNAMIC))
02953          reg_source_db(peer);
02954    } else {
02955       ast_set_flag(peer, IAX_TEMPONLY);   
02956    }
02957 
02958    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
02959       time(&nowtime);
02960       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
02961          memset(&peer->addr, 0, sizeof(peer->addr));
02962          realtime_update_peer(peer->name, &peer->addr, 0);
02963          if (option_debug)
02964             ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
02965                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02966       }
02967       else {
02968          if (option_debug)
02969             ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
02970                   peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
02971       }
02972    }
02973 
02974    return peer;
02975 }

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

Definition at line 3048 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

03049 {
03050    char port[10];
03051    char regseconds[20];
03052    
03053    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
03054    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
03055    ast_update_realtime("iaxpeers", "name", peername, 
03056       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
03057       "regseconds", regseconds, NULL);
03058 }

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

Definition at line 2977 of file chan_iax2.c.

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

02978 {
02979    struct ast_variable *var;
02980    struct ast_variable *tmp;
02981    struct iax2_user *user=NULL;
02982 
02983    var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL);
02984    if (!var)
02985       var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL);
02986    if (!var && sin) {
02987       char porta[6];
02988       snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port));
02989       var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02990       if (!var)
02991          var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
02992    }
02993    if (!var) { /* Last ditch effort */
02994       var = ast_load_realtime("iaxusers", "name", username, NULL);
02995       /*!\note
02996        * If this one loaded something, then we need to ensure that the host
02997        * field matched.  The only reason why we can't have this as a criteria
02998        * is because we only have the IP address and the host field might be
02999        * set as a name (and the reverse PTR might not match).
03000        */
03001       if (var) {
03002          for (tmp = var; tmp; tmp = tmp->next) {
03003             if (!strcasecmp(tmp->name, "host")) {
03004                struct ast_hostent ahp;
03005                struct hostent *hp;
03006                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
03007                   /* No match */
03008                   ast_variables_destroy(var);
03009                   var = NULL;
03010                }
03011                break;
03012             }
03013          }
03014       }
03015    }
03016    if (!var)
03017       return NULL;
03018 
03019    tmp = var;
03020    while(tmp) {
03021       /* Make sure it's not a peer only... */
03022       if (!strcasecmp(tmp->name, "type")) {
03023          if (strcasecmp(tmp->value, "friend") &&
03024              strcasecmp(tmp->value, "user")) {
03025             return NULL;
03026          } 
03027       }
03028       tmp = tmp->next;
03029    }
03030 
03031    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
03032 
03033    ast_variables_destroy(var);
03034 
03035    if (!user)
03036       return NULL;
03037 
03038    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
03039       ast_set_flag(user, IAX_RTCACHEFRIENDS);
03040       ao2_link(users, user);
03041    } else {
03042       ast_set_flag(user, IAX_TEMPONLY);   
03043    }
03044 
03045    return user;
03046 }

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 6200 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, iax2_peer::name, option_verbose, peer_ref(), peer_unref(), register_peer_exten(), sched, and VERBOSE_PREFIX_3.

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

06201 {
06202    char data[80];
06203    struct in_addr in;
06204    char *c, *d;
06205    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
06206       c = strchr(data, ':');
06207       if (c) {
06208          *c = '\0';
06209          c++;
06210          if (inet_aton(data, &in)) {
06211             d = strchr(c, ':');
06212             if (d) {
06213                *d = '\0';
06214                d++;
06215                if (option_verbose > 2)
06216                   ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 
06217                   ast_inet_ntoa(in), atoi(c), atoi(d));
06218                iax2_poke_peer(p, 0);
06219                p->expiry = atoi(d);
06220                memset(&p->addr, 0, sizeof(p->addr));
06221                p->addr.sin_family = AF_INET;
06222                p->addr.sin_addr = in;
06223                p->addr.sin_port = htons(atoi(c));
06224                if (p->expire > -1) {
06225                   if (!ast_sched_del(sched, p->expire)) {
06226                      p->expire = -1;
06227                      peer_unref(p);
06228                   }
06229                }
06230                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06231                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06232                if (p->expire == -1)
06233                   peer_unref(p);
06234                if (iax2_regfunk)
06235                   iax2_regfunk(p->name, 1);
06236                register_peer_exten(p, 1);
06237             }              
06238                
06239          }
06240       }
06241    }
06242 }

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

Definition at line 6120 of file chan_iax2.c.

References ast_add_extension(), ast_context_remove_extension(), ast_copy_string(), ast_exists_extension(), ast_free, ast_strdup, ast_strlen_zero(), ext, iax2_peer::name, iax2_peer::regexten, and S_OR.

Referenced by __expire_registry(), expire_register(), parse_register_contact(), peer_destructor(), reg_source_db(), sip_destroy_peer(), and update_registry().

06121 {
06122    char multi[256];
06123    char *stringp, *ext;
06124    if (!ast_strlen_zero(regcontext)) {
06125       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
06126       stringp = multi;
06127       while((ext = strsep(&stringp, "&"))) {
06128          if (onoff) {
06129             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
06130                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
06131                        "Noop", ast_strdup(peer->name), ast_free, "IAX2");
06132          } else
06133             ast_context_remove_extension(regcontext, ext, 1, NULL);
06134       }
06135    }
06136 }

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

Verify inbound registration.

Definition at line 5573 of file chan_iax2.c.

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

Referenced by handle_request_register(), and socket_process().

05574 {
05575    char requeststr[256] = "";
05576    char peer[256] = "";
05577    char md5secret[256] = "";
05578    char rsasecret[256] = "";
05579    char secret[256] = "";
05580    struct iax2_peer *p = NULL;
05581    struct ast_key *key;
05582    char *keyn;
05583    int x;
05584    int expire = 0;
05585    int res = -1;
05586 
05587    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
05588    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
05589    if (ies->username)
05590       ast_copy_string(peer, ies->username, sizeof(peer));
05591    if (ies->password)
05592       ast_copy_string(secret, ies->password, sizeof(secret));
05593    if (ies->md5_result)
05594       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
05595    if (ies->rsa_result)
05596       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
05597    if (ies->refresh)
05598       expire = ies->refresh;
05599 
05600    if (ast_strlen_zero(peer)) {
05601       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
05602       return -1;
05603    }
05604 
05605    /* SLD: first call to lookup peer during registration */
05606    ast_mutex_unlock(&iaxsl[callno]);
05607    p = find_peer(peer, 1);
05608    ast_mutex_lock(&iaxsl[callno]);
05609    if (!p || !iaxs[callno]) {
05610       if (iaxs[callno]) {
05611          ast_string_field_set(iaxs[callno], secret, "badsecret");
05612       }
05613       if (authdebug && !p)
05614          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05615       goto return_unref;
05616    }
05617 
05618    if (!ast_test_flag(p, IAX_DYNAMIC)) {
05619       if (authdebug)
05620          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
05621       goto return_unref;
05622    }
05623 
05624    if (!ast_apply_ha(p->ha, sin)) {
05625       if (authdebug)
05626          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05627       goto return_unref;
05628    }
05629    if (!inaddrcmp(&p->addr, sin))
05630       ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
05631    ast_string_field_set(iaxs[callno], secret, p->secret);
05632    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
05633    /* Check secret against what we have on file */
05634    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05635       if (!ast_strlen_zero(p->inkeys)) {
05636          char tmpkeys[256];
05637          char *stringp=NULL;
05638          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
05639          stringp=tmpkeys;
05640          keyn = strsep(&stringp, ":");
05641          while(keyn) {
05642             key = ast_key_get(keyn, AST_KEY_PUBLIC);
05643             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
05644                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05645                break;
05646             } else if (!key) 
05647                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
05648             keyn = strsep(&stringp, ":");
05649          }
05650          if (!keyn) {
05651             if (authdebug)
05652                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
05653             goto return_unref;
05654          }
05655       } else {
05656          if (authdebug)
05657             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
05658          goto return_unref;
05659       }
05660    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
05661       struct MD5Context md5;
05662       unsigned char digest[16];
05663       char *tmppw, *stringp;
05664       
05665       tmppw = ast_strdupa(p->secret);
05666       stringp = tmppw;
05667       while((tmppw = strsep(&stringp, ";"))) {
05668          MD5Init(&md5);
05669          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
05670          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
05671          MD5Final(digest, &md5);
05672          for (x=0;x<16;x++)
05673             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
05674          if (!strcasecmp(requeststr, md5secret)) 
05675             break;
05676       }
05677       if (tmppw) {
05678          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05679       } else {
05680          if (authdebug)
05681             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
05682          goto return_unref;
05683       }
05684    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
05685       /* They've provided a plain text password and we support that */
05686       if (strcmp(secret, p->secret)) {
05687          if (authdebug)
05688             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
05689          goto return_unref;
05690       } else
05691          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
05692    } else if (!ast_strlen_zero(iaxs[callno]->secret) || !ast_strlen_zero(iaxs[callno]->inkeys)) {
05693       if (authdebug &&
05694          ((!ast_strlen_zero(iaxs[callno]->secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) ||
05695           (!ast_strlen_zero(iaxs[callno]->inkeys) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)))) {
05696          ast_log(LOG_NOTICE, "Inappropriate authentication received for '%s'\n", p->name);
05697       } /* ELSE this is the first time through and no challenge exists, so it's not quite yet a failure. */
05698       goto return_unref;
05699    }
05700    ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
05701 
05702 return_unref:
05703    ast_string_field_set(iaxs[callno], peer, peer);
05704    /* Choose lowest expiry number */
05705    if (expire && (expire < iaxs[callno]->expiry)) 
05706       iaxs[callno]->expiry = expire;
05707 
05708    res = 0;
05709 
05710    if (p)
05711       peer_unref(p);
05712 
05713    return res;
05714 }

static int registry_authrequest ( int  callno  )  [static]

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

Referenced by socket_process().

06380 {
06381    struct iax_ie_data ied;
06382    struct iax2_peer *p;
06383    char challenge[10];
06384    const char *peer_name;
06385    int sentauthmethod;
06386 
06387    peer_name = ast_strdupa(iaxs[callno]->peer);
06388 
06389    /* SLD: third call to find_peer in registration */
06390    ast_mutex_unlock(&iaxsl[callno]);
06391    if ((p = find_peer(peer_name, 1))) {
06392       last_authmethod = p->authmethods;
06393    }
06394 
06395    ast_mutex_lock(&iaxsl[callno]);
06396    if (!iaxs[callno])
06397       goto return_unref;
06398 
06399    memset(&ied, 0, sizeof(ied));
06400    /* The selection of which delayed reject is sent may leak information,
06401     * if it sets a static response.  For example, if a host is known to only
06402     * use MD5 authentication, then an RSA response would indicate that the
06403     * peer does not exist, and vice-versa.
06404     * Therefore, we use whatever the last peer used (which may vary over the
06405     * course of a server, which should leak minimal information). */
06406    sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
06407    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
06408    if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
06409       /* Build the challenge */
06410       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06411       ast_string_field_set(iaxs[callno], challenge, challenge);
06412       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
06413    }
06414    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
06415 
06416 return_unref:
06417    if (p) {
06418       peer_unref(p);
06419    }
06420 
06421    return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1;
06422 }

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

Definition at line 6424 of file chan_iax2.c.

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

Referenced by socket_process().

06425 {
06426    struct iax2_registry *reg;
06427    /* Start pessimistic */
06428    struct iax_ie_data ied;
06429    char peer[256] = "";
06430    char challenge[256] = "";
06431    int res;
06432    int authmethods = 0;
06433    if (ies->authmethods)
06434       authmethods = ies->authmethods;
06435    if (ies->username)
06436       ast_copy_string(peer, ies->username, sizeof(peer));
06437    if (ies->challenge)
06438       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
06439    memset(&ied, 0, sizeof(ied));
06440    reg = iaxs[callno]->reg;
06441    if (reg) {
06442          if (inaddrcmp(&reg->addr, sin)) {
06443             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06444             return -1;
06445          }
06446          if (ast_strlen_zero(reg->secret)) {
06447             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
06448             reg->regstate = REG_STATE_NOAUTH;
06449             return -1;
06450          }
06451          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
06452          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
06453          if (reg->secret[0] == '[') {
06454             char tmpkey[256];
06455             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
06456             tmpkey[strlen(tmpkey) - 1] = '\0';
06457             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL);
06458          } else
06459             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL);
06460          if (!res) {
06461             reg->regstate = REG_STATE_AUTHSENT;
06462             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
06463          } else
06464             return -1;
06465          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
06466    } else   
06467       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
06468    return -1;
06469 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 4865 of file chan_iax2.c.

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

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

04866 {
04867    switch(regstate) {
04868    case REG_STATE_UNREGISTERED:
04869       return "Unregistered";
04870    case REG_STATE_REGSENT:
04871       return "Request Sent";
04872    case REG_STATE_AUTHSENT:
04873       return "Auth. Sent";
04874    case REG_STATE_REGISTERED:
04875       return "Registered";
04876    case REG_STATE_REJECTED:
04877       return "Rejected";
04878    case REG_STATE_TIMEOUT:
04879       return "Timeout";
04880    case REG_STATE_NOAUTH:
04881       return "No Authentication";
04882    default:
04883       return "Unknown";
04884    }
04885 }

static int reload ( void   )  [static]

Definition at line 10380 of file chan_iax2.c.

References reload_config().

10381 {
10382    return reload_config();
10383 }

static int reload_config ( void   )  [static]

Definition at line 10354 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, iax2_registry::entry, iax2_do_register(), iax_provision_reload(), poke_all_peers(), prune_peers(), prune_users(), reload_firmware(), and set_config().

10355 {
10356    char *config = "iax.conf";
10357    struct iax2_registry *reg;
10358 
10359    if (set_config(config, 1) > 0) {
10360       prune_peers();
10361       prune_users();
10362       AST_LIST_LOCK(&registrations);
10363       AST_LIST_TRAVERSE(&registrations, reg, entry)
10364          iax2_do_register(reg);
10365       AST_LIST_UNLOCK(&registrations);
10366       /* Qualify hosts, too */
10367       poke_all_peers();
10368    }
10369    reload_firmware(0);
10370    iax_provision_reload();
10371 
10372    return 0;
10373 }

static void reload_firmware ( int  unload  )  [static]

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

02019 {
02020    struct iax_firmware *cur, *curl, *curp;
02021    DIR *fwd;
02022    struct dirent *de;
02023    char dir[256];
02024    char fn[256];
02025    /* Mark all as dead */
02026    ast_mutex_lock(&waresl.lock);
02027    cur = waresl.wares;
02028    while(cur) {
02029       cur->dead = 1;
02030       cur = cur->next;
02031    }
02032 
02033    /* Now that we've freed them, load the new ones */
02034    if (!unload) {
02035       snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
02036       fwd = opendir(dir);
02037       if (fwd) {
02038          while((de = readdir(fwd))) {
02039             if (de->d_name[0] != '.') {
02040                snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
02041                if (!try_firmware(fn)) {
02042                   if (option_verbose > 1)
02043                      ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name);
02044                }
02045             }
02046          }
02047          closedir(fwd);
02048       } else 
02049          ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
02050    }
02051 
02052    /* Clean up leftovers */
02053    cur = waresl.wares;
02054    curp = NULL;
02055    while(cur) {
02056       curl = cur;
02057       cur = cur->next;
02058       if (curl->dead) {
02059          if (curp) {
02060             curp->next = cur;
02061          } else {
02062             waresl.wares = cur;
02063          }
02064          destroy_firmware(curl);
02065       } else {
02066          curp = cur;
02067       }
02068    }
02069    ast_mutex_unlock(&waresl.lock);
02070 }

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1258 of file chan_iax2.c.

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

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

01259 {
01260    if (!pvt->peercallno) {
01261       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01262       return;
01263    }
01264 
01265    ao2_unlink(iax_peercallno_pvts, pvt);
01266 }

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

Definition at line 6928 of file chan_iax2.c.

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

Referenced by socket_process().

06929 {
06930    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
06931    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
06932    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
06933    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
06934    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
06935    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
06936    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
06937 }

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

Definition at line 9164 of file chan_iax2.c.

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

Referenced by start_network_thread().

09165 {
09166    int count;
09167    int res;
09168    struct timeval tv;
09169    struct timespec ts;
09170 
09171    for (;;) {
09172       pthread_testcancel();
09173       ast_mutex_lock(&sched_lock);
09174       res = ast_sched_wait(sched);
09175       if ((res > 1000) || (res < 0))
09176          res = 1000;
09177       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
09178       ts.tv_sec = tv.tv_sec;
09179       ts.tv_nsec = tv.tv_usec * 1000;
09180       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
09181       ast_mutex_unlock(&sched_lock);
09182       pthread_testcancel();
09183 
09184       count = ast_sched_runq(sched);
09185       if (option_debug && count >= 20)
09186          ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
09187    }
09188    return NULL;
09189 }

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 2708 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_samp2tv(), AST_SCHED_DEL, ast_test_flag, ast_tv(), ast_tvadd(), ast_tvzero(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, iaxs, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, LOG_DEBUG, option_debug, ast_channel_tech::properties, sched, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process().

02709 {
02710    int type, len;
02711    int ret;
02712    int needfree = 0;
02713    struct ast_channel *owner = NULL;
02714    struct ast_channel *bridge = NULL;
02715    
02716    /* Attempt to recover wrapped timestamps */
02717    unwrap_timestamp(fr);
02718 
02719    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
02720    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
02721       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
02722    else {
02723 #if 0
02724       if (option_debug)
02725          ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
02726 #endif
02727       fr->af.delivery = ast_tv(0,0);
02728    }
02729 
02730    type = JB_TYPE_CONTROL;
02731    len = 0;
02732 
02733    if(fr->af.frametype == AST_FRAME_VOICE) {
02734       type = JB_TYPE_VOICE;
02735       len = ast_codec_get_samples(&fr->af) / 8;
02736    } else if(fr->af.frametype == AST_FRAME_CNG) {
02737       type = JB_TYPE_SILENCE;
02738    }
02739 
02740    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
02741       if (tsout)
02742          *tsout = fr->ts;
02743       __do_deliver(fr);
02744       return -1;
02745    }
02746 
02747    if ((owner = iaxs[fr->callno]->owner))
02748       bridge = ast_bridged_channel(owner);
02749 
02750    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
02751     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
02752    if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
02753       jb_frame frame;
02754 
02755       /* deliver any frames in the jb */
02756       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
02757          __do_deliver(frame.data);
02758          /* __do_deliver() can make the call disappear */
02759          if (!iaxs[fr->callno])
02760             return -1;
02761       }
02762 
02763       jb_reset(iaxs[fr->callno]->jb);
02764 
02765       AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
02766 
02767       /* deliver this frame now */
02768       if (tsout)
02769          *tsout = fr->ts;
02770       __do_deliver(fr);
02771       return -1;
02772    }
02773 
02774    /* insert into jitterbuffer */
02775    /* TODO: Perhaps we could act immediately if it's not droppable and late */
02776    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
02777          calc_rxstamp(iaxs[fr->callno],fr->ts));
02778    if (ret == JB_DROP) {
02779       needfree++;
02780    } else if (ret == JB_SCHED) {
02781       update_jbsched(iaxs[fr->callno]);
02782    }
02783    if (tsout)
02784       *tsout = fr->ts;
02785    if (needfree) {
02786       /* Free our iax frame */
02787       iax2_frame_free(fr);
02788       return -1;
02789    }
02790    return 0;
02791 }

static int scheduled_destroy ( const void *  vid  )  [static]

Definition at line 1345 of file chan_iax2.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_destroy(), LOG_DEBUG, option_debug, and PTR_TO_CALLNO.

Referenced by iax2_hangup().

01346 {
01347    short callno = PTR_TO_CALLNO(vid);
01348    ast_mutex_lock(&iaxsl[callno]);
01349    if (iaxs[callno]) {
01350       if (option_debug) {
01351          ast_log(LOG_DEBUG, "Really destroying %d now...\n", callno);
01352       }
01353       iax2_destroy(callno);
01354    }
01355    ast_mutex_unlock(&iaxsl[callno]);
01356    return 0;
01357 }

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

References AST_FRAME_IAX, compress_subclass(), and f.

Referenced by socket_process().

03227 {
03228    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03229       .ts = htonl(ts), .iseqno = seqno, .oseqno = 0, .type = AST_FRAME_IAX,
03230       .csub = compress_subclass(command) };
03231 
03232    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03233 }

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

Definition at line 5149 of file chan_iax2.c.

References __send_command().

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

05150 {
05151    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
05152 }

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

05169 {
05170    int call_num = i->callno;
05171    /* It is assumed that the callno has already been locked */
05172    iax2_predestroy(i->callno);
05173    if (!iaxs[call_num])
05174       return -1;
05175    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05176 }

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

Definition at line 5178 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05179 {
05180    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05181 }

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

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

05155 {
05156    int res;
05157    ast_mutex_lock(&iaxsl[callno]);
05158    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05159    ast_mutex_unlock(&iaxsl[callno]);
05160    return res;
05161 }

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

Definition at line 5183 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

05184 {
05185    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05186 }

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

Definition at line 1063 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

01064 {
01065 #ifdef SCHED_MULTITHREADED
01066    if (schedule_action(__send_lagrq, data))
01067 #endif      
01068       __send_lagrq(data);
01069    
01070    return 0;
01071 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 2143 of file chan_iax2.c.

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

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

02144 {
02145    int res;
02146    int callno = f->callno;
02147 
02148    /* Don't send if there was an error, but return error instead */
02149    if (!callno || !iaxs[callno] || iaxs[callno]->error)
02150        return -1;
02151    
02152    /* Called with iaxsl held */
02153    if (option_debug > 2 && iaxdebug)
02154       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));
02155    if (f->transfer) {
02156       if (iaxdebug)
02157          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
02158       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
02159                sizeof(iaxs[callno]->transfer));
02160    } else {
02161       if (iaxdebug)
02162          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
02163       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
02164                sizeof(iaxs[callno]->addr));
02165    }
02166    if (res < 0) {
02167       if (option_debug && iaxdebug)
02168          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02169       handle_error();
02170    } else
02171       res = 0;
02172    return res;
02173 }

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

Definition at line 1018 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

01019 {
01020 #ifdef SCHED_MULTITHREADED
01021    if (schedule_action(__send_ping, data))
01022 #endif      
01023       __send_ping(data);
01024 
01025    return 0;
01026 }

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

Definition at line 6606 of file chan_iax2.c.

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

Referenced by timing_read().

06607 {
06608    int res = 0;
06609    struct iax_frame *fr;
06610    struct ast_iax2_meta_hdr *meta;
06611    struct ast_iax2_meta_trunk_hdr *mth;
06612    int calls = 0;
06613    
06614    /* Point to frame */
06615    fr = (struct iax_frame *)tpeer->trunkdata;
06616    /* Point to meta data */
06617    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
06618    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
06619    if (tpeer->trunkdatalen) {
06620       /* We're actually sending a frame, so fill the meta trunk header and meta header */
06621       meta->zeros = 0;
06622       meta->metacmd = IAX_META_TRUNK;
06623       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
06624          meta->cmddata = IAX_META_TRUNK_MINI;
06625       else
06626          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
06627       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
06628       /* And the rest of the ast_iax2 header */
06629       fr->direction = DIRECTION_OUTGRESS;
06630       fr->retrans = -1;
06631       fr->transfer = 0;
06632       /* Any appropriate call will do */
06633       fr->data = fr->afdata;
06634       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
06635       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
06636       calls = tpeer->calls;
06637 #if 0
06638       if (option_debug)
06639          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));
06640 #endif      
06641       /* Reset transmit trunk side data */
06642       tpeer->trunkdatalen = 0;
06643       tpeer->calls = 0;
06644    }
06645    if (res < 0)
06646       return res;
06647    return calls;
06648 }

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

Load configuration.

Definition at line 9984 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_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_netsock_bind(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_netsock_sockfd(), ast_netsock_unref(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), build_peer(), build_user(), capability, DEFAULT_MAXMS, errno, format, gen, get_encrypt_methods(), globalflags, iax2_register(), IAX_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, io, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_PEER_BUCKETS, ast_variable::name, netsock, ast_variable::next, option_verbose, outsock, peer_unref(), portno, prefs, reg_source_db(), secret, set_config_destroy(), set_timing(), socket_read(), user_unref(), ast_variable::value, and VERBOSE_PREFIX_2.

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

09985 {
09986    struct ast_config *cfg, *ucfg;
09987    int capability=iax2_capability;
09988    struct ast_variable *v;
09989    char *cat;
09990    const char *utype;
09991    const char *tosval;
09992    int format;
09993    int portno = IAX_DEFAULT_PORTNO;
09994    int  x;
09995    struct iax2_user *user;
09996    struct iax2_peer *peer;
09997    struct ast_netsock *ns;
09998 #if 0
09999    static unsigned short int last_port=0;
10000 #endif
10001 
10002    cfg = ast_config_load(config_file);
10003    
10004    if (!cfg) {
10005       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
10006       return -1;
10007    }
10008 
10009    if (reload) {
10010       set_config_destroy();
10011    }
10012 
10013    /* Reset global codec prefs */   
10014    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
10015    
10016    /* Reset Global Flags */
10017    memset(&globalflags, 0, sizeof(globalflags));
10018    ast_set_flag(&globalflags, IAX_RTUPDATE);
10019 
10020 #ifdef SO_NO_CHECK
10021    nochecksums = 0;
10022 #endif
10023 
10024    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
10025    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
10026 
10027    maxauthreq = 3;
10028 
10029    v = ast_variable_browse(cfg, "general");
10030 
10031    /* Seed initial tos value */
10032    tosval = ast_variable_retrieve(cfg, "general", "tos");
10033    if (tosval) {
10034       if (ast_str2tos(tosval, &tos))
10035          ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n");
10036    }
10037    while(v) {
10038       if (!strcasecmp(v->name, "bindport")){ 
10039          if (reload)
10040             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
10041          else
10042             portno = atoi(v->value);
10043       } else if (!strcasecmp(v->name, "pingtime")) 
10044          ping_time = atoi(v->value);
10045       else if (!strcasecmp(v->name, "iaxthreadcount")) {
10046          if (reload) {
10047             if (atoi(v->value) != iaxthreadcount)
10048                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
10049          } else {
10050             iaxthreadcount = atoi(v->value);
10051             if (iaxthreadcount < 1) {
10052                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
10053                iaxthreadcount = 1;
10054             } else if (iaxthreadcount > 256) {
10055                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
10056                iaxthreadcount = 256;
10057             }
10058          }
10059       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
10060          if (reload) {
10061             AST_LIST_LOCK(&dynamic_list);
10062             iaxmaxthreadcount = atoi(v->value);
10063             AST_LIST_UNLOCK(&dynamic_list);
10064          } else {
10065             iaxmaxthreadcount = atoi(v->value);
10066             if (iaxmaxthreadcount < 0) {
10067                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
10068                iaxmaxthreadcount = 0;
10069             } else if (iaxmaxthreadcount > 256) {
10070                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
10071                iaxmaxthreadcount = 256;
10072             }
10073          }
10074       } else if (!strcasecmp(v->name, "nochecksums")) {
10075 #ifdef SO_NO_CHECK
10076          if (ast_true(v->value))
10077             nochecksums = 1;
10078          else
10079             nochecksums = 0;
10080 #else
10081          if (ast_true(v->value))
10082             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
10083 #endif
10084       }
10085       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
10086          maxjitterbuffer = atoi(v->value);
10087       else if (!strcasecmp(v->name, "resyncthreshold")) 
10088          resyncthreshold = atoi(v->value);
10089       else if (!strcasecmp(v->name, "maxjitterinterps")) 
10090          maxjitterinterps = atoi(v->value);
10091       else if (!strcasecmp(v->name, "lagrqtime")) 
10092          lagrq_time = atoi(v->value);
10093       else if (!strcasecmp(v->name, "maxregexpire")) 
10094          max_reg_expire = atoi(v->value);
10095       else if (!strcasecmp(v->name, "minregexpire")) 
10096          min_reg_expire = atoi(v->value);
10097       else if (!strcasecmp(v->name, "bindaddr")) {
10098          if (reload) {
10099             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
10100          } else {
10101             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) {
10102                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
10103             } else {
10104                if (option_verbose > 1) {
10105                   if (strchr(v->value, ':'))
10106                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value);
10107                   else
10108                      ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno);
10109                }
10110                if (defaultsockfd < 0) 
10111                   defaultsockfd = ast_netsock_sockfd(ns);
10112                ast_netsock_unref(ns);
10113             }
10114          }
10115       } else if (!strcasecmp(v->name, "authdebug"))
10116          authdebug = ast_true(v->value);
10117       else if (!strcasecmp(v->name, "encryption"))
10118          iax2_encryption = get_encrypt_methods(v->value);
10119       else if (!strcasecmp(v->name, "notransfer")) {
10120          ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n");
10121          ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
10122          ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER);   
10123       } else if (!strcasecmp(v->name, "transfer")) {
10124          if (!strcasecmp(v->value, "mediaonly")) {
10125             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
10126          } else if (ast_true(v->value)) {
10127             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
10128          } else 
10129             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
10130       } else if (!strcasecmp(v->name, "codecpriority")) {
10131          if(!strcasecmp(v->value, "caller"))
10132             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
10133          else if(!strcasecmp(v->value, "disabled"))
10134             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
10135          else if(!strcasecmp(v->value, "reqonly")) {
10136             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
10137             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
10138          }
10139       } else if (!strcasecmp(v->name, "jitterbuffer"))
10140          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
10141       else if (!strcasecmp(v->name, "forcejitterbuffer"))
10142          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
10143       else if (!strcasecmp(v->name, "delayreject"))
10144          delayreject = ast_true(v->value);
10145       else if (!strcasecmp(v->name, "allowfwdownload"))
10146          ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD);
10147       else if (!strcasecmp(v->name, "rtcachefriends"))
10148          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
10149       else if (!strcasecmp(v->name, "rtignoreregexpire"))
10150          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
10151       else if (!strcasecmp(v->name, "rtupdate"))
10152          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
10153       else if (!strcasecmp(v->name, "trunktimestamps"))
10154          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
10155       else if (!strcasecmp(v->name, "rtautoclear")) {
10156          int i = atoi(v->value);
10157          if(i > 0)
10158             global_rtautoclear = i;
10159          else
10160             i = 0;
10161          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
10162       } else if (!strcasecmp(v->name, "trunkfreq")) {
10163          trunkfreq = atoi(v->value);
10164          if (trunkfreq < 10)
10165             trunkfreq = 10;
10166       } else if (!strcasecmp(v->name, "autokill")) {
10167          if (sscanf(v->value, "%d", &x) == 1) {
10168             if (x >= 0)
10169                autokill = x;
10170             else
10171                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
10172          } else if (ast_true(v->value)) {
10173             autokill = DEFAULT_MAXMS;
10174          } else {
10175             autokill = 0;
10176          }
10177       } else if (!strcasecmp(v->name, "bandwidth")) {
10178          if (!strcasecmp(v->value, "low")) {
10179             capability = IAX_CAPABILITY_LOWBANDWIDTH;
10180          } else if (!strcasecmp(v->value, "medium")) {
10181             capability = IAX_CAPABILITY_MEDBANDWIDTH;
10182          } else if (!strcasecmp(v->value, "high")) {
10183             capability = IAX_CAPABILITY_FULLBANDWIDTH;
10184          } else
10185             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
10186       } else if (!strcasecmp(v->name, "allow")) {
10187          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
10188       } else if (!strcasecmp(v->name, "disallow")) {
10189          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
10190       } else if (!strcasecmp(v->name, "register")) {
10191          iax2_register(v->value, v->lineno);
10192       } else if (!strcasecmp(v->name, "iaxcompat")) {
10193          iaxcompat = ast_true(v->value);
10194       } else if (!strcasecmp(v->name, "regcontext")) {
10195          ast_copy_string(regcontext, v->value, sizeof(regcontext));
10196          /* Create context if it doesn't exist already */
10197          if (!ast_context_find(regcontext))
10198             ast_context_create(NULL, regcontext, "IAX2");
10199       } else if (!strcasecmp(v->name, "tos")) {
10200          if (ast_str2tos(v->value, &tos))
10201             ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno);
10202       } else if (!strcasecmp(v->name, "accountcode")) {
10203          ast_copy_string(accountcode, v->value, sizeof(accountcode));
10204       } else if (!strcasecmp(v->name, "mohinterpret")) {
10205          ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
10206       } else if (!strcasecmp(v->name, "mohsuggest")) {
10207          ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest));
10208       } else if (!strcasecmp(v->name, "amaflags")) {
10209          format = ast_cdr_amaflags2int(v->value);
10210          if (format < 0) {
10211             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
10212          } else {
10213             amaflags = format;
10214          }
10215       } else if (!strcasecmp(v->name, "language")) {
10216          ast_copy_string(language, v->value, sizeof(language));
10217       } else if (!strcasecmp(v->name, "maxauthreq")) {
10218          maxauthreq = atoi(v->value);
10219          if (maxauthreq < 0)
10220             maxauthreq = 0;
10221       } else if (!strcasecmp(v->name, "adsi")) {
10222          adsi = ast_true(v->value);
10223       } /*else if (strcasecmp(v->name,"type")) */
10224       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
10225       v = v->next;
10226    }
10227    
10228    if (defaultsockfd < 0) {
10229       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) {
10230          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
10231       } else {
10232          if (option_verbose > 1)
10233             ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
10234          defaultsockfd = ast_netsock_sockfd(ns);
10235          ast_netsock_unref(ns);
10236       }
10237    }
10238    if (reload) {
10239       ast_netsock_release(outsock);
10240       outsock = ast_netsock_list_alloc();
10241       if (!outsock) {
10242          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
10243          return -1;
10244       }
10245       ast_netsock_init(outsock);
10246    }
10247 
10248    if (min_reg_expire > max_reg_expire) {
10249       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
10250          min_reg_expire, max_reg_expire, max_reg_expire);
10251       min_reg_expire = max_reg_expire;
10252    }
10253    iax2_capability = capability;
10254    
10255    ucfg = ast_config_load("users.conf");
10256    if (ucfg) {
10257       struct ast_variable *gen;
10258       int genhasiax;
10259       int genregisteriax;
10260       const char *hasiax, *registeriax;
10261       
10262       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
10263       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
10264       gen = ast_variable_browse(ucfg, "general");
10265       cat = ast_category_browse(ucfg, NULL);
10266       while (cat) {
10267          if (strcasecmp(cat, "general")) {
10268             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
10269             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
10270             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
10271                /* Start with general parameters, then specific parameters, user and peer */
10272                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
10273                if (user) {
10274                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10275                   user = user_unref(user);
10276                }
10277                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
10278                if (peer) {
10279                   if (ast_test_flag(peer, IAX_DYNAMIC))
10280                      reg_source_db(peer);
10281                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10282                   peer = peer_unref(peer);
10283                }
10284             }
10285             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
10286                char tmp[256];
10287                const char *host = ast_variable_retrieve(ucfg, cat, "host");
10288                const char *username = ast_variable_retrieve(ucfg, cat, "username");
10289                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
10290                if (!host)
10291                   host = ast_variable_retrieve(ucfg, "general", "host");
10292                if (!username)
10293                   username = ast_variable_retrieve(ucfg, "general", "username");
10294                if (!secret)
10295                   secret = ast_variable_retrieve(ucfg, "general", "secret");
10296                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
10297                   if (!ast_strlen_zero(secret))
10298                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
10299                   else
10300                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
10301                   iax2_register(tmp, 0);
10302                }
10303             }
10304          }
10305          cat = ast_category_browse(ucfg, cat);
10306       }
10307       ast_config_destroy(ucfg);
10308    }
10309    
10310    cat = ast_category_browse(cfg, NULL);
10311    while(cat) {
10312       if (strcasecmp(cat, "general")) {
10313          utype = ast_variable_retrieve(cfg, cat, "type");
10314          if (utype) {
10315             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
10316                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
10317                if (user) {
10318                   __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10319                   user = user_unref(user);
10320                }
10321             }
10322             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
10323                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
10324                if (peer) {
10325                   if (ast_test_flag(peer, IAX_DYNAMIC))
10326                      reg_source_db(peer);
10327                   __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0);
10328                   peer = peer_unref(peer);
10329                }
10330             } else if (strcasecmp(utype, "user")) {
10331                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
10332             }
10333          } else
10334             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
10335       }
10336       cat = ast_category_browse(cfg, cat);
10337    }
10338    ast_config_destroy(cfg);
10339    set_timing();
10340    return 1;
10341 }

static void set_config_destroy ( void   )  [static]

Definition at line 9968 of file chan_iax2.c.

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

Referenced by set_config().

09969 {
09970    strcpy(accountcode, "");
09971    strcpy(language, "");
09972    strcpy(mohinterpret, "default");
09973    strcpy(mohsuggest, "");
09974    amaflags = 0;
09975    delayreject = 0;
09976    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
09977    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
09978    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
09979    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
09980    delete_users();
09981 }

static void set_timing ( void   )  [static]

Definition at line 9953 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

09954 {
09955 #ifdef HAVE_DAHDI
09956    int bs = trunkfreq * 8;
09957    if (timingfd > -1) {
09958       if (
09959 #ifdef DAHDI_TIMERACK
09960          ioctl(timingfd, DAHDI_TIMERCONFIG, &bs) &&
09961 #endif         
09962          ioctl(timingfd, DAHDI_SET_BLOCKSIZE, &bs))
09963          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
09964    }
09965 #endif
09966 }

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

Definition at line 756 of file chan_iax2.c.

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

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

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

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 7080 of file chan_iax2.c.

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

Referenced by handle_deferred_full_frames().

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

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

Definition at line 7002 of file chan_iax2.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_thread::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(), iax2_thread::list, LOG_WARNING, option_debug, ast_iax2_full_hdr::scallno, signal_condition(), iax2_thread::sin, t, thread, and ast_iax2_full_hdr::type.

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

07003 {
07004    struct iax2_thread *thread;
07005    socklen_t len;
07006    time_t t;
07007    static time_t last_errtime = 0;
07008    struct ast_iax2_full_hdr *fh;
07009 
07010    if (!(thread = find_idle_thread())) {
07011       time(&t);
07012       if (t != last_errtime && option_debug)
07013          ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n");
07014       last_errtime = t;
07015       usleep(1);
07016       return 1;
07017    }
07018 
07019    len = sizeof(thread->iosin);
07020    thread->iofd = fd;
07021    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
07022    thread->buf_size = sizeof(thread->readbuf);
07023    thread->buf = thread->readbuf;
07024    if (thread->buf_len < 0) {
07025       if (errno != ECONNREFUSED && errno != EAGAIN)
07026          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
07027       handle_error();
07028       thread->iostate = IAX_IOSTATE_IDLE;
07029       signal_condition(&thread->lock, &thread->cond);
07030       return 1;
07031    }
07032    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
07033       thread->iostate = IAX_IOSTATE_IDLE;
07034       signal_condition(&thread->lock, &thread->cond);
07035       return 1;
07036    }
07037    
07038    /* Determine if this frame is a full frame; if so, and any thread is currently
07039       processing a full frame for the same callno from this peer, then drop this
07040       frame (and the peer will retransmit it) */
07041    fh = (struct ast_iax2_full_hdr *) thread->buf;
07042    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
07043       struct iax2_thread *cur = NULL;
07044       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
07045       
07046       AST_LIST_LOCK(&active_list);
07047       AST_LIST_TRAVERSE(&active_list, cur, list) {
07048          if ((cur->ffinfo.callno == callno) &&
07049              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
07050             break;
07051       }
07052       if (cur) {
07053          /* we found another thread processing a full frame for this call,
07054             so queue it up for processing later. */
07055          defer_full_frame(thread, cur);
07056          AST_LIST_UNLOCK(&active_list);
07057          thread->iostate = IAX_IOSTATE_IDLE;
07058          signal_condition(&thread->lock, &thread->cond);
07059          return 1;
07060       } else {
07061          /* this thread is going to process this frame, so mark it */
07062          thread->ffinfo.callno = callno;
07063          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
07064          thread->ffinfo.type = fh->type;
07065          thread->ffinfo.csub = fh->csub;
07066       }
07067       AST_LIST_UNLOCK(&active_list);
07068    }
07069    
07070    /* Mark as ready and send on its way */
07071    thread->iostate = IAX_IOSTATE_READY;
07072 #ifdef DEBUG_SCHED_MULTITHREAD
07073    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
07074 #endif
07075    signal_condition(&thread->lock, &thread->cond);
07076 
07077    return 1;
07078 }

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

Definition at line 6789 of file chan_iax2.c.

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

Referenced by socket_process().

06790 {
06791    pthread_t newthread;
06792    struct dpreq_data *dpr;
06793    pthread_attr_t attr;
06794    
06795    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
06796       return;
06797 
06798    pthread_attr_init(&attr);
06799    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
06800 
06801    dpr->callno = callno;
06802    ast_copy_string(dpr->context, context, sizeof(dpr->context));
06803    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
06804    if (callerid)
06805       dpr->callerid = ast_strdup(callerid);
06806    if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
06807       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
06808    }
06809 
06810    pthread_attr_destroy(&attr);
06811 }

static int start_network_thread ( void   )  [static]

Definition at line 9258 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, iax_frame::list, LOG_WARNING, network_thread(), option_verbose, sched_thread(), thread, and VERBOSE_PREFIX_2.

Referenced by load_module().

09259 {
09260    pthread_attr_t attr;
09261    int threadcount = 0;
09262    int x;
09263    for (x = 0; x < iaxthreadcount; x++) {
09264       struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread));
09265       if (thread) {
09266          thread->type = IAX_TYPE_POOL;
09267          thread->threadnum = ++threadcount;
09268          ast_mutex_init(&thread->lock);
09269          ast_cond_init(&thread->cond, NULL);
09270          pthread_attr_init(&attr);
09271          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
09272          if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) {
09273             ast_log(LOG_WARNING, "Failed to create new thread!\n");
09274             free(thread);
09275             thread = NULL;
09276          }
09277          AST_LIST_LOCK(&idle_list);
09278          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
09279          AST_LIST_UNLOCK(&idle_list);
09280       }
09281    }
09282    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
09283    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
09284    if (option_verbose > 1)
09285       ast_verbose(VERBOSE_PREFIX_2 "%d helper threads started\n", threadcount);
09286    return 0;
09287 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 6471 of file chan_iax2.c.

References iax2_destroy_helper(), and iaxs.

Referenced by socket_process().

06472 {
06473    iax2_destroy_helper(iaxs[callno]);
06474 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1248 of file chan_iax2.c.

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

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

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

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

Definition at line 6658 of file chan_iax2.c.

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

Referenced by network_thread().

06659 {
06660    char buf[1024];
06661    int res;
06662    struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL;
06663    int processed = 0;
06664    int totalcalls = 0;
06665 #ifdef DAHDI_TIMERACK
06666    int x = 1;
06667 #endif
06668    struct timeval now;
06669    if (iaxtrunkdebug)
06670       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA);
06671    gettimeofday(&now, NULL);
06672    if (events & AST_IO_PRI) {
06673 #ifdef DAHDI_TIMERACK
06674       /* Great, this is a timing interface, just call the ioctl */
06675       if (ioctl(fd, DAHDI_TIMERACK, &x)) {
06676          ast_log(LOG_WARNING, "Unable to acknowledge timer. IAX trunking will fail!\n");
06677          usleep(1);
06678          return -1;
06679       }
06680 #endif      
06681    } else {
06682       /* Read and ignore from the pseudo channel for timing */
06683       res = read(fd, buf, sizeof(buf));
06684       if (res < 1) {
06685          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
06686          return 1;
06687       }
06688    }
06689    /* For each peer that supports trunking... */
06690    ast_mutex_lock(&tpeerlock);
06691    tpeer = tpeers;
06692    while(tpeer) {
06693       processed++;
06694       res = 0;
06695       ast_mutex_lock(&tpeer->lock);
06696       /* We can drop a single tpeer per pass.  That makes all this logic
06697          substantially easier */
06698       if (!drop && iax2_trunk_expired(tpeer, &now)) {
06699          /* Take it out of the list, but don't free it yet, because it
06700             could be in use */
06701          if (prev)
06702             prev->next = tpeer->next;
06703          else
06704             tpeers = tpeer->next;
06705          drop = tpeer;
06706       } else {
06707          res = send_trunk(tpeer, &now);
06708          if (iaxtrunkdebug)
06709             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);
06710       }     
06711       totalcalls += res;   
06712       res = 0;
06713       ast_mutex_unlock(&tpeer->lock);
06714       prev = tpeer;
06715       tpeer = tpeer->next;
06716    }
06717    ast_mutex_unlock(&tpeerlock);
06718    if (drop) {
06719       ast_mutex_lock(&drop->lock);
06720       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
06721          because by the time they could get tpeerlock, we've already grabbed it */
06722       if (option_debug)
06723          ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
06724       if (drop->trunkdata) {
06725          free(drop->trunkdata);
06726          drop->trunkdata = NULL;
06727       }
06728       ast_mutex_unlock(&drop->lock);
06729       ast_mutex_destroy(&drop->lock);
06730       free(drop);
06731       
06732    }
06733    if (iaxtrunkdebug)
06734       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
06735    iaxtrunkdebug =0;
06736    return 1;
06737 }

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

Definition at line 2129 of file chan_iax2.c.

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

Referenced by send_trunk().

02130 {
02131    int res;
02132    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
02133                sizeof(*sin));
02134    if (res < 0) {
02135       if (option_debug)
02136          ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno));
02137       handle_error();
02138    } else
02139       res = 0;
02140    return res;
02141 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1817 of file chan_iax2.c.

References ast_calloc, ast_log(), ast_random(), ast_strlen_zero(), 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, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.

Referenced by reload_firmware().

01818 {
01819    struct stat stbuf;
01820    struct iax_firmware *cur;
01821    int ifd;
01822    int fd;
01823    int res;
01824    
01825    struct ast_iax2_firmware_header *fwh, fwh2;
01826    struct MD5Context md5;
01827    unsigned char sum[16];
01828    unsigned char buf[1024];
01829    int len, chunk;
01830    char *s2;
01831    char *last;
01832    s2 = alloca(strlen(s) + 100);
01833    if (!s2) {
01834       ast_log(LOG_WARNING, "Alloca failed!\n");
01835       return -1;
01836    }
01837    last = strrchr(s, '/');
01838    if (last)
01839       last++;
01840    else
01841       last = s;
01842    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01843    res = stat(s, &stbuf);
01844    if (res < 0) {
01845       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01846       return -1;
01847    }
01848    /* Make sure it's not a directory */
01849    if (S_ISDIR(stbuf.st_mode))
01850       return -1;
01851    ifd = open(s, O_RDONLY);
01852    if (ifd < 0) {
01853       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01854       return -1;
01855    }
01856    fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600);
01857    if (fd < 0) {
01858       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
01859       close(ifd);
01860       return -1;
01861    }
01862    /* Unlink our newly created file */
01863    unlink(s2);
01864    
01865    /* Now copy the firmware into it */
01866    len = stbuf.st_size;
01867    while(len) {
01868       chunk = len;
01869       if (chunk > sizeof(buf))
01870          chunk = sizeof(buf);
01871       res = read(ifd, buf, chunk);
01872       if (res != chunk) {
01873          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01874          close(ifd);
01875          close(fd);
01876          return -1;
01877       }
01878       res = write(fd, buf, chunk);
01879       if (res != chunk) {
01880          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
01881          close(ifd);
01882          close(fd);
01883          return -1;
01884       }
01885       len -= chunk;
01886    }
01887    close(ifd);
01888    /* Return to the beginning */
01889    lseek(fd, 0, SEEK_SET);
01890    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
01891       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
01892       close(fd);
01893       return -1;
01894    }
01895    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
01896       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
01897       close(fd);
01898       return -1;
01899    }
01900    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
01901       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
01902       close(fd);
01903       return -1;
01904    }
01905    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
01906       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
01907       close(fd);
01908       return -1;
01909    }
01910    fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
01911    if (fwh == (void *) -1) {
01912       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
01913       close(fd);
01914       return -1;
01915    }
01916    MD5Init(&md5);
01917    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
01918    MD5Final(sum, &md5);
01919    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
01920       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
01921       munmap((void*)fwh, stbuf.st_size);
01922       close(fd);
01923       return -1;
01924    }
01925    cur = waresl.wares;
01926    while(cur) {
01927       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
01928          /* Found a candidate */
01929          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
01930             /* The version we have on loaded is older, load this one instead */
01931             break;
01932          /* This version is no newer than what we have.  Don't worry about it.
01933             We'll consider it a proper load anyhow though */
01934          munmap((void*)fwh, stbuf.st_size);
01935          close(fd);
01936          return 0;
01937       }
01938       cur = cur->next;
01939    }
01940    if (!cur) {
01941       /* Allocate a new one and link it */
01942       if ((cur = ast_calloc(1, sizeof(*cur)))) {
01943          cur->fd = -1;
01944          cur->next = waresl.wares;
01945          waresl.wares = cur;
01946       }
01947    }
01948    if (cur) {
01949       if (cur->fwh) {
01950          munmap((void*)cur->fwh, cur->mmaplen);
01951       }
01952       if (cur->fd > -1)
01953          close(cur->fd);
01954       cur->fwh = fwh;
01955       cur->fd = fd;
01956       cur->mmaplen = stbuf.st_size;
01957       cur->dead = 0;
01958    }
01959    return 0;
01960 }

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

Definition at line 5863 of file chan_iax2.c.

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

Referenced by socket_process().

05864 {
05865    int newcall = 0;
05866    char newip[256];
05867    struct iax_ie_data ied;
05868    struct sockaddr_in new;
05869    
05870    
05871    memset(&ied, 0, sizeof(ied));
05872    if (ies->apparent_addr)
05873       bcopy(ies->apparent_addr, &new, sizeof(new));
05874    if (ies->callno)
05875       newcall = ies->callno;
05876    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
05877       ast_log(LOG_WARNING, "Invalid transfer request\n");
05878       return -1;
05879    }
05880    pvt->transfercallno = newcall;
05881    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
05882    inet_aton(newip, &pvt->transfer.sin_addr);
05883    pvt->transfer.sin_family = AF_INET;
05884    pvt->transferring = TRANSFER_BEGIN;
05885    pvt->transferid = ies->transferid;
05886    if (ies->transferid)
05887       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
05888    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
05889    return 0; 
05890 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1093 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01094 {
01095    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01096    if (csub & IAX_FLAG_SC_LOG) {
01097       /* special case for 'compressed' -1 */
01098       if (csub == 0xff)
01099          return -1;
01100       else
01101          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01102    }
01103    else
01104       return csub;
01105 }

static void unlink_peer ( struct iax2_peer peer  )  [static]

Definition at line 6139 of file chan_iax2.c.

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

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

06140 {
06141    if (peer->expire > -1) {
06142       if (!ast_sched_del(sched, peer->expire)) {
06143          peer->expire = -1;
06144          peer_unref(peer);
06145       }
06146    }
06147 
06148    if (peer->pokeexpire > -1) {
06149       if (!ast_sched_del(sched, peer->pokeexpire)) {
06150          peer->pokeexpire = -1;
06151          peer_unref(peer);
06152       }
06153    }
06154 
06155    ao2_unlink(peers, peer);
06156 }

static int unload_module ( void   )  [static]

Definition at line 11184 of file chan_iax2.c.

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

11185 {
11186    ast_custom_function_unregister(&iaxpeer_function);
11187    return __unload_module();
11188 }

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

Definition at line 3590 of file chan_iax2.c.

References ast_mutex_unlock(), and iaxsl.

Referenced by iax2_bridge().

03591 {
03592    ast_mutex_unlock(&iaxsl[callno1]);
03593    ast_mutex_unlock(&iaxsl[callno0]);
03594 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

Definition at line 2563 of file chan_iax2.c.

References iax_frame::af, AST_FRAME_VIDEO, ast_log(), iax_frame::callno, ast_frame::frametype, iaxs, chan_iax2_pvt::last, LOG_DEBUG, option_debug, and iax_frame::ts.

Referenced by schedule_delivery().

02564 {
02565    /* Video mini frames only encode the lower 15 bits of the session
02566     * timestamp, but other frame types (e.g. audio) encode 16 bits. */
02567    const int ts_shift = (fr->af.frametype == AST_FRAME_VIDEO) ? 15 : 16;
02568    const int lower_mask = (1 << ts_shift) - 1;
02569    const int upper_mask = ~lower_mask;
02570    const int last_upper = iaxs[fr->callno]->last & upper_mask;
02571 
02572    if ( (fr->ts & upper_mask) == last_upper ) {
02573       const int x = fr->ts - iaxs[fr->callno]->last;
02574       const int threshold = (ts_shift == 15) ? 25000 : 50000;
02575 
02576       if (x < -threshold) {
02577          /* Sudden big jump backwards in timestamp:
02578             What likely happened here is that miniframe timestamp has circled but we haven't
02579             gotten the update from the main packet.  We'll just pretend that we did, and
02580             update the timestamp appropriately. */
02581          fr->ts = (last_upper + (1 << ts_shift)) | (fr->ts & lower_mask);
02582          if (option_debug && iaxdebug)
02583             ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n");
02584       } else if (x > threshold) {
02585          /* Sudden apparent big jump forwards in timestamp:
02586             What's likely happened is this is an old miniframe belonging to the previous
02587             top 15 or 16-bit timestamp that has turned up out of order.
02588             Adjust the timestamp appropriately. */
02589          fr->ts = (last_upper - (1 << ts_shift)) | (fr->ts & lower_mask);
02590          if (option_debug && iaxdebug)
02591             ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n");
02592       }
02593    }
02594 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2598 of file chan_iax2.c.

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

Referenced by __get_from_jb(), and schedule_delivery().

02599 {
02600    int when;
02601    
02602    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02603    
02604    when = jb_next(pvt->jb) - when;
02605 
02606    AST_SCHED_DEL(sched, pvt->jbid);
02607 
02608    if(when <= 0) {
02609       /* XXX should really just empty until when > 0.. */
02610       when = 1;
02611    }
02612    
02613    pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
02614 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1477 of file chan_iax2.c.

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

Referenced by __find_callno(), and make_trunk().

01478 {
01479    int max = 1;
01480    int x;
01481    /* XXX Prolly don't need locks here XXX */
01482    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01483       if (iaxs[x])
01484          max = x + 1;
01485    }
01486    maxnontrunkcall = max;
01487    if (option_debug && iaxdebug)
01488       ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max);
01489 }

static void update_max_trunk ( void   )  [static]

Definition at line 1268 of file chan_iax2.c.

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

Referenced by iax2_destroy(), and make_trunk().

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

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2200 of file chan_iax2.c.

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

Referenced by __attempt_transmit().

02201 {
02202    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02203    struct ast_iax2_full_hdr *fh = f->data;
02204    /* Mark this as a retransmission */
02205    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02206    /* Update iseqno */
02207    f->iseqno = iaxs[f->callno]->iseqno;
02208    fh->iseqno = f->iseqno;
02209    return 0;
02210 }

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 6250 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(), iax2_peer::cid_name, iax2_peer::cid_num, EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), globalflags, iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, iaxs, iaxsl, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax2_peer::mailbox, manager_event(), iax2_peer::name, option_verbose, peer_ref(), peer_unref(), realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, VERBOSE_PREFIX_3, and iax2_peer::zonetag.

Referenced by socket_process().

06251 {
06252    /* Called from IAX thread only, with proper iaxsl lock */
06253    struct iax_ie_data ied;
06254    struct iax2_peer *p;
06255    int msgcount;
06256    char data[80];
06257    int version;
06258    const char *peer_name;
06259    int res = -1;
06260 
06261    memset(&ied, 0, sizeof(ied));
06262 
06263    peer_name = ast_strdupa(iaxs[callno]->peer);
06264 
06265    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
06266    ast_mutex_unlock(&iaxsl[callno]);
06267    if (!(p = find_peer(peer_name, 1))) {
06268       ast_mutex_lock(&iaxsl[callno]);
06269       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
06270       return -1;
06271    }
06272    ast_mutex_lock(&iaxsl[callno]);
06273    if (!iaxs[callno])
06274       goto return_unref;
06275 
06276    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
06277       if (sin->sin_addr.s_addr) {
06278          time_t nowtime;
06279          time(&nowtime);
06280          realtime_update_peer(peer_name, sin, nowtime);
06281       } else {
06282          realtime_update_peer(peer_name, sin, 0);
06283       }
06284    }
06285    if (inaddrcmp(&p->addr, sin)) {
06286       if (iax2_regfunk)
06287          iax2_regfunk(p->name, 1);
06288       /* Stash the IP address from which they registered */
06289       memcpy(&p->addr, sin, sizeof(p->addr));
06290       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
06291       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
06292          ast_db_put("IAX/Registry", p->name, data);
06293          if  (option_verbose > 2)
06294             ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 
06295                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
06296          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
06297          register_peer_exten(p, 1);
06298          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06299       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
06300          if  (option_verbose > 2)
06301             ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 
06302                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
06303          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
06304          register_peer_exten(p, 0);
06305          ast_db_del("IAX/Registry", p->name);
06306          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
06307       }
06308       /* Update the host */
06309       /* Verify that the host is really there */
06310       iax2_poke_peer(p, callno);
06311    }     
06312 
06313    /* Make sure our call still exists, an INVAL at the right point may make it go away */
06314    if (!iaxs[callno]) {
06315       res = -1;
06316       goto return_unref;
06317    }
06318 
06319    /* Store socket fd */
06320    p->sockfd = fd;
06321    /* Setup the expiry */
06322    if (p->expire > -1) {
06323       if (!ast_sched_del(sched, p->expire)) {
06324          p->expire = -1;
06325          peer_unref(p);
06326       }
06327    }
06328    /* treat an unspecified refresh interval as the minimum */
06329    if (!refresh)
06330       refresh = min_reg_expire;
06331    if (refresh > max_reg_expire) {
06332       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06333          p->name, max_reg_expire, refresh);
06334       p->expiry = max_reg_expire;
06335    } else if (refresh < min_reg_expire) {
06336       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
06337          p->name, min_reg_expire, refresh);
06338       p->expiry = min_reg_expire;
06339    } else {
06340       p->expiry = refresh;
06341    }
06342    if (p->expiry && sin->sin_addr.s_addr) {
06343       p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
06344       if (p->expire == -1)
06345          peer_unref(p);
06346    }
06347    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
06348    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
06349    if (sin->sin_addr.s_addr) {
06350       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
06351       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
06352       if (!ast_strlen_zero(p->mailbox)) {
06353          int new, old;
06354          ast_app_inboxcount(p->mailbox, &new, &old);
06355          if (new > 255)
06356             new = 255;
06357          if (old > 255)
06358             old = 255;
06359          msgcount = (old << 8) | new;
06360          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
06361       }
06362       if (ast_test_flag(p, IAX_HASCALLERID)) {
06363          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
06364          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
06365       }
06366    }
06367    version = iax_check_version(devtype);
06368    if (version) 
06369       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
06370 
06371    res = 0;
06372 
06373 return_unref:
06374    peer_unref(p);
06375 
06376    return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
06377 }

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

References iax2_user::name.

Referenced by load_module().

01141 {
01142    struct iax2_user *user = obj, *user2 = arg;
01143 
01144    return !strcmp(user->name, user2->name) ? CMP_MATCH | CMP_STOP : 0;
01145 }

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

Definition at line 9890 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

09891 {
09892    struct iax2_user *user = obj;
09893 
09894    ast_set_flag(user, IAX_DELME);
09895 
09896    return 0;
09897 }

static void user_destructor ( void *  obj  )  [static]

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

09655 {
09656    struct iax2_user *user = obj;
09657 
09658    ast_free_ha(user->ha);
09659    free_context(user->contexts);
09660    if(user->vars) {
09661       ast_variables_destroy(user->vars);
09662       user->vars = NULL;
09663    }
09664    ast_string_field_free_memory(user);
09665 }

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

References ast_str_hash(), and iax2_user::name.

Referenced by load_module().

01131 {
01132    const struct iax2_user *user = obj;
01133 
01134    return ast_str_hash(user->name);
01135 }

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

Definition at line 1179 of file chan_iax2.c.

References ao2_ref().

01180 {
01181    ao2_ref(user, +1);
01182    return user;
01183 }

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

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

01186 {
01187    ao2_ref(user, -1);
01188    return NULL;
01189 }

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

Definition at line 6572 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, f, iaxq, iaxs, iax_frame::list, ast_iax2_queue::queue, and send_packet().

Referenced by socket_process().

06573 {
06574    struct iax_frame *f;
06575 
06576    AST_LIST_LOCK(&iaxq.queue);
06577    AST_LIST_TRAVERSE(&iaxq.queue, f, list) {
06578       /* Send a copy immediately */
06579       if ((f->callno == callno) && iaxs[f->callno] &&
06580          ((unsigned char ) (f->oseqno - last) < 128) &&
06581          (f->retries >= 0)) {
06582          send_packet(f);
06583       }
06584    }
06585    AST_LIST_UNLOCK(&iaxq.queue);
06586 }

static int wait_for_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Note:
expects the pvt to be locked

Definition at line 3488 of file chan_iax2.c.

References chan_iax2_pvt::callno, DEADLOCK_AVOIDANCE, iaxs, iaxsl, and chan_iax2_pvt::peercallno.

Referenced by iax2_indicate(), and iax2_setoption().

03489 {
03490    unsigned short callno = pvt->callno;
03491 
03492    if (!pvt->peercallno) {
03493       /* We don't know the remote side's call number, yet.  :( */
03494       int count = 10;
03495       while (count-- && pvt && !pvt->peercallno) {
03496          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
03497          pvt = iaxs[callno];
03498       }
03499       if (!pvt->peercallno) {
03500          return -1;
03501       }
03502    }
03503 
03504    return 0;
03505 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Inter Asterisk eXchange (Ver 2)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 11337 of file chan_iax2.c.

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 216 of file chan_iax2.c.

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

int adsi = 0 [static]

Definition at line 220 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

Definition at line 219 of file chan_iax2.c.

Referenced by build_device(), and build_gateway().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 11337 of file chan_iax2.c.

int authdebug = 1 [static]

Definition at line 155 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 156 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 11000 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry cli_iax2_jb_debug_deprecated [static]

Initial value:

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

Definition at line 10980 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_debug_deprecated [static]

Initial value:

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

Definition at line 10985 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_jb_debug_deprecated [static]

Initial value:

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

Definition at line 10995 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_no_trunk_debug_deprecated [static]

Initial value:

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

Definition at line 10990 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_trunk_debug_deprecated [static]

Initial value:

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

Definition at line 10975 of file chan_iax2.c.

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

Definition at line 142 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 10949 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 10941 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 10933 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 173 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 221 of file chan_iax2.c.

struct iax2_dpcache * dpcache [static]

Referenced by find_cache(), and iax2_show_cache().

ast_mutex_t dpcache_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 688 of file chan_iax2.c.

Referenced by complete_dpreply(), find_cache(), iax2_canmatch(), iax2_exec(), iax2_exists(), iax2_matchmore(), iax2_show_cache(), and socket_process().

int global_rtautoclear = 120 [static]

Definition at line 275 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

Definition at line 224 of file chan_iax2.c.

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

int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static]

Definition at line 202 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 222 of file chan_iax2.c.

enum { ... } iax2_flags

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

Definition at line 175 of file chan_iax2.c.

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

char iax2_reload_usage[] [static]

Initial value:

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

Definition at line 10891 of file chan_iax2.c.

enum { ... } iax2_state

struct ast_switch iax2_switch [static]

Definition at line 10865 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

Definition at line 865 of file chan_iax2.c.

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

char iax2_test_losspct_usage[] [static]

Initial value:

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

Definition at line 10957 of file chan_iax2.c.

struct ao2_container* iax_peercallno_pvts [static]

Another container of iax2_pvt structures.

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

Definition at line 824 of file chan_iax2.c.

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

int iaxactivethreadcount = 0 [static]

Definition at line 452 of file chan_iax2.c.

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

int iaxcompat = 0 [static]

Definition at line 157 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 204 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 160 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 162 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 450 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxdynamicthreadnum = 0 [static]

Definition at line 451 of file chan_iax2.c.

Referenced by find_idle_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 449 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 10801 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct ast_iax2_queue iaxq [static]

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

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

Definition at line 811 of file chan_iax2.c.

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

ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static]

Definition at line 812 of file chan_iax2.c.

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

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 448 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 206 of file chan_iax2.c.

struct io_context* io [static]

Definition at line 199 of file chan_iax2.c.

int lagrq_time = 10 [static]

Definition at line 150 of file chan_iax2.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 144 of file chan_iax2.c.

int last_authmethod = 0 [static]

Definition at line 158 of file chan_iax2.c.

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

Definition at line 813 of file chan_iax2.c.

int max_reg_expire [static]

Definition at line 167 of file chan_iax2.c.

int max_retries = 4 [static]

Definition at line 148 of file chan_iax2.c.

int maxauthreq = 3 [static]

Definition at line 147 of file chan_iax2.c.

int maxjitterbuffer = 1000 [static]

Definition at line 151 of file chan_iax2.c.

int maxjitterinterps = 10 [static]

Definition at line 153 of file chan_iax2.c.

int maxnontrunkcall = 1 [static]

Definition at line 831 of file chan_iax2.c.

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 830 of file chan_iax2.c.

int min_reg_expire [static]

Definition at line 166 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 217 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 218 of file chan_iax2.c.

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

struct ast_netsock_list* netsock [static]

Definition at line 171 of file chan_iax2.c.

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

pthread_t netthreadid = AST_PTHREADT_NULL [static]

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

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 172 of file chan_iax2.c.

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

char* papp = "IAX2Provision" [static]

Definition at line 8906 of file chan_iax2.c.

char* pdescrip [static]

Initial value:

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

Definition at line 8908 of file chan_iax2.c.

struct ao2_container* peers [static]

Definition at line 649 of file chan_iax2.c.

int ping_time = 21 [static]

Definition at line 149 of file chan_iax2.c.

struct ast_codec_pref prefs [static]

Definition at line 138 of file chan_iax2.c.

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

char prune_realtime_usage[] [static]

Initial value:

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

Definition at line 10887 of file chan_iax2.c.

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

Definition at line 8907 of file chan_iax2.c.

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 145 of file chan_iax2.c.

int resyncthreshold = 1000 [static]

Definition at line 152 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 200 of file chan_iax2.c.

ast_cond_t sched_cond [static]

Definition at line 229 of file chan_iax2.c.

ast_mutex_t sched_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 228 of file chan_iax2.c.

Referenced by __unload_module(), iax2_sched_add(), iax2_transmit(), and sched_thread().

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 227 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 10879 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 10907 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 10925 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 10911 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 10883 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 10919 of file chan_iax2.c.

char show_prov_usage[] [static]

Definition at line 10895 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 10929 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 10875 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 10915 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 10902 of file chan_iax2.c.

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

Definition at line 140 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 208 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 169 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 164 of file chan_iax2.c.

ast_mutex_t tpeerlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 381 of file chan_iax2.c.

Referenced by find_tpeer(), and timing_read().

struct iax2_trunk_peer * tpeers [static]

Referenced by find_tpeer(), and timing_read().

int trunkfreq = 20 [static]

Definition at line 154 of file chan_iax2.c.

struct ao2_container* users [static]

Definition at line 652 of file chan_iax2.c.

struct ast_firmware_list waresl [static]

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


Generated on Wed Feb 11 12:00:13 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7