Thu Jul 9 13:40:58 2009

Asterisk developer's documentation


chan_iax2.c File Reference

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

#include "asterisk.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 <strings.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <regex.h>
#include <sys/ioctl.h>
#include <dahdi/user.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/config.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/event.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  chan_iax2_pvt
struct  create_addr_info
struct  dpcache
struct  dpreq_data
struct  dynamic_list
struct  firmwares
struct  frame_queue
 a list of frames that may need to be retransmitted More...
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
struct  tpeers

Defines

#define ACN_FORMAT1   "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n"
#define ACN_FORMAT2   "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n"
#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 %s%s %3s%s\n"
#define FORMAT   "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\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 %s %9s\n"
#define FORMAT2   "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\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 & ~AST_FORMAT_AUDIO_UNDEFINED)
#define IAX_CAPABILITY_LOWBANDWIDTH
#define IAX_CAPABILITY_LOWFREE
#define IAX_CAPABILITY_MEDBANDWIDTH
#define MARK_IAX_SUBCLASS_TX   0x8000
#define MAX_JITTER_BUFFER   50
#define MAX_PEER_BUCKETS   563
#define MAX_RETRY_TIME   10000
#define MAX_TIMESTAMP_SKEW   160
#define MAX_TRUNK_MTU   1240
 Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240.
#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  {
  CACHE_FLAG_EXISTS = (1 << 0), CACHE_FLAG_NONEXISTENT = (1 << 1), CACHE_FLAG_CANEXIST = (1 << 2), CACHE_FLAG_PENDING = (1 << 3),
  CACHE_FLAG_TIMEOUT = (1 << 4), CACHE_FLAG_TRANSMITTED = (1 << 5), CACHE_FLAG_UNKNOWN = (1 << 6), CACHE_FLAG_MATCHMORE = (1 << 7)
}
enum  iax2_flags {
  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  iax2_state { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2) }
enum  iax2_thread_iostate { IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_SCHEDREADY }
enum  iax2_thread_type { IAX_THREAD_TYPE_POOL, IAX_THREAD_TYPE_DYNAMIC }
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 acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen)
static int acf_channel_write (struct ast_channel *chan, const char *function, char *data, const char *value)
static int acf_iaxvar_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int acf_iaxvar_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
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, struct chan_iax2_pvt *pvt)
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 (const char *context)
static void build_ecx_key (const unsigned char *digest, struct chan_iax2_pvt *pvt)
static void build_encryption_keys (const unsigned char *digest, struct chan_iax2_pvt *pvt)
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 void build_rand_pad (unsigned char *buf, ssize_t len)
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 char * complete_iax2_unregister (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 (ast_aes_decrypt_key *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 (ast_aes_encrypt_key *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 struct iax2_userfind_user (const char *name)
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, const char *cmd, char *data, char *buf, size_t len)
static int get_auth_methods (const char *value)
static int get_encrypt_methods (const char *s)
static int get_from_jb (const void *p)
static char * handle_cli_iax2_provision (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_prune_realtime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_set_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_set_debug_jb (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_set_debug_jb_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_set_debug_trunk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_set_debug_trunk_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_set_mtu (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Set trunk MTU from CLI.
static char * handle_cli_iax2_show_cache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_firmware (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_netstats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show one peer in detail.
static char * handle_cli_iax2_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_registry (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_threads (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_test_losspct (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_iax2_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 void iax2_ami_channelupdate (struct chan_iax2_pvt *pvt)
 Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers.
static int iax2_answer (struct ast_channel *c)
static int iax2_append_register (const char *hostname, const char *username, const char *secret, const char *porta)
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_register (struct iax2_registry *reg)
static int iax2_do_register_s (const void *data)
static void iax2_dprequest (struct iax2_dpcache *dp, int callno)
static void * iax2_dup_variable_datastore (void *)
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 void iax2_free_variable_datastore (void *)
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_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_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force)
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 (const char *value, int lineno)
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_sched_replace (int id, 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_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly)
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 void log_jitterstats (unsigned short callno)
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_peer_list (struct mansession *s, const struct message *m)
 callback to display iax peers in manager format
static int manager_iax2_show_peers (struct mansession *s, const struct message *m)
 callback to display iax peers in manager
static int match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
static void memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, ast_aes_decrypt_key *dcx)
static void memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, ast_aes_encrypt_key *ecx)
static void merge_encryption (struct chan_iax2_pvt *p, unsigned int enc)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
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 remove_by_transfercallno (struct chan_iax2_pvt *pvt)
static void save_osptoken (struct iax_frame *fr, struct iax_ies *ies)
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_process_meta (int packet_len, struct ast_iax2_meta_hdr *meta, struct sockaddr_in *sin, int sockfd, struct iax_frame *fr)
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 void store_by_transfercallno (struct chan_iax2_pvt *pvt)
static int timing_read (int *id, int fd, short events, void *cbdata)
static int transfercallno_pvt_cmp_cb (void *obj, void *arg, int flags)
static int transfercallno_pvt_hash_cb (const void *obj, const int flags)
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 , .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 = "068e67f60f50dd9ee86464c05884a49d" , .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_set_debug_deprecated = { .handler = handle_cli_iax2_set_debug_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ }
static struct ast_cli_entry cli_iax2_set_debug_jb_deprecated = { .handler = handle_cli_iax2_set_debug_jb_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ }
static struct ast_cli_entry cli_iax2_set_debug_trunk_deprecated = { .handler = handle_cli_iax2_set_debug_trunk_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ }
static char context [80] = "default"
static unsigned int cos = 0
static int defaultsockfd = -1
static int delayreject = 0
static int global_max_trunk_mtu
static int global_rtautoclear = 120
static struct ast_flags globalflags = { 0 }
static int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH
static int iax2_encryption = 0
int(*) iax2_regfunk (const char *username, int onoff) = NULL
static struct ast_switch iax2_switch
static struct ast_channel_tech iax2_tech
static struct ast_datastore_info iax2_variable_datastore_info
static struct ao2_containeriax_peercallno_pvts
 Another container of iax2_pvt structures.
static struct ao2_containeriax_transfercallno_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 chan_iax2_pvtiaxs [IAX_MAX_CALLS]
 an array of iax2 pvt structures
static ast_mutex_t iaxsl [ARRAY_LEN(iaxs)]
 chan_iax2_pvt structure locks
static int iaxthreadcount = DEFAULT_THREAD_COUNT
static int iaxtrunkdebug = 0
static struct ast_custom_function iaxvar_function
static struct io_contextio
static int jittertargetextra = 40
static int lagrq_time = 10
static char language [MAX_LANGUAGE] = ""
static int last_authmethod = 0
static struct timeval lastused [ARRAY_LEN(iaxs)]
 The last time a call number was used.
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 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 * 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_RECURSIVE_MUTEX_INITIALIZER_NP )
static pthread_t schedthreadid = AST_PTHREADT_NULL
static int srvlookup = 0
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 int trunk_maxmtu
static int trunk_nmaxmtu
static int trunk_timed
static int trunk_untimed
static int trunkfreq = 20
static int trunkmaxsize = MAX_TRUNKDATA
static struct ao2_containerusers


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 ACN_FORMAT1   "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n"

Referenced by ast_cli_netstats().

#define ACN_FORMAT2   "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n"

Referenced by ast_cli_netstats().

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

Definition at line 114 of file chan_iax2.c.

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

#define DEBUG_SCHED_MULTITHREAD

Definition at line 105 of file chan_iax2.c.

#define DEBUG_SUPPORT

Definition at line 122 of file chan_iax2.c.

#define DEFAULT_DROP   3

Definition at line 120 of file chan_iax2.c.

#define DEFAULT_FREQ_NOTOK   10 * 1000

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

Referenced by build_peer().

#define DEFAULT_MAX_THREAD_COUNT   100

Definition at line 117 of file chan_iax2.c.

#define DEFAULT_MAXMS   2000

Definition at line 206 of file chan_iax2.c.

#define DEFAULT_RETRY_TIME   1000

Definition at line 118 of file chan_iax2.c.

Referenced by __find_callno(), and complete_transfer().

#define DEFAULT_THREAD_COUNT   10

Definition at line 116 of file chan_iax2.c.

#define DEFAULT_TRUNKDATA   640 * 10

40ms, uncompressed linear * 10 channels

Definition at line 450 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 %s%s %3s%s\n"

#define FORMAT   "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\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 %s %9s\n"

#define FORMAT2   "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\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 127 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 371 of file chan_iax2.c.

Referenced by iax2_trunk_queue().

#define IAX_CAPABILITY_FULLBANDWIDTH   (0xFFFF & ~AST_FORMAT_AUDIO_UNDEFINED)

Definition at line 188 of file chan_iax2.c.

Referenced by cache_get_callno_locked(), and set_config().

#define IAX_CAPABILITY_LOWBANDWIDTH

Value:

Definition at line 197 of file chan_iax2.c.

Referenced by set_config().

#define IAX_CAPABILITY_LOWFREE

Value:

Definition at line 202 of file chan_iax2.c.

#define IAX_CAPABILITY_MEDBANDWIDTH

Definition at line 190 of file chan_iax2.c.

Referenced by set_config().

#define MARK_IAX_SUBCLASS_TX   0x8000

Definition at line 458 of file chan_iax2.c.

Referenced by ast_cli_netstats(), handle_cli_iax2_show_channels(), and iax2_send().

#define MAX_JITTER_BUFFER   50

Definition at line 447 of file chan_iax2.c.

#define MAX_PEER_BUCKETS   563

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

Referenced by load_module().

#define MAX_RETRY_TIME   10000

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

#define MAX_TRUNK_MTU   1240

Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240.

Definition at line 136 of file chan_iax2.c.

Referenced by handle_cli_iax2_set_mtu(), and set_config().

#define MAX_TRUNKDATA   640 * 200

40ms, uncompressed linear * 200 channels

Definition at line 156 of file chan_iax2.c.

Referenced by set_config(), and set_config_destroy().

#define MAX_USER_BUCKETS   MAX_PEER_BUCKETS

Definition at line 679 of file chan_iax2.c.

Referenced by load_module().

#define MEMORY_SIZE   100

Definition at line 119 of file chan_iax2.c.

#define MIN_JITTER_BUFFER   10

Definition at line 448 of file chan_iax2.c.

#define MIN_RETRY_TIME   100

Definition at line 444 of file chan_iax2.c.

Referenced by iax2_send().

#define MIN_REUSE_TIME   60

Definition at line 124 of file chan_iax2.c.

Referenced by __find_callno(), and make_trunk().

#define NEW_ALLOW   1

Definition at line 1539 of file chan_iax2.c.

Referenced by __find_callno(), and socket_process().

#define NEW_FORCE   2

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

Referenced by socket_process(), and socket_process_meta().

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

Definition at line 113 of file chan_iax2.c.

Referenced by __auto_congest(), __get_from_jb(), acf_channel_read(), acf_channel_write(), 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 101 of file chan_iax2.c.

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

Definition at line 1144 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 904 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 455 of file chan_iax2.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
CACHE_FLAG_EXISTS  Extension exists
CACHE_FLAG_NONEXISTENT  Extension is nonexistent
CACHE_FLAG_CANEXIST  Extension can exist
CACHE_FLAG_PENDING  Waiting to hear back response
CACHE_FLAG_TIMEOUT  Timed out
CACHE_FLAG_TRANSMITTED  Request transmitted
CACHE_FLAG_UNKNOWN  Timeout
CACHE_FLAG_MATCHMORE  Matchmore

Definition at line 684 of file chan_iax2.c.

00684      {
00685    /*! Extension exists */
00686    CACHE_FLAG_EXISTS      = (1 << 0),
00687    /*! Extension is nonexistent */
00688    CACHE_FLAG_NONEXISTENT = (1 << 1),
00689    /*! Extension can exist */
00690    CACHE_FLAG_CANEXIST    = (1 << 2),
00691    /*! Waiting to hear back response */
00692    CACHE_FLAG_PENDING     = (1 << 3),
00693    /*! Timed out */
00694    CACHE_FLAG_TIMEOUT     = (1 << 4),
00695    /*! Request transmitted */
00696    CACHE_FLAG_TRANSMITTED = (1 << 5),
00697    /*! Timeout */
00698    CACHE_FLAG_UNKNOWN     = (1 << 6),
00699    /*! Matchmore */
00700    CACHE_FLAG_MATCHMORE   = (1 << 7),
00701 };

enum iax2_flags

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

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

enum iax2_state

Enumerator:
IAX_STATE_STARTED 
IAX_STATE_AUTHENTICATED 
IAX_STATE_TBD 

Definition at line 242 of file chan_iax2.c.

00242                 {
00243    IAX_STATE_STARTED =        (1 << 0),
00244    IAX_STATE_AUTHENTICATED =  (1 << 1),
00245    IAX_STATE_TBD =            (1 << 2),
00246 };

enum iax2_thread_iostate

Enumerator:
IAX_IOSTATE_IDLE 
IAX_IOSTATE_READY 
IAX_IOSTATE_PROCESSING 
IAX_IOSTATE_SCHEDREADY 

Definition at line 724 of file chan_iax2.c.

enum iax2_thread_type

Enumerator:
IAX_THREAD_TYPE_POOL 
IAX_THREAD_TYPE_DYNAMIC 

Definition at line 731 of file chan_iax2.c.

00731                       {
00732    IAX_THREAD_TYPE_POOL,
00733    IAX_THREAD_TYPE_DYNAMIC,
00734 };

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


Function Documentation

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

Definition at line 2419 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(), iax_frame::callno, f, ast_frame::frametype, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iax2_trunk_peer::list, LOG_WARNING, MAX_RETRY_TIME, ast_format::name, REG_STATE_TIMEOUT, sched, send_command(), send_packet(), ast_frame::subclass, and update_packet().

Referenced by attempt_transmit().

02420 {
02421    /* Attempt to transmit the frame to the remote peer...
02422       Called without iaxsl held. */
02423    struct iax_frame *f = (struct iax_frame *)data;
02424    int freeme = 0;
02425    int callno = f->callno;
02426    /* Make sure this call is still active */
02427    if (callno) 
02428       ast_mutex_lock(&iaxsl[callno]);
02429    if (callno && iaxs[callno]) {
02430       if ((f->retries < 0) /* Already ACK'd */ ||
02431           (f->retries >= max_retries) /* Too many attempts */) {
02432             /* Record an error if we've transmitted too many times */
02433             if (f->retries >= max_retries) {
02434                if (f->transfer) {
02435                   /* Transfer timeout */
02436                   send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
02437                } else if (f->final) {
02438                   if (f->final) 
02439                      iax2_destroy(callno);
02440                } else {
02441                   if (iaxs[callno]->owner)
02442                      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);
02443                   iaxs[callno]->error = ETIMEDOUT;
02444                   if (iaxs[callno]->owner) {
02445                      struct ast_frame fr = { 0, };
02446                      /* Hangup the fd */
02447                      fr.frametype = AST_FRAME_CONTROL;
02448                      fr.subclass = AST_CONTROL_HANGUP;
02449                      iax2_queue_frame(callno, &fr); /* XXX */
02450                      /* Remember, owner could disappear */
02451                      if (iaxs[callno] && iaxs[callno]->owner)
02452                         iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
02453                   } else {
02454                      if (iaxs[callno]->reg) {
02455                         memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us));
02456                         iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT;
02457                         iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE;
02458                      }
02459                      iax2_destroy(callno);
02460                   }
02461                }
02462 
02463             }
02464             freeme = 1;
02465       } else {
02466          /* Update it if it needs it */
02467          update_packet(f);
02468          /* Attempt transmission */
02469          send_packet(f);
02470          f->retries++;
02471          /* Try again later after 10 times as long */
02472          f->retrytime *= 10;
02473          if (f->retrytime > MAX_RETRY_TIME)
02474             f->retrytime = MAX_RETRY_TIME;
02475          /* Transfer messages max out at one second */
02476          if (f->transfer && (f->retrytime > 1000))
02477             f->retrytime = 1000;
02478          f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
02479       }
02480    } else {
02481       /* Make sure it gets freed */
02482       f->retries = -1;
02483       freeme = 1;
02484    }
02485    if (callno)
02486       ast_mutex_unlock(&iaxsl[callno]);
02487    /* Do not try again */
02488    if (freeme) {
02489       /* Don't attempt delivery, just remove it from the queue */
02490       AST_LIST_LOCK(&frame_queue);
02491       AST_LIST_REMOVE(&frame_queue, f, list);
02492       AST_LIST_UNLOCK(&frame_queue);
02493       f->retrans = -1;
02494       /* Free the IAX frame */
02495       iax2_frame_free(f);
02496    }
02497 }

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

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

Referenced by auth_reject().

07371 {
07372    /* Called from IAX thread only, without iaxs lock */
07373    int callno = (int)(long)(nothing);
07374    struct iax_ie_data ied;
07375    ast_mutex_lock(&iaxsl[callno]);
07376    if (iaxs[callno]) {
07377       memset(&ied, 0, sizeof(ied));
07378       if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
07379          iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
07380          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
07381       } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
07382          iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
07383          iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
07384       }
07385       send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
07386    }
07387    ast_mutex_unlock(&iaxsl[callno]);
07388 }

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

Definition at line 3527 of file chan_iax2.c.

References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, iax2_queue_frame(), LOG_NOTICE, and PTR_TO_CALLNO.

Referenced by auto_congest().

03528 {
03529    int callno = PTR_TO_CALLNO(nothing);
03530    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
03531    ast_mutex_lock(&iaxsl[callno]);
03532    if (iaxs[callno]) {
03533       iaxs[callno]->initid = -1;
03534       iax2_queue_frame(callno, &f);
03535       ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n");
03536    }
03537    ast_mutex_unlock(&iaxsl[callno]);
03538 }

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

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

Referenced by auto_hangup().

07420 {
07421    /* Called from IAX thread only, without iaxs lock */
07422    int callno = (int)(long)(nothing);
07423    struct iax_ie_data ied;
07424    ast_mutex_lock(&iaxsl[callno]);
07425    if (iaxs[callno]) {
07426       memset(&ied, 0, sizeof(ied));
07427       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
07428       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
07429       send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
07430    }
07431    ast_mutex_unlock(&iaxsl[callno]);
07432 }

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 2213 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, and iax_frame::retrans.

Referenced by __get_from_jb(), and schedule_delivery().

02214 {
02215    /* Just deliver the packet by using queueing.  This is called by
02216      the IAX thread with the iaxsl lock held. */
02217    struct iax_frame *fr = data;
02218    fr->retrans = -1;
02219    ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
02220    if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
02221       iax2_queue_frame(fr->callno, &fr->af);
02222    /* Free our iax frame */
02223    iax2_frame_free(fr);
02224    /* And don't run again */
02225    return 0;
02226 }

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

Definition at line 7032 of file chan_iax2.c.

References iax2_peer::addr, ast_db_del(), ast_debug, ast_device_state_changed(), 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, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().

Referenced by expire_registry().

07033 {
07034    struct iax2_peer *peer = (struct iax2_peer *) data;
07035 
07036    if (!peer)
07037       return;
07038 
07039    peer->expire = -1;
07040 
07041    ast_debug(1, "Expiring registration for peer '%s'\n", peer->name);
07042    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
07043       realtime_update_peer(peer->name, &peer->addr, 0);
07044    manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
07045    /* Reset the address */
07046    memset(&peer->addr, 0, sizeof(peer->addr));
07047    /* Reset expiry value */
07048    peer->expiry = min_reg_expire;
07049    if (!ast_test_flag(peer, IAX_TEMPONLY))
07050       ast_db_del("IAX/Registry", peer->name);
07051    register_peer_exten(peer, 0);
07052    ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
07053    if (iax2_regfunk)
07054       iax2_regfunk(peer->name, 0);
07055 
07056    if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
07057       unlink_peer(peer);
07058 
07059    peer_unref(peer);
07060 }

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]

Definition at line 1685 of file chan_iax2.c.

References chan_iax2_pvt::addr, ao2_find(), ao2_ref(), ast_copy_flags, ast_debug, 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_transfercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, LOG_WARNING, match(), MIN_REUSE_TIME, NEW_ALLOW, new_iax(), OBJ_POINTER, chan_iax2_pvt::peercallno, sched, send_lagrq(), send_ping(), store_by_peercallno(), chan_iax2_pvt::transfer, TRUNK_CALL_START, and update_max_nontrunk().

Referenced by find_callno(), and find_callno_locked().

01686 {
01687    int res = 0;
01688    int x;
01689    struct timeval now;
01690    char host[80];
01691 
01692    if (new <= NEW_ALLOW) {
01693       if (callno) {
01694          struct chan_iax2_pvt *pvt;
01695          struct chan_iax2_pvt tmp_pvt = {
01696             .callno = dcallno,
01697             .peercallno = callno,
01698             .transfercallno = callno,
01699             /* hack!! */
01700             .frames_received = check_dcallno,
01701          };
01702 
01703          memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
01704          /* this works for finding normal call numbers not involving transfering */ 
01705          if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
01706             if (return_locked) {
01707                ast_mutex_lock(&iaxsl[pvt->callno]);
01708             }
01709             res = pvt->callno;
01710             ao2_ref(pvt, -1);
01711             pvt = NULL;
01712             return res;
01713          }
01714          /* this searches for transfer call numbers that might not get caught otherwise */
01715          memset(&tmp_pvt.addr, 0, sizeof(tmp_pvt.addr));
01716          memcpy(&tmp_pvt.transfer, sin, sizeof(tmp_pvt.addr));
01717          if ((pvt = ao2_find(iax_transfercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
01718             if (return_locked) {
01719                ast_mutex_lock(&iaxsl[pvt->callno]);
01720             }
01721             res = pvt->callno;
01722             ao2_ref(pvt, -1);
01723             pvt = NULL;
01724             return res;
01725          }
01726       }
01727          /* This will occur on the first response to a message that we initiated,
01728        * such as a PING. */
01729       if (dcallno) {
01730          ast_mutex_lock(&iaxsl[dcallno]);
01731       }
01732       if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) {
01733          iaxs[dcallno]->peercallno = callno;
01734          res = dcallno;
01735          store_by_peercallno(iaxs[dcallno]);
01736          if (!res || !return_locked) {
01737             ast_mutex_unlock(&iaxsl[dcallno]);
01738          }
01739          return res;
01740       }
01741       if (dcallno) {
01742          ast_mutex_unlock(&iaxsl[dcallno]);
01743       }
01744 #ifdef IAX_OLD_FIND
01745       /* If we get here, we SHOULD NOT find a call structure for this
01746          callno; if we do, it means that there is a call structure that
01747          has a peer callno but did NOT get entered into the hash table,
01748          which is bad.
01749 
01750          If we find a call structure using this old, slow method, output a log
01751          message so we'll know about it. After a few months of leaving this in
01752          place, if we don't hear about people seeing these messages, we can
01753          remove this code for good.
01754       */
01755 
01756       for (x = 1; !res && x < maxnontrunkcall; x++) {
01757          ast_mutex_lock(&iaxsl[x]);
01758          if (iaxs[x]) {
01759             /* Look for an exact match */
01760             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01761                res = x;
01762             }
01763          }
01764          if (!res || !return_locked)
01765             ast_mutex_unlock(&iaxsl[x]);
01766       }
01767       for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) {
01768          ast_mutex_lock(&iaxsl[x]);
01769          if (iaxs[x]) {
01770             /* Look for an exact match */
01771             if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) {
01772                res = x;
01773             }
01774          }
01775          if (!res || !return_locked)
01776             ast_mutex_unlock(&iaxsl[x]);
01777       }
01778 #endif
01779    }
01780    if (!res && (new >= NEW_ALLOW)) {
01781       int start, found = 0;
01782 
01783       /* It may seem odd that we look through the peer list for a name for
01784        * this *incoming* call.  Well, it is weird.  However, users don't
01785        * have an IP address/port number that we can match against.  So,
01786        * this is just checking for a peer that has that IP/port and
01787        * assuming that we have a user of the same name.  This isn't always
01788        * correct, but it will be changed if needed after authentication. */
01789       if (!iax2_getpeername(*sin, host, sizeof(host)))
01790          snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
01791 
01792       now = ast_tvnow();
01793       start = 2 + (ast_random() % (TRUNK_CALL_START - 1));
01794       for (x = start; 1; x++) {
01795          if (x == TRUNK_CALL_START) {
01796             x = 1;
01797             continue;
01798          }
01799 
01800          /* Find first unused call number that hasn't been used in a while */
01801          ast_mutex_lock(&iaxsl[x]);
01802          if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01803             found = 1;
01804             break;
01805          }
01806          ast_mutex_unlock(&iaxsl[x]);
01807          
01808          if (x == start - 1) {
01809             break;
01810          }
01811       }
01812       /* We've still got lock held if we found a spot */
01813       if (x == start - 1 && !found) {
01814          ast_log(LOG_WARNING, "No more space\n");
01815          return 0;
01816       }
01817       iaxs[x] = new_iax(sin, host);
01818       update_max_nontrunk();
01819       if (iaxs[x]) {
01820          if (iaxdebug)
01821             ast_debug(1, "Creating new call structure %d\n", x);
01822          iaxs[x]->sockfd = sockfd;
01823          iaxs[x]->addr.sin_port = sin->sin_port;
01824          iaxs[x]->addr.sin_family = sin->sin_family;
01825          iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr;
01826          iaxs[x]->peercallno = callno;
01827          iaxs[x]->callno = x;
01828          iaxs[x]->pingtime = DEFAULT_RETRY_TIME;
01829          iaxs[x]->expiry = min_reg_expire;
01830          iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
01831          iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
01832          iaxs[x]->amaflags = amaflags;
01833          ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
01834          
01835          ast_string_field_set(iaxs[x], accountcode, accountcode);
01836          ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
01837          ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
01838 
01839          if (iaxs[x]->peercallno) {
01840             store_by_peercallno(iaxs[x]);
01841          }
01842       } else {
01843          ast_log(LOG_WARNING, "Out of resources\n");
01844          ast_mutex_unlock(&iaxsl[x]);
01845          return 0;
01846       }
01847       if (!return_locked)
01848          ast_mutex_unlock(&iaxsl[x]);
01849       res = x;
01850    }
01851    return res;
01852 }

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

Definition at line 2980 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(), ast_tvnow(), jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, 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_trunk_peer::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().

02981 {
02982    int callno = PTR_TO_CALLNO(p);
02983    struct chan_iax2_pvt *pvt = NULL;
02984    struct iax_frame *fr;
02985    jb_frame frame;
02986    int ret;
02987    long now;
02988    long next;
02989    struct timeval tv = ast_tvnow();
02990    
02991    /* Make sure we have a valid private structure before going on */
02992    ast_mutex_lock(&iaxsl[callno]);
02993    pvt = iaxs[callno];
02994    if (!pvt) {
02995       /* No go! */
02996       ast_mutex_unlock(&iaxsl[callno]);
02997       return;
02998    }
02999 
03000    pvt->jbid = -1;
03001    
03002    /* round up a millisecond since ast_sched_runq does; */
03003    /* prevents us from spinning while waiting for our now */
03004    /* to catch up with runq's now */
03005    tv.tv_usec += 1000;
03006    
03007    now = ast_tvdiff_ms(tv, pvt->rxcore);
03008    
03009    if(now >= (next = jb_next(pvt->jb))) {
03010       ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
03011       switch(ret) {
03012       case JB_OK:
03013          fr = frame.data;
03014          __do_deliver(fr);
03015          /* __do_deliver() can cause the call to disappear */
03016          pvt = iaxs[callno];
03017          break;
03018       case JB_INTERP:
03019       {
03020          struct ast_frame af = { 0, };
03021          
03022          /* create an interpolation frame */
03023          af.frametype = AST_FRAME_VOICE;
03024          af.subclass = pvt->voiceformat;
03025          af.samples  = frame.ms * 8;
03026          af.src  = "IAX2 JB interpolation";
03027          af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
03028          af.offset = AST_FRIENDLY_OFFSET;
03029          
03030          /* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
03031           * which we'd need to malloc, and then it would free it.  That seems like a drag */
03032          if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
03033             iax2_queue_frame(callno, &af);
03034             /* iax2_queue_frame() could cause the call to disappear */
03035             pvt = iaxs[callno];
03036          }
03037       }
03038          break;
03039       case JB_DROP:
03040          iax2_frame_free(frame.data);
03041          break;
03042       case JB_NOFRAME:
03043       case JB_EMPTY:
03044          /* do nothing */
03045          break;
03046       default:
03047          /* shouldn't happen */
03048          break;
03049       }
03050    }
03051    if (pvt)
03052       update_jbsched(pvt);
03053    ast_mutex_unlock(&iaxsl[callno]);
03054 }

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

Definition at line 6717 of file chan_iax2.c.

References iax2_registry::expire, and iax2_do_register().

Referenced by iax2_do_register_s().

06718 {
06719    struct iax2_registry *reg = (struct iax2_registry *)data;
06720    reg->expire = -1;
06721    iax2_do_register(reg);
06722 }

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

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

10140 {
10141    struct iax2_peer *peer = (struct iax2_peer *)data;
10142    int callno;
10143 
10144    if (peer->lastms > -1) {
10145       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
10146       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
10147       ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
10148    }
10149    if ((callno = peer->callno) > 0) {
10150       ast_mutex_lock(&iaxsl[callno]);
10151       iax2_destroy(callno);
10152       ast_mutex_unlock(&iaxsl[callno]);
10153    }
10154    peer->callno = 0;
10155    peer->lastms = -1;
10156    /* Try again quickly */
10157    peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
10158    if (peer->pokeexpire == -1)
10159       peer_unref(peer);
10160 }

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

Definition at line 7482 of file chan_iax2.c.

References iax2_poke_peer(), and peer_unref().

Referenced by iax2_poke_peer_s().

07483 {
07484    struct iax2_peer *peer = (struct iax2_peer *)data;
07485    iax2_poke_peer(peer, 0);
07486    peer_unref(peer);
07487 }

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

Definition at line 5134 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, status, and iax2_peer::username.

Referenced by handle_cli_iax2_show_peers(), and manager_iax2_show_peers().

05135 {
05136    regex_t regexbuf;
05137    int havepattern = 0;
05138    int total_peers = 0;
05139    int online_peers = 0;
05140    int offline_peers = 0;
05141    int unmonitored_peers = 0;
05142    struct ao2_iterator i;
05143 
05144 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
05145 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
05146 
05147    struct iax2_peer *peer = NULL;
05148    char name[256];
05149    int registeredonly=0;
05150    char *term = manager ? "\r\n" : "\n";
05151    char idtext[256] = "";
05152    switch (argc) {
05153    case 6:
05154       if (!strcasecmp(argv[3], "registered"))
05155          registeredonly = 1;
05156       else
05157          return RESULT_SHOWUSAGE;
05158       if (!strcasecmp(argv[4], "like")) {
05159          if (regcomp(&regexbuf, argv[5], REG_EXTENDED | REG_NOSUB))
05160             return RESULT_SHOWUSAGE;
05161          havepattern = 1;
05162       } else
05163          return RESULT_SHOWUSAGE;
05164       break;
05165    case 5:
05166       if (!strcasecmp(argv[3], "like")) {
05167          if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
05168             return RESULT_SHOWUSAGE;
05169          havepattern = 1;
05170       } else
05171          return RESULT_SHOWUSAGE;
05172       break;
05173    case 4:
05174       if (!strcasecmp(argv[3], "registered"))
05175          registeredonly = 1;
05176       else
05177          return RESULT_SHOWUSAGE;
05178       break;
05179    case 3:
05180       break;
05181    default:
05182       return RESULT_SHOWUSAGE;
05183    }
05184 
05185 
05186    if (!s)
05187       ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
05188 
05189    i = ao2_iterator_init(peers, 0);
05190    for (peer = ao2_iterator_next(&i); peer; 
05191       peer_unref(peer), peer = ao2_iterator_next(&i)) {
05192       char nm[20];
05193       char status[20];
05194       char srch[2000];
05195       int retstatus;
05196 
05197       if (registeredonly && !peer->addr.sin_addr.s_addr)
05198          continue;
05199       if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0))
05200          continue;
05201 
05202       if (!ast_strlen_zero(peer->username))
05203          snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
05204       else
05205          ast_copy_string(name, peer->name, sizeof(name));
05206       
05207       retstatus = peer_status(peer, status, sizeof(status));
05208       if (retstatus > 0)
05209          online_peers++;
05210       else if (!retstatus)
05211          offline_peers++;
05212       else
05213          unmonitored_peers++;
05214       
05215       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
05216       
05217       snprintf(srch, sizeof(srch), FORMAT, name, 
05218           peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
05219           ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
05220           nm,
05221           ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
05222           peer->encmethods ? "(E)" : "   ", status, term);
05223       
05224       if (s)
05225          astman_append(s, 
05226             "Event: PeerEntry\r\n%s"
05227             "Channeltype: IAX2\r\n"
05228             "ChanObjectType: peer\r\n"
05229             "ObjectName: %s\r\n"
05230             "IPaddress: %s\r\n"
05231             "IPport: %d\r\n"
05232             "Dynamic: %s\r\n"
05233             "Status: %s\r\n\r\n",
05234             idtext,
05235             name,
05236             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-",
05237             ntohs(peer->addr.sin_port),
05238             ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no",
05239             status);
05240       
05241       else
05242          ast_cli(fd, FORMAT, name, 
05243             peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
05244             ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
05245             nm,
05246             ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
05247             peer->encmethods ? "(E)" : "   ", status, term);
05248       total_peers++;
05249    }
05250 
05251    if (!s)
05252       ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
05253 
05254    if (havepattern)
05255       regfree(&regexbuf);
05256 
05257    return RESULT_SUCCESS;
05258 #undef FORMAT
05259 #undef FORMAT2
05260 }

static void __reg_module ( void   )  [static]

Definition at line 12524 of file chan_iax2.c.

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

Definition at line 1119 of file chan_iax2.c.

References ast_copy_string(), ast_debug, find_idle_thread(), IAX_IOSTATE_SCHEDREADY, signal_condition(), and thread.

01120 {
01121    struct iax2_thread *thread = NULL;
01122    static time_t lasterror;
01123    static time_t t;
01124 
01125    thread = find_idle_thread();
01126 
01127    if (thread != NULL) {
01128       thread->schedfunc = func;
01129       thread->scheddata = data;
01130       thread->iostate = IAX_IOSTATE_SCHEDREADY;
01131 #ifdef DEBUG_SCHED_MULTITHREAD
01132       ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc));
01133 #endif
01134       signal_condition(&thread->lock, &thread->cond);
01135       return 0;
01136    }
01137    time(&t);
01138    if (t != lasterror) 
01139       ast_debug(1, "Out of idle IAX2 threads for scheduling!\n");
01140    lasterror = t;
01141 
01142    return -1;
01143 }

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

References f, and iax2_send().

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

05938 {
05939    struct ast_frame f = { 0, };
05940 
05941    f.frametype = type;
05942    f.subclass = command;
05943    f.datalen = datalen;
05944    f.src = __FUNCTION__;
05945    f.data = (void *) data;
05946 
05947    return iax2_send(i, &f, ts, seqno, now, transfer, final);
05948 }

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

Definition at line 1212 of file chan_iax2.c.

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

Referenced by send_lagrq().

01213 {
01214    int callno = (long) data;
01215 
01216    ast_mutex_lock(&iaxsl[callno]);
01217 
01218    if (iaxs[callno]) {
01219       if (iaxs[callno]->peercallno) {
01220          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
01221          iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data);
01222       } else {
01223          /* I am the schedule, so I'm allowed to do this */
01224          iaxs[callno]->lagid = -1;
01225       }
01226    } else {
01227       ast_debug(1, "I was supposed to send a LAGRQ with callno %d, but no such call exists.\n", callno);
01228    }
01229 
01230    ast_mutex_unlock(&iaxsl[callno]);
01231 }

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

Definition at line 1167 of file chan_iax2.c.

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

Referenced by send_ping().

01168 {
01169    int callno = (long) data;
01170 
01171    ast_mutex_lock(&iaxsl[callno]);
01172 
01173    if (iaxs[callno]) {
01174       if (iaxs[callno]->peercallno) {
01175          send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1);
01176          iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data);
01177       } else {
01178          /* I am the schedule, so I'm allowed to do this */
01179          iaxs[callno]->pingid = -1;
01180       }
01181    } else {
01182       ast_debug(1, "I was supposed to send a PING with callno %d, but no such call exists.\n", callno);
01183    }
01184 
01185    ast_mutex_unlock(&iaxsl[callno]);
01186 }

static int __unload_module ( void   )  [static]

Definition at line 12264 of file chan_iax2.c.

References ao2_ref(), ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), ast_context_destroy(), ast_context_find(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, 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(), iax_transfercallno_pvts, iaxactivethreadcount, netsock, outsock, papp, reload_firmware(), sched, sched_context_destroy(), sched_lock, and thread.

12265 {
12266    struct iax2_thread *thread = NULL;
12267    struct ast_context *con;
12268    int x;
12269 
12270    /* Make sure threads do not hold shared resources when they are canceled */
12271    
12272    /* Grab the sched lock resource to keep it away from threads about to die */
12273    /* Cancel the network thread, close the net socket */
12274    if (netthreadid != AST_PTHREADT_NULL) {
12275       AST_LIST_LOCK(&frame_queue);
12276       ast_mutex_lock(&sched_lock);
12277       pthread_cancel(netthreadid);
12278       ast_cond_signal(&sched_cond);
12279       ast_mutex_unlock(&sched_lock);   /* Release the schedule lock resource */
12280       AST_LIST_UNLOCK(&frame_queue);
12281       pthread_join(netthreadid, NULL);
12282    }
12283    if (schedthreadid != AST_PTHREADT_NULL) {
12284       ast_mutex_lock(&sched_lock);
12285       pthread_cancel(schedthreadid);
12286       ast_cond_signal(&sched_cond);
12287       ast_mutex_unlock(&sched_lock);
12288       pthread_join(schedthreadid, NULL);
12289    }
12290 
12291    /* Call for all threads to halt */
12292    AST_LIST_LOCK(&idle_list);
12293    while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list)))
12294       pthread_cancel(thread->threadid);
12295    AST_LIST_UNLOCK(&idle_list);
12296 
12297    AST_LIST_LOCK(&active_list);
12298    while ((thread = AST_LIST_REMOVE_HEAD(&active_list, list)))
12299       pthread_cancel(thread->threadid);
12300    AST_LIST_UNLOCK(&active_list);
12301 
12302    AST_LIST_LOCK(&dynamic_list);
12303    while ((thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list)))
12304       pthread_cancel(thread->threadid);
12305    AST_LIST_UNLOCK(&dynamic_list);
12306    
12307    /* Wait for threads to exit */
12308    while(0 < iaxactivethreadcount)
12309       usleep(10000);
12310    
12311    ast_netsock_release(netsock);
12312    ast_netsock_release(outsock);
12313    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
12314       if (iaxs[x]) {
12315          iax2_destroy(x);
12316       }
12317    }
12318    ast_manager_unregister( "IAXpeers" );
12319    ast_manager_unregister( "IAXpeerlist" );
12320    ast_manager_unregister( "IAXnetstats" );
12321    ast_unregister_application(papp);
12322    ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
12323    ast_unregister_switch(&iax2_switch);
12324    ast_channel_unregister(&iax2_tech);
12325    delete_users();
12326    iax_provision_unload();
12327    sched_context_destroy(sched);
12328    reload_firmware(1);
12329 
12330    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
12331       ast_mutex_destroy(&iaxsl[x]);
12332    }
12333 
12334    ao2_ref(peers, -1);
12335    ao2_ref(users, -1);
12336    ao2_ref(iax_peercallno_pvts, -1);
12337    ao2_ref(iax_transfercallno_pvts, -1);  
12338    con = ast_context_find(regcontext);
12339    if (con)
12340       ast_context_destroy(con, "IAX2");
12341    
12342    return 0;
12343 }

static void __unreg_module ( void   )  [static]

Definition at line 12524 of file chan_iax2.c.

static int acf_channel_read ( struct ast_channel chan,
const char *  funcname,
char *  preparse,
char *  buf,
size_t  buflen 
) [static]

Definition at line 12051 of file chan_iax2.c.

References ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), chan, iax2_tech, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.

12052 {
12053    struct chan_iax2_pvt *pvt;
12054    unsigned int callno;
12055    int res = 0;
12056 
12057    if (!chan || chan->tech != &iax2_tech) {
12058       ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n");
12059       return -1;
12060    }
12061 
12062    callno = PTR_TO_CALLNO(chan->tech_pvt);
12063    ast_mutex_lock(&iaxsl[callno]);
12064    if (!(pvt = iaxs[callno])) {
12065       ast_mutex_unlock(&iaxsl[callno]);
12066       return -1;
12067    }
12068 
12069    if (!strcasecmp(args, "osptoken"))
12070       ast_copy_string(buf, pvt->osptoken, buflen);
12071    else
12072       res = -1;
12073 
12074    ast_mutex_unlock(&iaxsl[callno]);
12075 
12076    return res;
12077 }

static int acf_channel_write ( struct ast_channel chan,
const char *  function,
char *  data,
const char *  value 
) [static]

Definition at line 12023 of file chan_iax2.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_set, chan, iax2_tech, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.

12024 {
12025    struct chan_iax2_pvt *pvt;
12026    unsigned int callno;
12027    int res = 0;
12028 
12029    if (!chan || chan->tech != &iax2_tech) {
12030       ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n");
12031       return -1;
12032    }
12033 
12034    callno = PTR_TO_CALLNO(chan->tech_pvt);
12035    ast_mutex_lock(&iaxsl[callno]);
12036    if (!(pvt = iaxs[callno])) {
12037       ast_mutex_unlock(&iaxsl[callno]);
12038       return -1;
12039    }
12040 
12041    if (!strcasecmp(args, "osptoken"))
12042       ast_string_field_set(pvt, osptoken, value);
12043    else
12044       res = -1;
12045 
12046    ast_mutex_unlock(&iaxsl[callno]);
12047 
12048    return res;
12049 }

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

Definition at line 8165 of file chan_iax2.c.

References ast_channel_datastore_find(), ast_copy_string(), AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, chan, ast_datastore::data, ast_var_t::entries, iax2_variable_datastore_info, and var.

08166 {
08167    struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL);
08168    AST_LIST_HEAD(, ast_var_t) *varlist;
08169    struct ast_var_t *var;
08170 
08171    if (!variablestore) {
08172       *buf = '\0';
08173       return 0;
08174    }
08175    varlist = variablestore->data;
08176 
08177    AST_LIST_LOCK(varlist);
08178    AST_LIST_TRAVERSE(varlist, var, entries) {
08179       if (strcmp(var->name, data) == 0) {
08180          ast_copy_string(buf, var->value, len);
08181          break;
08182       }
08183    }
08184    AST_LIST_UNLOCK(varlist);
08185    return 0;
08186 }

static int acf_iaxvar_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
) [static]

Definition at line 8188 of file chan_iax2.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_find(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_delete(), chan, ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_var_t::entries, iax2_variable_datastore_info, ast_datastore::inheritance, LOG_ERROR, and var.

08189 {
08190    struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL);
08191    AST_LIST_HEAD(, ast_var_t) *varlist;
08192    struct ast_var_t *var;
08193 
08194    if (!variablestore) {
08195       variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL);
08196       if (!variablestore) {
08197          ast_log(LOG_ERROR, "Memory allocation error\n");
08198          return -1;
08199       }
08200       varlist = ast_calloc(1, sizeof(*varlist));
08201       if (!varlist) {
08202          ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data);
08203          return -1;
08204       }
08205 
08206       AST_LIST_HEAD_INIT(varlist);
08207       variablestore->data = varlist;
08208       variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
08209       ast_channel_datastore_add(chan, variablestore);
08210    } else
08211       varlist = variablestore->data;
08212 
08213    AST_LIST_LOCK(varlist);
08214    AST_LIST_TRAVERSE_SAFE_BEGIN(varlist, var, entries) {
08215       if (strcmp(var->name, data) == 0) {
08216          AST_LIST_REMOVE_CURRENT(entries);
08217          ast_var_delete(var);
08218          break;
08219       }
08220    }
08221    AST_LIST_TRAVERSE_SAFE_END;
08222    var = ast_var_assign(data, value);
08223    if (var)
08224       AST_LIST_INSERT_TAIL(varlist, var, entries);
08225    else
08226       ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data);
08227    AST_LIST_UNLOCK(varlist);
08228    return 0;
08229 }

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

Definition at line 5989 of file chan_iax2.c.

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

Referenced by check_access().

05990 {
05991    while(con) {
05992       if (!strcmp(con->context, context) || !strcmp(con->context, "*"))
05993          return -1;
05994       con = con->next;
05995    }
05996    return 0;
05997 }

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

Definition at line 5645 of file chan_iax2.c.

References ACN_FORMAT1, ACN_FORMAT2, ARRAY_LEN, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, iax_frame_subclass2str(), IAX_USEJITTERBUF, jb_getinfo(), jb_info::jitter, jb_info::losspct, MARK_IAX_SUBCLASS_TX, jb_info::min, and s.

Referenced by handle_cli_iax2_show_netstats(), and manager_iax2_show_netstats().

05646 {
05647    int x;
05648    int numchans = 0;
05649    char first_message[10] = { 0, };
05650    char last_message[10] = { 0, };
05651 #define ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n"
05652 #define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n"
05653    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
05654       ast_mutex_lock(&iaxsl[x]);
05655       if (iaxs[x]) {
05656          int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
05657          jb_info jbinfo;
05658          iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message));
05659          iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message));
05660 
05661          if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
05662             jb_getinfo(iaxs[x]->jb, &jbinfo);
05663             localjitter = jbinfo.jitter;
05664             localdelay = jbinfo.current - jbinfo.min;
05665             locallost = jbinfo.frames_lost;
05666             locallosspct = jbinfo.losspct/1000;
05667             localdropped = jbinfo.frames_dropped;
05668             localooo = jbinfo.frames_ooo;
05669          } else {
05670             localjitter = -1;
05671             localdelay = 0;
05672             locallost = -1;
05673             locallosspct = -1;
05674             localdropped = 0;
05675             localooo = -1;
05676          }
05677          if (s)
05678             astman_append(s, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2,
05679                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
05680                iaxs[x]->pingtime,
05681                localjitter,
05682                localdelay,
05683                locallost,
05684                locallosspct,
05685                localdropped,
05686                localooo,
05687                iaxs[x]->frames_received/1000,
05688                iaxs[x]->remote_rr.jitter,
05689                iaxs[x]->remote_rr.delay,
05690                iaxs[x]->remote_rr.losscnt,
05691                iaxs[x]->remote_rr.losspct,
05692                iaxs[x]->remote_rr.dropped,
05693                iaxs[x]->remote_rr.ooo,
05694                iaxs[x]->remote_rr.packets/1000,
05695                (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
05696                first_message,
05697                (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
05698                last_message);
05699          else
05700             ast_cli(fd, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2,
05701                iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
05702                iaxs[x]->pingtime,
05703                localjitter,
05704                localdelay,
05705                locallost,
05706                locallosspct,
05707                localdropped,
05708                localooo,
05709                iaxs[x]->frames_received/1000,
05710                iaxs[x]->remote_rr.jitter,
05711                iaxs[x]->remote_rr.delay,
05712                iaxs[x]->remote_rr.losscnt,
05713                iaxs[x]->remote_rr.losspct,
05714                iaxs[x]->remote_rr.dropped,
05715                iaxs[x]->remote_rr.ooo,
05716                iaxs[x]->remote_rr.packets/1000,
05717                (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
05718                first_message,
05719                (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
05720                last_message);
05721          numchans++;
05722       }
05723       ast_mutex_unlock(&iaxsl[x]);
05724    }
05725 
05726    return numchans;
05727 }

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 4237 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_calloc, ast_channel_alloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_free(), ast_channel_free(), ast_copy_string(), ast_debug, ast_free, ast_hangup(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, 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(), ast_var_assign(), 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, ast_datastore::data, DATASTORE_INHERIT_FOREVER, chan_iax2_pvt::dnid, ast_var_t::entries, ast_channel::exten, chan_iax2_pvt::exten, chan_iax2_pvt::host, iax2_ami_channelupdate(), iax2_tech, iax2_variable_datastore_info, chan_iax2_pvt::iaxvars, ast_datastore::inheritance, chan_iax2_pvt::language, LOG_ERROR, 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, var, chan_iax2_pvt::vars, and ast_channel::writeformat.

Referenced by iax2_request(), and socket_process().

04238 {
04239    struct ast_channel *tmp;
04240    struct chan_iax2_pvt *i;
04241    struct ast_variable *v = NULL;
04242 
04243    if (!(i = iaxs[callno])) {
04244       ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
04245       return NULL;
04246    }
04247 
04248    /* Don't hold call lock */
04249    ast_mutex_unlock(&iaxsl[callno]);
04250    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);
04251    ast_mutex_lock(&iaxsl[callno]);
04252    if (i != iaxs[callno]) {
04253       if (tmp) {
04254          /* unlock and relock iaxsl[callno] to preserve locking order */
04255          ast_mutex_unlock(&iaxsl[callno]);
04256          ast_channel_free(tmp);
04257          ast_mutex_lock(&iaxsl[callno]);
04258       }
04259       return NULL;
04260    }
04261    iax2_ami_channelupdate(i);
04262    if (!tmp)
04263       return NULL;
04264    tmp->tech = &iax2_tech;
04265    /* We can support any format by default, until we get restricted */
04266    tmp->nativeformats = capability;
04267    tmp->readformat = tmp->rawreadformat = ast_best_codec(capability);
04268    tmp->writeformat = tmp->rawwriteformat = ast_best_codec(capability);
04269    tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
04270 
04271    /* Don't use ast_set_callerid() here because it will
04272     * generate a NewCallerID event before the NewChannel event */
04273    if (!ast_strlen_zero(i->ani))
04274       tmp->cid.cid_ani = ast_strdup(i->ani);
04275    else
04276       tmp->cid.cid_ani = ast_strdup(i->cid_num);
04277    tmp->cid.cid_dnid = ast_strdup(i->dnid);
04278    tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
04279    tmp->cid.cid_pres = i->calling_pres;
04280    tmp->cid.cid_ton = i->calling_ton;
04281    tmp->cid.cid_tns = i->calling_tns;
04282    if (!ast_strlen_zero(i->language))
04283       ast_string_field_set(tmp, language, i->language);
04284    if (!ast_strlen_zero(i->accountcode))
04285       ast_string_field_set(tmp, accountcode, i->accountcode);
04286    if (i->amaflags)
04287       tmp->amaflags = i->amaflags;
04288    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
04289    ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
04290    if (i->adsi)
04291       tmp->adsicpe = i->peeradsicpe;
04292    else
04293       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
04294    i->owner = tmp;
04295    i->capability = capability;
04296 
04297    /* Set inherited variables */
04298    if (i->vars) {
04299       for (v = i->vars ; v ; v = v->next)
04300          pbx_builtin_setvar_helper(tmp, v->name, v->value);
04301    }
04302    if (i->iaxvars) {
04303       struct ast_datastore *variablestore;
04304       struct ast_variable *var, *prev = NULL;
04305       AST_LIST_HEAD(, ast_var_t) *varlist;
04306       ast_debug(1, "Loading up the channel with IAXVARs\n");
04307       varlist = ast_calloc(1, sizeof(*varlist));
04308       variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL);
04309       if (variablestore && varlist) {
04310          variablestore->data = varlist;
04311          variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
04312          AST_LIST_HEAD_INIT(varlist);
04313          for (var = i->iaxvars; var; var = var->next) {
04314             struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
04315             if (prev)
04316                ast_free(prev);
04317             prev = var;
04318             if (!newvar) {
04319                /* Don't abort list traversal, as this would leave i->iaxvars in an inconsistent state. */
04320                ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
04321             } else {
04322                AST_LIST_INSERT_TAIL(varlist, newvar, entries);
04323             }
04324          }
04325          if (prev)
04326             ast_free(prev);
04327          i->iaxvars = NULL;
04328          ast_channel_datastore_add(i->owner, variablestore);
04329       } else {
04330          if (variablestore) {
04331             ast_channel_datastore_free(variablestore);
04332          }
04333          if (varlist) {
04334             ast_free(varlist);
04335          }
04336       }
04337    }
04338 
04339    if (state != AST_STATE_DOWN) {
04340       if (ast_pbx_start(tmp)) {
04341          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
04342          ast_hangup(tmp);
04343          i->owner = NULL;
04344          return NULL;
04345       }
04346    }
04347 
04348    ast_module_ref(ast_module_info->self);
04349    return tmp;
04350 }

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

Definition at line 2499 of file chan_iax2.c.

References __attempt_transmit(), and schedule_action.

Referenced by __attempt_transmit(), and network_thread().

02500 {
02501 #ifdef SCHED_MULTITHREADED
02502    if (schedule_action(__attempt_transmit, data))
02503 #endif      
02504       __attempt_transmit(data);
02505    return 0;
02506 }

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

Definition at line 7404 of file chan_iax2.c.

References auth_reject(), iax2_sched_replace(), and sched.

Referenced by socket_process().

07405 {
07406    /* Schedule sending the authentication failure in one second, to prevent
07407       guessing */
07408    if (iaxs[callno]) {
07409       iaxs[callno]->authfail = failcode;
07410       if (delayreject) {
07411          iaxs[callno]->authid = iax2_sched_replace(iaxs[callno]->authid, 
07412             sched, 1000, auth_reject, (void *)(long)callno);
07413       } else
07414          auth_reject((void *)(long)callno);
07415    }
07416    return 0;
07417 }

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

Definition at line 7390 of file chan_iax2.c.

References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), and schedule_action.

Referenced by auth_fail().

07391 {
07392    int callno = (int)(long)(data);
07393    ast_mutex_lock(&iaxsl[callno]);
07394    if (iaxs[callno])
07395       iaxs[callno]->authid = -1;
07396    ast_mutex_unlock(&iaxsl[callno]);
07397 #ifdef SCHED_MULTITHREADED
07398    if (schedule_action(__auth_reject, data))
07399 #endif      
07400       __auth_reject(data);
07401    return 0;
07402 }

static int authenticate ( const char *  challenge,
const char *  secret,
const char *  keyn,
int  authmethods,
struct iax_ie_data ied,
struct sockaddr_in *  sin,
struct chan_iax2_pvt pvt 
) [static]

Definition at line 6549 of file chan_iax2.c.

References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_encryption_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().

06550 {
06551    int res = -1;
06552    int x;
06553    if (!ast_strlen_zero(keyn)) {
06554       if (!(authmethods & IAX_AUTH_RSA)) {
06555          if (ast_strlen_zero(secret)) 
06556             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));
06557       } else if (ast_strlen_zero(challenge)) {
06558          ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr));
06559       } else {
06560          char sig[256];
06561          struct ast_key *key;
06562          key = ast_key_get(keyn, AST_KEY_PRIVATE);
06563          if (!key) {
06564             ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
06565          } else {
06566             if (ast_sign(key, (char*)challenge, sig)) {
06567                ast_log(LOG_NOTICE, "Unable to sign challenge with key\n");
06568                res = -1;
06569             } else {
06570                iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig);
06571                res = 0;
06572             }
06573          }
06574       }
06575    } 
06576    /* Fall back */
06577    if (res && !ast_strlen_zero(secret)) {
06578       if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) {
06579          struct MD5Context md5;
06580          unsigned char digest[16];
06581          char digres[128];
06582          MD5Init(&md5);
06583          MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
06584          MD5Update(&md5, (unsigned char *)secret, strlen(secret));
06585          MD5Final(digest, &md5);
06586          /* If they support md5, authenticate with it.  */
06587          for (x=0;x<16;x++)
06588             sprintf(digres + (x << 1),  "%2.2x", digest[x]); /* safe */
06589          if (pvt) {
06590             build_encryption_keys(digest, pvt);
06591          }
06592          iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres);
06593          res = 0;
06594       } else if (authmethods & IAX_AUTH_PLAINTEXT) {
06595          iax_ie_append_str(ied, IAX_IE_PASSWORD, secret);
06596          res = 0;
06597       } else
06598          ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods);
06599    }
06600    return res;
06601 }

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

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_free(), AST_FRAME_IAX, ast_free, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), authenticate(), iax2_peer::authmethods, chan_iax2_pvt::callno, ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_var_t::entries, iax2_variable_datastore_info, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, ies, ast_datastore::inheritance, LOG_ERROR, iax2_peer::mask, merge_encryption(), iax2_peer::name, iax2_peer::outkey, peer_unref(), realtime_peer(), iax2_peer::secret, send_command(), iax2_peer::username, and var.

Referenced by socket_process().

06608 {
06609    struct iax2_peer *peer = NULL;
06610    /* Start pessimistic */
06611    int res = -1;
06612    int authmethods = 0;
06613    struct iax_ie_data ied;
06614    uint16_t callno = p->callno;
06615 
06616    memset(&ied, 0, sizeof(ied));
06617    
06618    if (ies->username)
06619       ast_string_field_set(p, username, ies->username);
06620    if (ies->challenge)
06621       ast_string_field_set(p, challenge, ies->challenge);
06622    if (ies->authmethods)
06623       authmethods = ies->authmethods;
06624    if (authmethods & IAX_AUTH_MD5)
06625       merge_encryption(p, ies->encmethods);
06626    else
06627       p->encmethods = 0;
06628 
06629    /* Check for override RSA authentication first */
06630    if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) {
06631       /* Normal password authentication */
06632       res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, p);
06633    } else {
06634       struct ao2_iterator i = ao2_iterator_init(peers, 0);
06635       while ((peer = ao2_iterator_next(&i))) {
06636          if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
06637              /* No peer specified at our end, or this is the peer */
06638              && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
06639              /* No username specified in peer rule, or this is the right username */
06640              && (!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)))
06641              /* No specified host, or this is our host */
06642             ) {
06643             res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, p);
06644             if (!res) {
06645                peer_unref(peer);
06646                break;
06647             }
06648          }
06649          peer_unref(peer);
06650       }
06651       if (!peer) {
06652          /* We checked our list and didn't find one.  It's unlikely, but possible, 
06653             that we're trying to authenticate *to* a realtime peer */
06654          const char *peer_name = ast_strdupa(p->peer);
06655          ast_mutex_unlock(&iaxsl[callno]);
06656          if ((peer = realtime_peer(peer_name, NULL))) {
06657             ast_mutex_lock(&iaxsl[callno]);
06658             if (!(p = iaxs[callno])) {
06659                peer_unref(peer);
06660                return -1;
06661             }
06662             res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, p);
06663             peer_unref(peer);
06664          }
06665          if (!peer) {
06666             ast_mutex_lock(&iaxsl[callno]);
06667             if (!(p = iaxs[callno]))
06668                return -1;
06669          }
06670       }
06671    }
06672    if (ies->encmethods)
06673       ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED);
06674    if (!res) {
06675       struct ast_datastore *variablestore;
06676       struct ast_variable *var, *prev = NULL;
06677       AST_LIST_HEAD(, ast_var_t) *varlist;
06678       varlist = ast_calloc(1, sizeof(*varlist));
06679       variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL);
06680       if (variablestore && varlist && p->owner) {
06681          variablestore->data = varlist;
06682          variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
06683          AST_LIST_HEAD_INIT(varlist);
06684          for (var = ies->vars; var; var = var->next) {
06685             struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
06686             if (prev)
06687                ast_free(prev);
06688             prev = var;
06689             if (!newvar) {
06690                /* Don't abort list traversal, as this would leave ies->vars in an inconsistent state. */
06691                ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
06692             } else {
06693                AST_LIST_INSERT_TAIL(varlist, newvar, entries);
06694             }
06695          }
06696          if (prev)
06697             ast_free(prev);
06698          ies->vars = NULL;
06699          ast_channel_datastore_add(p->owner, variablestore);
06700       } else {
06701          if (p->owner)
06702             ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
06703          if (variablestore)
06704             ast_channel_datastore_free(variablestore);
06705          if (varlist)
06706             ast_free(varlist);
06707       }
06708    }
06709 
06710    if (!res)
06711       res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1);
06712    return res;
06713 }

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 6260 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, 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, OBJ_POINTER, send_command(), send_command_final(), user, user_unref(), and chan_iax2_pvt::username.

Referenced by socket_process().

06261 {
06262    struct iax_ie_data ied;
06263    int res = -1, authreq_restrict = 0;
06264    char challenge[10];
06265    struct chan_iax2_pvt *p = iaxs[call_num];
06266 
06267    memset(&ied, 0, sizeof(ied));
06268 
06269    /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
06270    if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
06271       struct iax2_user *user, tmp_user = {
06272          .name = p->username, 
06273       };
06274 
06275       user = ao2_find(users, &tmp_user, OBJ_POINTER);
06276       if (user) {
06277          if (user->curauthreq == user->maxauthreq)
06278             authreq_restrict = 1;
06279          else
06280             user->curauthreq++;
06281          user = user_unref(user);
06282       }
06283    }
06284 
06285    /* If the AUTHREQ limit test failed, send back an error */
06286    if (authreq_restrict) {
06287       iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
06288       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
06289       send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
06290       return 0;
06291    }
06292 
06293    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
06294    if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
06295       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
06296       ast_string_field_set(p, challenge, challenge);
06297       /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */
06298       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
06299    }
06300    if (p->encmethods)
06301       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
06302 
06303    iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
06304 
06305    res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
06306 
06307    if (p->encmethods)
06308       ast_set_flag(p, IAX_ENCRYPTED);
06309 
06310    return res;
06311 }

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

Definition at line 6313 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::authrej, chan_iax2_pvt::challenge, 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(), OBJ_POINTER, chan_iax2_pvt::secret, secret, chan_iax2_pvt::state, strsep(), user, user_unref(), and chan_iax2_pvt::username.

Referenced by socket_process().

06314 {
06315    char requeststr[256];
06316    char md5secret[256] = "";
06317    char secret[256] = "";
06318    char rsasecret[256] = "";
06319    int res = -1; 
06320    int x;
06321    struct iax2_user *user, tmp_user = {
06322       .name = p->username, 
06323    };
06324 
06325    if (p->authrej) {
06326       return res;
06327    }
06328    user = ao2_find(users, &tmp_user, OBJ_POINTER);
06329    if (user) {
06330       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
06331          ast_atomic_fetchadd_int(&user->curauthreq, -1);
06332          ast_clear_flag(p, IAX_MAXAUTHREQ);
06333       }
06334       ast_string_field_set(p, host, user->name);
06335       user = user_unref(user);
06336    }
06337 
06338    if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
06339       return res;
06340    if (ies->password)
06341       ast_copy_string(secret, ies->password, sizeof(secret));
06342    if (ies->md5_result)
06343       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
06344    if (ies->rsa_result)
06345       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
06346    if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) {
06347       struct ast_key *key;
06348       char *keyn;
06349       char tmpkey[256];
06350       char *stringp=NULL;
06351       ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey));
06352       stringp=tmpkey;
06353       keyn = strsep(&stringp, ":");
06354       while(keyn) {
06355          key = ast_key_get(keyn, AST_KEY_PUBLIC);
06356          if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
06357             res = 0;
06358             break;
06359          } else if (!key)
06360             ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
06361          keyn = strsep(&stringp, ":");
06362       }
06363    } else if (p->authmethods & IAX_AUTH_MD5) {
06364       struct MD5Context md5;
06365       unsigned char digest[16];
06366       char *tmppw, *stringp;
06367       
06368       tmppw = ast_strdupa(p->secret);
06369       stringp = tmppw;
06370       while((tmppw = strsep(&stringp, ";"))) {
06371          MD5Init(&md5);
06372          MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge));
06373          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
06374          MD5Final(digest, &md5);
06375          /* If they support md5, authenticate with it.  */
06376          for (x=0;x<16;x++)
06377             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
06378          if (!strcasecmp(requeststr, md5secret)) {
06379             res = 0;
06380             break;
06381          }
06382       }
06383    } else if (p->authmethods & IAX_AUTH_PLAINTEXT) {
06384       if (!strcmp(secret, p->secret))
06385          res = 0;
06386    }
06387    return res;
06388 }

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

Definition at line 3540 of file chan_iax2.c.

References __auto_congest(), and schedule_action.

Referenced by iax2_call(), and sip_call().

03541 {
03542 #ifdef SCHED_MULTITHREADED
03543    if (schedule_action(__auto_congest, data))
03544 #endif      
03545       __auto_congest(data);
03546    return 0;
03547 }

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

Definition at line 7434 of file chan_iax2.c.

References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), and schedule_action.

Referenced by iax2_dprequest(), and iax2_provision().

07435 {
07436    int callno = (int)(long)(data);
07437    ast_mutex_lock(&iaxsl[callno]);
07438    if (iaxs[callno]) {
07439       iaxs[callno]->autoid = -1;
07440    }
07441    ast_mutex_unlock(&iaxsl[callno]);
07442 #ifdef SCHED_MULTITHREADED
07443    if (schedule_action(__auto_hangup, data))
07444 #endif      
07445       __auto_hangup(data);
07446    return 0;
07447 }

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

Definition at line 10455 of file chan_iax2.c.

References ast_calloc, and ast_copy_string().

Referenced by build_user().

10456 {
10457    struct iax2_context *con;
10458 
10459    if ((con = ast_calloc(1, sizeof(*con))))
10460       ast_copy_string(con->context, context, sizeof(con->context));
10461    
10462    return con;
10463 }

static void build_ecx_key ( const unsigned char *  digest,
struct chan_iax2_pvt pvt 
) [static]

Definition at line 4692 of file chan_iax2.c.

References ast_aes_decrypt_key, ast_aes_encrypt_key, build_rand_pad(), chan_iax2_pvt::ecx, chan_iax2_pvt::mydcx, and chan_iax2_pvt::semirand.

Referenced by build_encryption_keys().

04693 {
04694    /* it is required to hold the corresponding decrypt key to our encrypt key
04695     * in the pvt struct because queued frames occasionally need to be decrypted and
04696     * re-encrypted when updated for a retransmission */
04697    build_rand_pad(pvt->semirand, sizeof(pvt->semirand));
04698    ast_aes_encrypt_key(digest, &pvt->ecx);
04699    ast_aes_decrypt_key(digest, &pvt->mydcx);
04700 }

static void build_encryption_keys ( const unsigned char *  digest,
struct chan_iax2_pvt pvt 
) [static]

Definition at line 4686 of file chan_iax2.c.

References ast_aes_decrypt_key, build_ecx_key(), and chan_iax2_pvt::dcx.

Referenced by authenticate(), and decrypt_frame().

04687 {
04688    build_ecx_key(digest, pvt);
04689    ast_aes_decrypt_key(digest, &pvt->dcx);
04690 }

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 10603 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_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), 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_strdupa, 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, inet_aton(), iax2_peer::inkeys, ast_variable::lineno, LOG_WARNING, mailbox, mwi_event_cb(), ast_variable::name, iax2_peer::name, ast_variable::next, OBJ_POINTER, iax2_peer::outkey, peer_destructor(), peer_set_srcaddr(), peer_unref(), iax2_peer::peercontext, prefs, regexten, S_OR, sched, secret, strsep(), unlink_peer(), ast_variable::value, and zonetag.

10604 {
10605    struct iax2_peer *peer = NULL;
10606    struct ast_ha *oldha = NULL;
10607    int maskfound = 0;
10608    int found = 0;
10609    int firstpass = 1;
10610    struct iax2_peer tmp_peer = {
10611       .name = name,
10612    };
10613 
10614    if (!temponly) {
10615       peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
10616       if (peer && !ast_test_flag(peer, IAX_DELME))
10617          firstpass = 0;
10618    }
10619 
10620    if (peer) {
10621       found++;
10622       if (firstpass) {
10623          oldha = peer->ha;
10624          peer->ha = NULL;
10625       }
10626       unlink_peer(peer);
10627    } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
10628       peer->expire = -1;
10629       peer->pokeexpire = -1;
10630       peer->sockfd = defaultsockfd;
10631       if (ast_string_field_init(peer, 32))
10632          peer = peer_unref(peer);
10633    }
10634 
10635    if (peer) {
10636       if (firstpass) {
10637          ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
10638          peer->encmethods = iax2_encryption;
10639          peer->adsi = adsi;
10640          ast_string_field_set(peer,secret,"");
10641          if (!found) {
10642             ast_string_field_set(peer, name, name);
10643             peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
10644             peer->expiry = min_reg_expire;
10645          }
10646          peer->prefs = prefs;
10647          peer->capability = iax2_capability;
10648          peer->smoothing = 0;
10649          peer->pokefreqok = DEFAULT_FREQ_OK;
10650          peer->pokefreqnotok = DEFAULT_FREQ_NOTOK;
10651          ast_string_field_set(peer,context,"");
10652          ast_string_field_set(peer,peercontext,"");
10653          ast_clear_flag(peer, IAX_HASCALLERID);
10654          ast_string_field_set(peer, cid_name, "");
10655          ast_string_field_set(peer, cid_num, "");
10656          ast_string_field_set(peer, mohinterpret, mohinterpret);
10657          ast_string_field_set(peer, mohsuggest, mohsuggest);
10658       }
10659 
10660       if (!v) {
10661          v = alt;
10662          alt = NULL;
10663       }
10664       while(v) {
10665          if (!strcasecmp(v->name, "secret")) {
10666             ast_string_field_set(peer, secret, v->value);
10667          } else if (!strcasecmp(v->name, "mailbox")) {
10668             ast_string_field_set(peer, mailbox, v->value);
10669          } else if (!strcasecmp(v->name, "hasvoicemail")) {
10670             if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
10671                ast_string_field_set(peer, mailbox, name);
10672             }
10673          } else if (!strcasecmp(v->name, "mohinterpret")) {
10674             ast_string_field_set(peer, mohinterpret, v->value);
10675          } else if (!strcasecmp(v->name, "mohsuggest")) {
10676             ast_string_field_set(peer, mohsuggest, v->value);
10677          } else if (!strcasecmp(v->name, "dbsecret")) {
10678             ast_string_field_set(peer, dbsecret, v->value);
10679          } else if (!strcasecmp(v->name, "trunk")) {
10680             ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK);   
10681             if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) {
10682                ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without DAHDI timing\n", peer->name);
10683                ast_clear_flag(peer, IAX_TRUNK);
10684             }
10685          } else if (!strcasecmp(v->name, "auth")) {
10686             peer->authmethods = get_auth_methods(v->value);
10687          } else if (!strcasecmp(v->name, "encryption")) {
10688             peer->encmethods = get_encrypt_methods(v->value);
10689          } else if (!strcasecmp(v->name, "transfer")) {
10690             if (!strcasecmp(v->value, "mediaonly")) {
10691                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
10692             } else if (ast_true(v->value)) {
10693                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
10694             } else 
10695                ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
10696          } else if (!strcasecmp(v->name, "jitterbuffer")) {
10697             ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF);  
10698          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
10699             ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF);   
10700          } else if (!strcasecmp(v->name, "host")) {
10701             if (!strcasecmp(v->value, "dynamic")) {
10702                /* They'll register with us */
10703                ast_set_flag(peer, IAX_DYNAMIC); 
10704                if (!found) {
10705                   /* Initialize stuff iff we're not found, otherwise
10706                      we keep going with what we had */
10707                   memset(&peer->addr.sin_addr, 0, 4);
10708                   if (peer->addr.sin_port) {
10709                      /* If we've already got a port, make it the default rather than absolute */
10710                      peer->defaddr.sin_port = peer->addr.sin_port;
10711                      peer->addr.sin_port = 0;
10712                   }
10713                }
10714             } else {
10715                /* Non-dynamic.  Make sure we become that way if we're not */
10716                AST_SCHED_DEL(sched, peer->expire);
10717                ast_clear_flag(peer, IAX_DYNAMIC);
10718                if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr))
10719                   return peer_unref(peer);
10720                if (!peer->addr.sin_port)
10721                   peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO);
10722             }
10723             if (!maskfound)
10724                inet_aton("255.255.255.255", &peer->mask);
10725          } else if (!strcasecmp(v->name, "defaultip")) {
10726             if (ast_get_ip(&peer->defaddr, v->value))
10727                return peer_unref(peer);
10728          } else if (!strcasecmp(v->name, "sourceaddress")) {
10729             peer_set_srcaddr(peer, v->value);
10730          } else if (!strcasecmp(v->name, "permit") ||
10731                   !strcasecmp(v->name, "deny")) {
10732             peer->ha = ast_append_ha(v->name, v->value, peer->ha, NULL);
10733          } else if (!strcasecmp(v->name, "mask")) {
10734             maskfound++;
10735             inet_aton(v->value, &peer->mask);
10736          } else if (!strcasecmp(v->name, "context")) {
10737             ast_string_field_set(peer, context, v->value);
10738          } else if (!strcasecmp(v->name, "regexten")) {
10739             ast_string_field_set(peer, regexten, v->value);
10740          } else if (!strcasecmp(v->name, "peercontext")) {
10741             ast_string_field_set(peer, peercontext, v->value);
10742          } else if (!strcasecmp(v->name, "port")) {
10743             if (ast_test_flag(peer, IAX_DYNAMIC))
10744                peer->defaddr.sin_port = htons(atoi(v->value));
10745             else
10746                peer->addr.sin_port = htons(atoi(v->value));
10747          } else if (!strcasecmp(v->name, "username")) {
10748             ast_string_field_set(peer, username, v->value);
10749          } else if (!strcasecmp(v->name, "allow")) {
10750             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
10751          } else if (!strcasecmp(v->name, "disallow")) {
10752             ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
10753          } else if (!strcasecmp(v->name, "callerid")) {
10754             if (!ast_strlen_zero(v->value)) {
10755                char name2[80];
10756                char num2[80];
10757                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
10758                ast_string_field_set(peer, cid_name, name2);
10759                ast_string_field_set(peer, cid_num, num2);
10760             } else {
10761                ast_string_field_set(peer, cid_name, "");
10762                ast_string_field_set(peer, cid_num, "");
10763             }
10764             ast_set_flag(peer, IAX_HASCALLERID);
10765          } else if (!strcasecmp(v->name, "fullname")) {
10766             ast_string_field_set(peer, cid_name, S_OR(v->value, ""));
10767             ast_set_flag(peer, IAX_HASCALLERID);
10768          } else if (!strcasecmp(v->name, "cid_number")) {
10769             ast_string_field_set(peer, cid_num, S_OR(v->value, ""));
10770             ast_set_flag(peer, IAX_HASCALLERID);
10771          } else if (!strcasecmp(v->name, "sendani")) {
10772             ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 
10773          } else if (!strcasecmp(v->name, "inkeys")) {
10774             ast_string_field_set(peer, inkeys, v->value);
10775          } else if (!strcasecmp(v->name, "outkey")) {
10776             ast_string_field_set(peer, outkey, v->value);
10777          } else if (!strcasecmp(v->name, "qualify")) {
10778             if (!strcasecmp(v->value, "no")) {
10779                peer->maxms = 0;
10780             } else if (!strcasecmp(v->value, "yes")) {
10781                peer->maxms = DEFAULT_MAXMS;
10782             } else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
10783                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);
10784                peer->maxms = 0;
10785             }
10786          } else if (!strcasecmp(v->name, "qualifysmoothing")) {
10787             peer->smoothing = ast_true(v->value);
10788          } else if (!strcasecmp(v->name, "qualifyfreqok")) {
10789             if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) {
10790                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);
10791             }
10792          } else if (!strcasecmp(v->name, "qualifyfreqnotok")) {
10793             if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) {
10794                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);
10795             } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok);
10796          } else if (!strcasecmp(v->name, "timezone")) {
10797             ast_string_field_set(peer, zonetag, v->value);
10798          } else if (!strcasecmp(v->name, "adsi")) {
10799             peer->adsi = ast_true(v->value);
10800          }/* else if (strcasecmp(v->name,"type")) */
10801          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
10802          v = v->next;
10803          if (!v) {
10804             v = alt;
10805             alt = NULL;
10806          }
10807       }
10808       if (!peer->authmethods)
10809          peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
10810       ast_clear_flag(peer, IAX_DELME); 
10811       /* Make sure these are IPv4 addresses */
10812       peer->addr.sin_family = AF_INET;
10813    }
10814 
10815    if (oldha)
10816       ast_free_ha(oldha);
10817 
10818    if (!ast_strlen_zero(peer->mailbox)) {
10819       char *mailbox, *context;
10820       context = mailbox = ast_strdupa(peer->mailbox);
10821       strsep(&context, "@");
10822       if (ast_strlen_zero(context))
10823          context = "default";
10824       peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10825          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10826          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10827          AST_EVENT_IE_END);
10828    }
10829 
10830    return peer;
10831 }

static void build_rand_pad ( unsigned char *  buf,
ssize_t  len 
) [static]

Definition at line 4676 of file chan_iax2.c.

References ast_random().

Referenced by build_ecx_key(), and update_packet().

04677 {
04678    long tmp;
04679    for (tmp = ast_random(); len > 0; tmp = ast_random()) {
04680       memcpy(buf, (unsigned char *) &tmp, (len > sizeof(tmp)) ? sizeof(tmp) : len);
04681       buf += sizeof(tmp);
04682       len -= sizeof(tmp);
04683    }
04684 }

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

References 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(), build_context(), cid_name, cid_num, cleanup(), iax2_user::dbsecret, format, free_context(), get_auth_methods(), get_encrypt_methods(), globalflags, 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_WARNING, ast_variable::name, iax2_user::name, ast_variable::next, OBJ_POINTER, prefs, secret, user, user_destructor(), user_unref(), and ast_variable::value.

10848 {
10849    struct iax2_user *user = NULL;
10850    struct iax2_context *con, *conl = NULL;
10851    struct ast_ha *oldha = NULL;
10852    struct iax2_context *oldcon = NULL;
10853    int format;
10854    int firstpass=1;
10855    int oldcurauthreq = 0;
10856    char *varname = NULL, *varval = NULL;
10857    struct ast_variable *tmpvar = NULL;
10858    struct iax2_user tmp_user = {
10859       .name = name,
10860    };
10861 
10862    if (!temponly) {
10863       user = ao2_find(users, &tmp_user, OBJ_POINTER);
10864       if (user && !ast_test_flag(user, IAX_DELME))
10865          firstpass = 0;
10866    }
10867 
10868    if (user) {
10869       if (firstpass) {
10870          oldcurauthreq = user->curauthreq;
10871          oldha = user->ha;
10872          oldcon = user->contexts;
10873          user->ha = NULL;
10874          user->contexts = NULL;
10875       }
10876       /* Already in the list, remove it and it will be added back (or FREE'd) */
10877       ao2_unlink(users, user);
10878    } else {
10879       user = ao2_alloc(sizeof(*user), user_destructor);
10880    }
10881    
10882    if (user) {
10883       if (firstpass) {
10884          ast_string_field_free_memory(user);
10885          memset(user, 0, sizeof(struct iax2_user));
10886          if (ast_string_field_init(user, 32)) {
10887             user = user_unref(user);
10888             goto cleanup;
10889          }
10890          user->maxauthreq = maxauthreq;
10891          user->curauthreq = oldcurauthreq;
10892          user->prefs = prefs;
10893          user->capability = iax2_capability;
10894          user->encmethods = iax2_encryption;
10895          user->adsi = adsi;
10896          ast_string_field_set(user, name, name);
10897          ast_string_field_set(user, language, language);
10898          ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP);   
10899          ast_clear_flag(user, IAX_HASCALLERID);
10900          ast_string_field_set(user, cid_name, "");
10901          ast_string_field_set(user, cid_num, "");
10902          ast_string_field_set(user, accountcode, accountcode);
10903          ast_string_field_set(user, mohinterpret, mohinterpret);
10904          ast_string_field_set(user, mohsuggest, mohsuggest);
10905       }
10906       if (!v) {
10907          v = alt;
10908          alt = NULL;
10909       }
10910       while(v) {
10911          if (!strcasecmp(v->name, "context")) {
10912             con = build_context(v->value);
10913             if (con) {
10914                if (conl)
10915                   conl->next = con;
10916                else
10917                   user->contexts = con;
10918                conl = con;
10919             }
10920          } else if (!strcasecmp(v->name, "permit") ||
10921                   !strcasecmp(v->name, "deny")) {
10922             user->ha = ast_append_ha(v->name, v->value, user->ha, NULL);
10923          } else if (!strcasecmp(v->name, "setvar")) {
10924             varname = ast_strdupa(v->value);
10925             if (varname && (varval = strchr(varname,'='))) {
10926                *varval = '\0';
10927                varval++;
10928                if((tmpvar = ast_variable_new(varname, varval, ""))) {
10929                   tmpvar->next = user->vars; 
10930                   user->vars = tmpvar;
10931                }
10932             }
10933          } else if (!strcasecmp(v->name, "allow")) {
10934             ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
10935          } else if (!strcasecmp(v->name, "disallow")) {
10936             ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0);
10937          } else if (!strcasecmp(v->name, "trunk")) {
10938             ast_set2_flag(user, ast_true(v->value), IAX_TRUNK);   
10939             if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) {
10940                ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without DAHDI timing\n", user->name);
10941                ast_clear_flag(user, IAX_TRUNK);
10942             }
10943          } else if (!strcasecmp(v->name, "auth")) {
10944             user->authmethods = get_auth_methods(v->value);
10945          } else if (!strcasecmp(v->name, "encryption")) {
10946             user->encmethods = get_encrypt_methods(v->value);
10947          } else if (!strcasecmp(v->name, "transfer")) {
10948             if (!strcasecmp(v->value, "mediaonly")) {
10949                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA);  
10950             } else if (ast_true(v->value)) {
10951                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
10952             } else 
10953                ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
10954          } else if (!strcasecmp(v->name, "codecpriority")) {
10955             if(!strcasecmp(v->value, "caller"))
10956                ast_set_flag(user, IAX_CODEC_USER_FIRST);
10957             else if(!strcasecmp(v->value, "disabled"))
10958                ast_set_flag(user, IAX_CODEC_NOPREFS);
10959             else if(!strcasecmp(v->value, "reqonly")) {
10960                ast_set_flag(user, IAX_CODEC_NOCAP);
10961                ast_set_flag(user, IAX_CODEC_NOPREFS);
10962             }
10963          } else if (!strcasecmp(v->name, "jitterbuffer")) {
10964             ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF);
10965          } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
10966             ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF);
10967          } else if (!strcasecmp(v->name, "dbsecret")) {
10968             ast_string_field_set(user, dbsecret, v->value);
10969          } else if (!strcasecmp(v->name, "secret")) {
10970             if (!ast_strlen_zero(user->secret)) {
10971                char *old = ast_strdupa(user->secret);
10972 
10973                ast_string_field_build(user, secret, "%s;%s", old, v->value);
10974             } else
10975                ast_string_field_set(user, secret, v->value);
10976          } else if (!strcasecmp(v->name, "callerid")) {
10977             if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) {
10978                char name2[80];
10979                char num2[80];
10980                ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2));
10981                ast_string_field_set(user, cid_name, name2);
10982                ast_string_field_set(user, cid_num, num2);
10983                ast_set_flag(user, IAX_HASCALLERID);
10984             } else {
10985                ast_clear_flag(user, IAX_HASCALLERID);
10986                ast_string_field_set(user, cid_name, "");
10987                ast_string_field_set(user, cid_num, "");
10988             }
10989          } else if (!strcasecmp(v->name, "fullname")) {
10990             if (!ast_strlen_zero(v->value)) {
10991                ast_string_field_set(user, cid_name, v->value);
10992                ast_set_flag(user, IAX_HASCALLERID);
10993             } else {
10994                ast_string_field_set(user, cid_name, "");
10995                if (ast_strlen_zero(user->cid_num))
10996                   ast_clear_flag(user, IAX_HASCALLERID);
10997             }
10998          } else if (!strcasecmp(v->name, "cid_number")) {
10999             if (!ast_strlen_zero(v->value)) {
11000                ast_string_field_set(user, cid_num, v->value);
11001                ast_set_flag(user, IAX_HASCALLERID);
11002             } else {
11003                ast_string_field_set(user, cid_num, "");
11004                if (ast_strlen_zero(user->cid_name))
11005                   ast_clear_flag(user, IAX_HASCALLERID);
11006             }
11007          } else if (!strcasecmp(v->name, "accountcode")) {
11008             ast_string_field_set(user, accountcode, v->value);
11009          } else if (!strcasecmp(v->name, "mohinterpret")) {
11010             ast_string_field_set(user, mohinterpret, v->value);
11011          } else if (!strcasecmp(v->name, "mohsuggest")) {
11012             ast_string_field_set(user, mohsuggest, v->value);
11013          } else if (!strcasecmp(v->name, "language")) {
11014             ast_string_field_set(user, language, v->value);
11015          } else if (!strcasecmp(v->name, "amaflags")) {
11016             format = ast_cdr_amaflags2int(v->value);
11017             if (format < 0) {
11018                ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
11019             } else {
11020                user->amaflags = format;
11021             }
11022          } else if (!strcasecmp(v->name, "inkeys")) {
11023             ast_string_field_set(user, inkeys, v->value);
11024          } else if (!strcasecmp(v->name, "maxauthreq")) {
11025             user->maxauthreq = atoi(v->value);
11026             if (user->maxauthreq < 0)
11027                user->maxauthreq = 0;
11028          } else if (!strcasecmp(v->name, "adsi")) {
11029             user->adsi = ast_true(v->value);
11030          }/* else if (strcasecmp(v->name,"type")) */
11031          /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
11032          v = v->next;
11033          if (!v) {
11034             v = alt;
11035             alt = NULL;
11036          }
11037       }
11038       if (!user->authmethods) {
11039          if (!ast_strlen_zero(user->secret)) {
11040             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
11041             if (!ast_strlen_zero(user->inkeys))
11042                user->authmethods |= IAX_AUTH_RSA;
11043          } else if (!ast_strlen_zero(user->inkeys)) {
11044             user->authmethods = IAX_AUTH_RSA;
11045          } else {
11046             user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
11047          }
11048       }
11049       ast_clear_flag(user, IAX_DELME);
11050    }
11051 cleanup:
11052    if (oldha)
11053       ast_free_ha(oldha);
11054    if (oldcon)
11055       free_context(oldcon);
11056    return user;
11057 }

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

Definition at line 11616 of file chan_iax2.c.

References ARRAY_LEN, ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), 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, LOG_WARNING, NEW_FORCE, parse_dial_string(), secret, and send_command().

Referenced by find_cache().

11617 {
11618    struct sockaddr_in sin;
11619    int x;
11620    int callno;
11621    struct iax_ie_data ied;
11622    struct create_addr_info cai;
11623    struct parsed_dial_string pds;
11624    char *tmpstr;
11625 
11626    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
11627       /* Look for an *exact match* call.  Once a call is negotiated, it can only
11628          look up entries for a single context */
11629       if (!ast_mutex_trylock(&iaxsl[x])) {
11630          if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot))
11631             return x;
11632          ast_mutex_unlock(&iaxsl[x]);
11633       }
11634    }
11635 
11636    /* No match found, we need to create a new one */
11637 
11638    memset(&cai, 0, sizeof(cai));
11639    memset(&ied, 0, sizeof(ied));
11640    memset(&pds, 0, sizeof(pds));
11641 
11642    tmpstr = ast_strdupa(data);
11643    parse_dial_string(tmpstr, &pds);
11644 
11645    if (ast_strlen_zero(pds.peer)) {
11646       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
11647       return -1;
11648    }
11649 
11650    /* Populate our address from the given */
11651    if (create_addr(pds.peer, NULL, &sin, &cai))
11652       return -1;
11653 
11654    ast_debug(1, "peer: %s, username: %s, password: %s, context: %s\n",
11655       pds.peer, pds.username, pds.password, pds.context);
11656 
11657    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
11658    if (callno < 1) {
11659       ast_log(LOG_WARNING, "Unable to create call\n");
11660       return -1;
11661    }
11662 
11663    ast_string_field_set(iaxs[callno], dproot, data);
11664    iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH;
11665 
11666    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
11667    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD");
11668    /* the string format is slightly different from a standard dial string,
11669       because the context appears in the 'exten' position
11670    */
11671    if (pds.exten)
11672       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten);
11673    if (pds.username)
11674       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
11675    iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH);
11676    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH);
11677    /* Keep password handy */
11678    if (pds.password)
11679       ast_string_field_set(iaxs[callno], secret, pds.password);
11680    if (pds.key)
11681       ast_string_field_set(iaxs[callno], outkey, pds.key);
11682    /* Start the call going */
11683    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
11684 
11685    return callno;
11686 }

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

Definition at line 4528 of file chan_iax2.c.

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

04529 {
04530    /* Returns where in "receive time" we are.  That is, how many ms
04531       since we received (or would have received) the frame with timestamp 0 */
04532    int ms;
04533 #ifdef IAXTESTS
04534    int jit;
04535 #endif /* IAXTESTS */
04536    /* Setup rxcore if necessary */
04537    if (ast_tvzero(p->rxcore)) {
04538       p->rxcore = ast_tvnow();
04539       if (iaxdebug)
04540          ast_debug(1, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
04541                p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
04542       p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
04543 #if 1
04544       if (iaxdebug)
04545          ast_debug(1, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
04546                p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec));
04547 #endif
04548    }
04549 
04550    ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore);
04551 #ifdef IAXTESTS
04552    if (test_jit) {
04553       if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) {
04554          jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0));
04555          if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0)))
04556             jit = -jit;
04557          ms += jit;
04558       }
04559    }
04560    if (test_late) {
04561       ms += test_late;
04562       test_late = 0;
04563    }
04564 #endif /* IAXTESTS */
04565    return ms;
04566 }

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

Definition at line 4396 of file chan_iax2.c.

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

Referenced by iax2_send(), and socket_process().

04397 {
04398    int ms;
04399    int voice = 0;
04400    int genuine = 0;
04401    int adjust;
04402    struct timeval *delivery = NULL;
04403 
04404 
04405    /* What sort of frame do we have?: voice is self-explanatory
04406       "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK
04407       non-genuine frames are CONTROL frames [ringing etc], DTMF
04408       The "genuine" distinction is needed because genuine frames must get a clock-based timestamp,
04409       the others need a timestamp slaved to the voice frames so that they go in sequence
04410    */
04411    if (f) {
04412       if (f->frametype == AST_FRAME_VOICE) {
04413          voice = 1;
04414          delivery = &f->delivery;
04415       } else if (f->frametype == AST_FRAME_IAX) {
04416          genuine = 1;
04417       } else if (f->frametype == AST_FRAME_CNG) {
04418          p->notsilenttx = 0;  
04419       }
04420    }
04421    if (ast_tvzero(p->offset)) {
04422       p->offset = ast_tvnow();
04423       /* Round to nearest 20ms for nice looking traces */
04424       p->offset.tv_usec -= p->offset.tv_usec % 20000;
04425    }
04426    /* If the timestamp is specified, just send it as is */
04427    if (ts)
04428       return ts;
04429    /* If we have a time that the frame arrived, always use it to make our timestamp */
04430    if (delivery && !ast_tvzero(*delivery)) {
04431       ms = ast_tvdiff_ms(*delivery, p->offset);
04432       if (ms < 0) {
04433          ms = 0;
04434       }
04435       if (iaxdebug)
04436          ast_debug(3, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
04437    } else {
04438       ms = ast_tvdiff_ms(ast_tvnow(), p->offset);
04439       if (ms < 0)
04440          ms = 0;
04441       if (voice) {
04442          /* On a voice frame, use predicted values if appropriate */
04443          if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
04444             /* Adjust our txcore, keeping voice and non-voice synchronized */
04445             /* AN EXPLANATION:
04446                When we send voice, we usually send "calculated" timestamps worked out
04447                on the basis of the number of samples sent. When we send other frames,
04448                we usually send timestamps worked out from the real clock.
04449                The problem is that they can tend to drift out of step because the 
04450                   source channel's clock and our clock may not be exactly at the same rate.
04451                We fix this by continuously "tweaking" p->offset.  p->offset is "time zero"
04452                for this call.  Moving it adjusts timestamps for non-voice frames.
04453                We make the adjustment in the style of a moving average.  Each time we
04454                adjust p->offset by 10% of the difference between our clock-derived
04455                timestamp and the predicted timestamp.  That's why you see "10000"
04456                below even though IAX2 timestamps are in milliseconds.
04457                The use of a moving average avoids offset moving too radically.
04458                Generally, "adjust" roams back and forth around 0, with offset hardly
04459                changing at all.  But if a consistent different starts to develop it
04460                will be eliminated over the course of 10 frames (200-300msecs) 
04461             */
04462             adjust = (ms - p->nextpred);
04463             if (adjust < 0)
04464                p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000));
04465             else if (adjust > 0)
04466                p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000));
04467 
04468             if (!p->nextpred) {
04469                p->nextpred = ms; /*f->samples / 8;*/
04470                if (p->nextpred <= p->lastsent)
04471                   p->nextpred = p->lastsent + 3;
04472             }
04473             ms = p->nextpred;
04474          } else {
04475                 /* in this case, just use the actual
04476             * time, since we're either way off
04477             * (shouldn't happen), or we're  ending a
04478             * silent period -- and seed the next
04479             * predicted time.  Also, round ms to the
04480             * next multiple of frame size (so our
04481             * silent periods are multiples of
04482             * frame size too) */
04483 
04484             if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW )
04485                ast_debug(1, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n",
04486                   abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW);
04487 
04488             if (f->samples >= 8) /* check to make sure we dont core dump */
04489             {
04490                int diff = ms % (f->samples / 8);
04491                if (diff)
04492                    ms += f->samples/8 - diff;
04493             }
04494 
04495             p->nextpred = ms;
04496             p->notsilenttx = 1;
04497          }
04498       } else if ( f->frametype == AST_FRAME_VIDEO ) {
04499          /*
04500          * IAX2 draft 03 says that timestamps MUST be in order.
04501          * It does not say anything about several frames having the same timestamp
04502          * When transporting video, we can have a frame that spans multiple iax packets
04503          * (so called slices), so it would make sense to use the same timestamp for all of
04504          * them
04505          * We do want to make sure that frames don't go backwards though
04506          */
04507          if ( (unsigned int)ms < p->lastsent )
04508             ms = p->lastsent;
04509       } else {
04510          /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless
04511             it's a genuine frame */
04512          if (genuine) {
04513             /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */
04514             if (ms <= p->lastsent)
04515                ms = p->lastsent + 3;
04516          } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) {
04517             /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */
04518             ms = p->lastsent + 3;
04519          }
04520       }
04521    }
04522    p->lastsent = ms;
04523    if (voice)
04524       p->nextpred = p->nextpred + f->samples / 8;
04525    return ms;
04526 }

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

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

04353 {
04354    unsigned long int mssincetx; /* unsigned to handle overflows */
04355    long int ms, pred;
04356 
04357    tpeer->trunkact = *tv;
04358    mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime);
04359    if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
04360       /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
04361       tpeer->txtrunktime = *tv;
04362       tpeer->lastsent = 999999;
04363    }
04364    /* Update last transmit time now */
04365    tpeer->lasttxtime = *tv;
04366    
04367    /* Calculate ms offset */
04368    ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime);
04369    /* Predict from last value */
04370    pred = tpeer->lastsent + sampms;
04371    if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
04372       ms = pred;
04373    
04374    /* We never send the same timestamp twice, so fudge a little if we must */
04375    if (ms == tpeer->lastsent)
04376       ms = tpeer->lastsent + 1;
04377    tpeer->lastsent = ms;
04378    return ms;
04379 }

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

Definition at line 6000 of file chan_iax2.c.

References 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(), cid_name, cid_num, exten, ast_variable::file, iax2_getpeertrunk(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, 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, ies, LOG_WARNING, ast_variable::name, ast_variable::next, prefs, realtime_user(), secret, user, user_unref(), ast_variable::value, and version.

Referenced by socket_process().

06001 {
06002    /* Start pessimistic */
06003    int res = -1;
06004    int version = 2;
06005    struct iax2_user *user = NULL, *best = NULL;
06006    int bestscore = 0;
06007    int gotcapability = 0;
06008    struct ast_variable *v = NULL, *tmpvar = NULL;
06009    struct ao2_iterator i;
06010 
06011    if (!iaxs[callno])
06012       return res;
06013    if (ies->called_number)
06014       ast_string_field_set(iaxs[callno], exten, ies->called_number);
06015    if (ies->calling_number) {
06016       ast_shrink_phone_number(ies->calling_number);
06017       ast_string_field_set(iaxs[callno], cid_num, ies->calling_number);
06018    }
06019    if (ies->calling_name)
06020       ast_string_field_set(iaxs[callno], cid_name, ies->calling_name);
06021    if (ies->calling_ani)
06022       ast_string_field_set(iaxs[callno], ani, ies->calling_ani);
06023    if (ies->dnid)
06024       ast_string_field_set(iaxs[callno], dnid, ies->dnid);
06025    if (ies->rdnis)
06026       ast_string_field_set(iaxs[callno], rdnis, ies->rdnis);
06027    if (ies->called_context)
06028       ast_string_field_set(iaxs[callno], context, ies->called_context);
06029    if (ies->language)
06030       ast_string_field_set(iaxs[callno], language, ies->language);
06031    if (ies->username)
06032       ast_string_field_set(iaxs[callno], username, ies->username);
06033    if (ies->calling_ton > -1)
06034       iaxs[callno]->calling_ton = ies->calling_ton;
06035    if (ies->calling_tns > -1)
06036       iaxs[callno]->calling_tns = ies->calling_tns;
06037    if (ies->calling_pres > -1)
06038       iaxs[callno]->calling_pres = ies->calling_pres;
06039    if (ies->format)
06040       iaxs[callno]->peerformat = ies->format;
06041    if (ies->adsicpe)
06042       iaxs[callno]->peeradsicpe = ies->adsicpe;
06043    if (ies->capability) {
06044       gotcapability = 1;
06045       iaxs[callno]->peercapability = ies->capability;
06046    } 
06047    if (ies->version)
06048       version = ies->version;
06049 
06050    /* Use provided preferences until told otherwise for actual preferences */
06051    if(ies->codec_prefs) {
06052       ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0);
06053       ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0);
06054    }
06055 
06056    if (!gotcapability) 
06057       iaxs[callno]->peercapability = iaxs[callno]->peerformat;
06058    if (version > IAX_PROTO_VERSION) {
06059       ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 
06060          ast_inet_ntoa(sin->sin_addr), version);
06061       return res;
06062    }
06063    /* Search the userlist for a compatible entry, and fill in the rest */
06064    i = ao2_iterator_init(users, 0);
06065    while ((user = ao2_iterator_next(&i))) {
06066       if ((ast_strlen_zero(iaxs[callno]->username) ||          /* No username specified */
06067          !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
06068          && ast_apply_ha(user->ha, sin)   /* Access is permitted from this IP */
06069          && (ast_strlen_zero(iaxs[callno]->context) ||         /* No context specified */
06070               apply_context(user->contexts, iaxs[callno]->context))) {        /* Context is permitted */
06071          if (!ast_strlen_zero(iaxs[callno]->username)) {
06072             /* Exact match, stop right now. */
06073             if (best)
06074                user_unref(best);
06075             best = user;
06076             break;
06077          } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) {
06078             /* No required authentication */
06079             if (user->ha) {
06080                /* There was host authentication and we passed, bonus! */
06081                if (bestscore < 4) {
06082                   bestscore = 4;
06083                   if (best)
06084                      user_unref(best);
06085                   best = user;
06086                   continue;
06087                }
06088             } else {
06089                /* No host access, but no secret, either, not bad */
06090                if (bestscore < 3) {
06091                   bestscore = 3;
06092                   if (best)
06093                      user_unref(best);
06094                   best = user;
06095                   continue;
06096                }
06097             }
06098          } else {
06099             if (user->ha) {
06100                /* Authentication, but host access too, eh, it's something.. */
06101                if (bestscore < 2) {
06102                   bestscore = 2;
06103                   if (best)
06104                      user_unref(best);
06105                   best = user;
06106                   continue;
06107                }
06108             } else {
06109                /* Authentication and no host access...  This is our baseline */
06110                if (bestscore < 1) {
06111                   bestscore = 1;
06112                   if (best)
06113                      user_unref(best);
06114                   best = user;
06115                   continue;
06116                }
06117             }
06118          }
06119       }
06120       user_unref(user);
06121    }
06122    user = best;
06123    if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
06124       user = realtime_user(iaxs[callno]->username, sin);
06125       if (user && !ast_strlen_zero(iaxs[callno]->context) &&         /* No context specified */
06126           !apply_context(user->contexts, iaxs[callno]->context)) {      /* Context is permitted */
06127          user = user_unref(user);
06128       }
06129    }
06130    if (user) {
06131       /* We found our match (use the first) */
06132       /* copy vars */
06133       for (v = user->vars ; v ; v = v->next) {
06134          if((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
06135             tmpvar->next = iaxs[callno]->vars; 
06136             iaxs[callno]->vars = tmpvar;
06137          }
06138       }
06139       /* If a max AUTHREQ restriction is in place, activate it */
06140       if (user->maxauthreq > 0)
06141          ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
06142       iaxs[callno]->prefs = user->prefs;
06143       ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
06144       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
06145       ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP);
06146       iaxs[callno]->encmethods = user->encmethods;
06147       /* Store the requested username if not specified */
06148       if (ast_strlen_zero(iaxs[callno]->username))
06149          ast_string_field_set(iaxs[callno], username, user->name);
06150       /* Store whether this is a trunked call, too, of course, and move if appropriate */
06151       ast_copy_flags(iaxs[callno], user, IAX_TRUNK);
06152       iaxs[callno]->capability = user->capability;
06153       /* And use the default context */
06154       if (ast_strlen_zero(iaxs[callno]->context)) {
06155          if (user->contexts)
06156             ast_string_field_set(iaxs[callno], context, user->contexts->context);
06157          else
06158             ast_string_field_set(iaxs[callno], context, context);
06159       }
06160       /* And any input keys */
06161       ast_string_field_set(iaxs[callno], inkeys, user->inkeys);
06162       /* And the permitted authentication methods */
06163       iaxs[callno]->authmethods = user->authmethods;
06164       iaxs[callno]->adsi = user->adsi;
06165       /* If the user has callerid, override the remote caller id. */
06166       if (ast_test_flag(user, IAX_HASCALLERID)) {
06167          iaxs[callno]->calling_tns = 0;
06168          iaxs[callno]->calling_ton = 0;
06169          ast_string_field_set(iaxs[callno], cid_num, user->cid_num);
06170          ast_string_field_set(iaxs[callno], cid_name, user->cid_name);
06171          ast_string_field_set(iaxs[callno], ani, user->cid_num);
06172          iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
06173       } else if (ast_strlen_zero(iaxs[callno]->cid_num) && ast_strlen_zero(iaxs[callno]->cid_name)) {
06174          iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE;
06175       } /* else user is allowed to set their own CID settings */
06176       if (!ast_strlen_zero(user->accountcode))
06177          ast_string_field_set(iaxs[callno], accountcode, user->accountcode);
06178       if (!ast_strlen_zero(user->mohinterpret))
06179          ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
06180       if (!ast_strlen_zero(user->mohsuggest))
06181          ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
06182       if (user->amaflags)
06183          iaxs[callno]->amaflags = user->amaflags;
06184       if (!ast_strlen_zero(user->language))
06185          ast_string_field_set(iaxs[callno], language, user->language);
06186       ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);   
06187       /* Keep this check last */
06188       if (!ast_strlen_zero(user->dbsecret)) {
06189          char *family, *key=NULL;
06190          char buf[80];
06191          family = ast_strdupa(user->dbsecret);
06192          key = strchr(family, '/');
06193          if (key) {
06194             *key = '\0';
06195             key++;
06196          }
06197          if (!key || ast_db_get(family, key, buf, sizeof(buf)))
06198             ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret);
06199          else
06200             ast_string_field_set(iaxs[callno], secret, buf);
06201       } else
06202          ast_string_field_set(iaxs[callno], secret, user->secret);
06203       res = 0;
06204       user = user_unref(user);
06205    } else {
06206        /* user was not found, but we should still fake an AUTHREQ.
06207         * Set authmethods to the last known authmethod used by the system
06208         * Set a fake secret, it's not looked at, just required to attempt authentication.
06209         * Set authrej so the AUTHREP is rejected without even looking at its contents */
06210       iaxs[callno]->authmethods = last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
06211       ast_string_field_set(iaxs[callno], secret, "badsecret");
06212       iaxs[callno]->authrej = 1;
06213       if (!ast_strlen_zero(iaxs[callno]->username)) {
06214          /* only send the AUTHREQ if a username was specified. */
06215          res = 0;
06216       }
06217    }
06218    ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK);  
06219    return res;
06220 }

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

Definition at line 7773 of file chan_iax2.c.

References ast_debug, iax2_provision(), and iax_provision_version().

Referenced by socket_process().

07774 {
07775    unsigned int ourver;
07776    char rsi[80];
07777    snprintf(rsi, sizeof(rsi), "si-%s", si);
07778    if (iax_provision_version(&ourver, rsi, 1))
07779       return 0;
07780    ast_debug(1, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver);
07781    if (ourver != ver) 
07782       iax2_provision(sin, sockfd, NULL, rsi, 1);
07783    return 0;
07784 }

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

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

Referenced by peer_set_srcaddr().

10482 {
10483    int sd;
10484    int res;
10485    
10486    sd = socket(AF_INET, SOCK_DGRAM, 0);
10487    if (sd < 0) {
10488       ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno));
10489       return -1;
10490    }
10491 
10492    res = bind(sd, sa, salen);
10493    if (res < 0) {
10494       ast_debug(1, "Can't bind: %s\n", strerror(errno));
10495       close(sd);
10496       return 1;
10497    }
10498 
10499    close(sd);
10500    return 0;
10501 }

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

Definition at line 6763 of file chan_iax2.c.

References ARRAY_LEN, ast_copy_string(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_UNKNOWN, iax2_dpcache::callno, iax2_dpcache::expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, ies, matchmore(), iax2_dpcache::orig, iax2_dpcache::peer_list, status, and iax2_dpcache::waiters.

Referenced by socket_process().

06764 {
06765    char exten[256] = "";
06766    int status = CACHE_FLAG_UNKNOWN, expiry = iaxdefaultdpcache, x, matchmore = 0;
06767    struct iax2_dpcache *dp = NULL;
06768    
06769    if (ies->called_number)
06770       ast_copy_string(exten, ies->called_number, sizeof(exten));
06771    
06772    if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
06773       status = CACHE_FLAG_EXISTS;
06774    else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
06775       status = CACHE_FLAG_CANEXIST;
06776    else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
06777       status = CACHE_FLAG_NONEXISTENT;
06778 
06779    if (ies->refresh)
06780       expiry = ies->refresh;
06781    if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
06782       matchmore = CACHE_FLAG_MATCHMORE;
06783    
06784    AST_LIST_LOCK(&dpcache);
06785    AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, peer_list) {
06786       if (strcmp(dp->exten, exten))
06787          continue;
06788       AST_LIST_REMOVE_CURRENT(peer_list);
06789       dp->callno = 0;
06790       dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
06791       if (dp->flags & CACHE_FLAG_PENDING) {
06792          dp->flags &= ~CACHE_FLAG_PENDING;
06793          dp->flags |= status;
06794          dp->flags |= matchmore;
06795       }
06796       /* Wake up waiters */
06797       for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
06798          if (dp->waiters[x] > -1) {
06799             if (write(dp->waiters[x], "asdf", 4) < 0) {
06800             }
06801          }
06802       }
06803    }
06804    AST_LIST_TRAVERSE_SAFE_END;
06805    AST_LIST_UNLOCK(&dpcache);
06806 
06807    return 0;
06808 }

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

Definition at line 2746 of file chan_iax2.c.

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

Referenced by handle_cli_iax2_prune_realtime(), and handle_cli_iax2_show_peer().

02747 {
02748    int which = 0;
02749    struct iax2_peer *peer;
02750    char *res = NULL;
02751    int wordlen = strlen(word);
02752    struct ao2_iterator i;
02753 
02754    /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
02755    if (pos != 3)
02756       return NULL;
02757 
02758    i = ao2_iterator_init(peers, 0);
02759    while ((peer = ao2_iterator_next(&i))) {
02760       if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
02761          res = ast_strdup(peer->name);
02762          peer_unref(peer);
02763          break;
02764       }
02765       peer_unref(peer);
02766    }
02767 
02768    return res;
02769 }

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

Definition at line 5374 of file chan_iax2.c.

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

Referenced by handle_cli_iax2_unregister().

05375 {
05376    int which = 0;
05377    struct iax2_peer *p = NULL;
05378    char *res = NULL;
05379    int wordlen = strlen(word);
05380 
05381    /* 0 - iax2; 1 - unregister; 2 - <peername> */
05382    if (pos == 2) {
05383       struct ao2_iterator i = ao2_iterator_init(peers, 0);
05384       while ((p = ao2_iterator_next(&i))) {
05385          if (!strncasecmp(p->name, word, wordlen) && 
05386             ++which > state && p->expire > 0) {
05387             res = ast_strdup(p->name);
05388             peer_unref(p);
05389             break;
05390          }
05391          peer_unref(p);
05392       }
05393    }
05394 
05395    return res;
05396 }

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

Definition at line 6810 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(), 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, remove_by_peercallno(), remove_by_transfercallno(), 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().

06811 {
06812    int peercallno = 0;
06813    struct chan_iax2_pvt *pvt = iaxs[callno];
06814    struct iax_frame *cur;
06815    jb_frame frame;
06816 
06817    if (ies->callno)
06818       peercallno = ies->callno;
06819 
06820    if (peercallno < 1) {
06821       ast_log(LOG_WARNING, "Invalid transfer request\n");
06822       return -1;
06823    }
06824    remove_by_transfercallno(pvt);
06825    memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
06826    memset(&pvt->transfer, 0, sizeof(pvt->transfer));
06827    /* Reset sequence numbers */
06828    pvt->oseqno = 0;
06829    pvt->rseqno = 0;
06830    pvt->iseqno = 0;
06831    pvt->aseqno = 0;
06832 
06833    if (pvt->peercallno) {
06834       remove_by_peercallno(pvt);
06835    }
06836    pvt->peercallno = peercallno;
06837    /*this is where the transfering call swiches hash tables */
06838    store_by_peercallno(pvt);
06839    pvt->transferring = TRANSFER_NONE;
06840    pvt->svoiceformat = -1;
06841    pvt->voiceformat = 0;
06842    pvt->svideoformat = -1;
06843    pvt->videoformat = 0;
06844    pvt->transfercallno = -1;
06845    memset(&pvt->rxcore, 0, sizeof(pvt->rxcore));
06846    memset(&pvt->offset, 0, sizeof(pvt->offset));
06847    /* reset jitterbuffer */
06848    while(jb_getall(pvt->jb,&frame) == JB_OK)
06849       iax2_frame_free(frame.data);
06850    jb_reset(pvt->jb);
06851    pvt->lag = 0;
06852    pvt->last = 0;
06853    pvt->lastsent = 0;
06854    pvt->nextpred = 0;
06855    pvt->pingtime = DEFAULT_RETRY_TIME;
06856    AST_LIST_LOCK(&frame_queue);
06857    AST_LIST_TRAVERSE(&frame_queue, cur, list) {
06858       /* We must cancel any packets that would have been transmitted
06859          because now we're talking to someone new.  It's okay, they
06860          were transmitted to someone that didn't care anyway. */
06861       if (callno == cur->callno) 
06862          cur->retries = -1;
06863    }
06864    AST_LIST_UNLOCK(&frame_queue);
06865    return 0; 
06866 }

static unsigned char compress_subclass ( int  subclass  )  [static]

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

01244 {
01245    int x;
01246    int power=-1;
01247    /* If it's 128 or smaller, just return it */
01248    if (subclass < IAX_FLAG_SC_LOG)
01249       return subclass;
01250    /* Otherwise find its power */
01251    for (x = 0; x < IAX_MAX_SHIFT; x++) {
01252       if (subclass & (1 << x)) {
01253          if (power > -1) {
01254             ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass);
01255             return 0;
01256          } else
01257             power = x;
01258       }
01259    }
01260    return power | IAX_FLAG_SC_LOG;
01261 }

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

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

07787 {
07788    jb_info stats;
07789    jb_getinfo(pvt->jb, &stats);
07790    
07791    memset(iep, 0, sizeof(*iep));
07792 
07793    iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter);
07794    if(stats.frames_in == 0) stats.frames_in = 1;
07795    iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff)));
07796    iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in);
07797    iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min);
07798    iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped);
07799    iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo);
07800 }

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

Definition at line 3438 of file chan_iax2.c.

References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_codec_pref_prepend(), ast_copy_flags, ast_copy_string(), ast_db_get(), ast_get_ip_or_srv(), 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, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_DEBUG, 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.

03439 {
03440    struct iax2_peer *peer;
03441    int res = -1;
03442    struct ast_codec_pref ourprefs;
03443 
03444    ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK);
03445    cai->sockfd = defaultsockfd;
03446    cai->maxtime = 0;
03447    sin->sin_family = AF_INET;
03448 
03449    if (!(peer = find_peer(peername, 1))) {
03450       cai->found = 0;
03451       if (ast_get_ip_or_srv(sin, peername, srvlookup ? "_iax._udp" : NULL)) {
03452          ast_log(LOG_WARNING, "No such host: %s\n", peername);
03453          return -1;
03454       }
03455       sin->sin_port = htons(IAX_DEFAULT_PORTNO);
03456       /* use global iax prefs for unknown peer/user */
03457       /* But move the calling channel's native codec to the top of the preference list */
03458       memcpy(&ourprefs, &prefs, sizeof(ourprefs));
03459       if (c)
03460          ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03461       ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03462       return 0;
03463    }
03464 
03465    cai->found = 1;
03466    
03467    /* if the peer has no address (current or default), return failure */
03468    if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr))
03469       goto return_unref;
03470 
03471    /* if the peer is being monitored and is currently unreachable, return failure */
03472    if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
03473       goto return_unref;
03474 
03475    ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
03476    cai->maxtime = peer->maxms;
03477    cai->capability = peer->capability;
03478    cai->encmethods = peer->encmethods;
03479    cai->sockfd = peer->sockfd;
03480    cai->adsi = peer->adsi;
03481    memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs));
03482    /* Move the calling channel's native codec to the top of the preference list */
03483    if (c) {
03484       ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats);
03485       ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1);
03486    }
03487    ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1);
03488    ast_copy_string(cai->context, peer->context, sizeof(cai->context));
03489    ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext));
03490    ast_copy_string(cai->username, peer->username, sizeof(cai->username));
03491    ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone));
03492    ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey));
03493    ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret));
03494    ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest));
03495    if (ast_strlen_zero(peer->dbsecret)) {
03496       ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret));
03497    } else {
03498       char *family;
03499       char *key = NULL;
03500 
03501       family = ast_strdupa(peer->dbsecret);
03502       key = strchr(family, '/');
03503       if (key)
03504          *key++ = '\0';
03505       if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) {
03506          ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret);
03507          goto return_unref;
03508       }
03509    }
03510 
03511    if (peer->addr.sin_addr.s_addr) {
03512       sin->sin_addr = peer->addr.sin_addr;
03513       sin->sin_port = peer->addr.sin_port;
03514    } else {
03515       sin->sin_addr = peer->defaddr.sin_addr;
03516       sin->sin_port = peer->defaddr.sin_port;
03517    }
03518 
03519    res = 0;
03520 
03521 return_unref:
03522    peer_unref(peer);
03523 
03524    return res;
03525 }

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

Definition at line 4750 of file chan_iax2.c.

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

Referenced by decrypt_frame(), and update_packet().

04751 {
04752    int padding;
04753    unsigned char *workspace;
04754 
04755    workspace = alloca(*datalen);
04756    memset(f, 0, sizeof(*f));
04757    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04758       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04759       if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
04760          return -1;
04761       /* Decrypt */
04762       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
04763 
04764       padding = 16 + (workspace[15] & 0x0f);
04765       if (iaxdebug)
04766          ast_debug(1, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
04767       if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
04768          return -1;
04769 
04770       *datalen -= padding;
04771       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04772       f->frametype = fh->type;
04773       if (f->frametype == AST_FRAME_VIDEO) {
04774          f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
04775       } else {
04776          f->subclass = uncompress_subclass(fh->csub);
04777       }
04778    } else {
04779       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04780       if (iaxdebug)
04781          ast_debug(1, "Decoding mini with length %d\n", *datalen);
04782       if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
04783          return -1;
04784       /* Decrypt */
04785       memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
04786       padding = 16 + (workspace[15] & 0x0f);
04787       if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
04788          return -1;
04789       *datalen -= padding;
04790       memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04791    }
04792    return 0;
04793 }

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

Definition at line 4836 of file chan_iax2.c.

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

Referenced by socket_process().

04837 {
04838    int res=-1;
04839    if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) {
04840       /* Search for possible keys, given secrets */
04841       struct MD5Context md5;
04842       unsigned char digest[16];
04843       char *tmppw, *stringp;
04844       
04845       tmppw = ast_strdupa(iaxs[callno]->secret);
04846       stringp = tmppw;
04847       while ((tmppw = strsep(&stringp, ";"))) {
04848          MD5Init(&md5);
04849          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
04850          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
04851          MD5Final(digest, &md5);
04852          build_encryption_keys(digest, iaxs[callno]);
04853          res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04854          if (!res) {
04855             ast_set_flag(iaxs[callno], IAX_KEYPOPULATED);
04856             break;
04857          }
04858       }
04859    } else 
04860       res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen);
04861    return res;
04862 }

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

07934 {
07935    struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf;
07936    struct ast_iax2_full_hdr *fh, *cur_fh;
07937 
07938    if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len)))
07939       return;
07940 
07941    pkt_buf->len = from_here->buf_len;
07942    memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len);
07943 
07944    fh = (struct ast_iax2_full_hdr *) pkt_buf->buf;
07945    ast_mutex_lock(&to_here->lock);
07946    AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) {
07947       cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf;
07948       if (fh->oseqno < cur_fh->oseqno) {
07949          AST_LIST_INSERT_BEFORE_CURRENT(pkt_buf, entry);
07950          break;
07951       }
07952    }
07953    AST_LIST_TRAVERSE_SAFE_END
07954 
07955    if (!cur_pkt_buf)
07956       AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry);
07957    
07958    ast_mutex_unlock(&to_here->lock);
07959 }

static void delete_users ( void   )  [static]

Definition at line 11077 of file chan_iax2.c.

References ao2_callback(), ast_dnsmgr_release(), ast_free, 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, iax2_destroy(), peer_delme_cb(), sched, and user_delme_cb().

11078 {
11079    struct iax2_registry *reg;
11080 
11081    ao2_callback(users, 0, user_delme_cb, NULL);
11082 
11083    AST_LIST_LOCK(&registrations);
11084    while ((reg = AST_LIST_REMOVE_HEAD(&registrations, entry))) {
11085       AST_SCHED_DEL(sched, reg->expire);
11086       if (reg->callno) {
11087          int callno = reg->callno;
11088          ast_mutex_lock(&iaxsl[callno]);
11089          if (iaxs[callno]) {
11090             iaxs[callno]->reg = NULL;
11091             iax2_destroy(callno);
11092          }
11093          ast_mutex_unlock(&iaxsl[callno]);
11094       }
11095       if (reg->dnsmgr)
11096          ast_dnsmgr_release(reg->dnsmgr);
11097       ast_free(reg);
11098    }
11099    AST_LIST_UNLOCK(&registrations);
11100 
11101    ao2_callback(peers, 0, peer_delme_cb, NULL);
11102 }

static void destroy_firmware ( struct iax_firmware cur  )  [static]

Definition at line 1954 of file chan_iax2.c.

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

Referenced by reload_firmware().

01955 {
01956    /* Close firmware */
01957    if (cur->fwh) {
01958       munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh)));
01959    }
01960    close(cur->fd);
01961    ast_free(cur);
01962 }

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

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

Referenced by dp_lookup_thread(), and socket_process().

07635 {
07636    unsigned short dpstatus = 0;
07637    struct iax_ie_data ied1;
07638    int mm;
07639 
07640    memset(&ied1, 0, sizeof(ied1));
07641    mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid);
07642    /* Must be started */
07643    if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) {
07644       dpstatus = IAX_DPSTATUS_EXISTS;
07645    } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) {
07646       dpstatus = IAX_DPSTATUS_CANEXIST;
07647    } else {
07648       dpstatus = IAX_DPSTATUS_NONEXISTENT;
07649    }
07650    if (ast_ignore_pattern(context, callednum))
07651       dpstatus |= IAX_DPSTATUS_IGNOREPAT;
07652    if (mm)
07653       dpstatus |= IAX_DPSTATUS_MATCHMORE;
07654    if (!skiplock)
07655       ast_mutex_lock(&iaxsl[callno]);
07656    if (iaxs[callno]) {
07657       iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum);
07658       iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus);
07659       iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache);
07660       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1);
07661    }
07662    if (!skiplock)
07663       ast_mutex_unlock(&iaxsl[callno]);
07664 }

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

Definition at line 7666 of file chan_iax2.c.

References ast_free, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, and dp_lookup().

Referenced by spawn_dp_lookup().

07667 {
07668    /* Look up for dpreq */
07669    struct dpreq_data *dpr = data;
07670    dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0);
07671    if (dpr->callerid)
07672       ast_free(dpr->callerid);
07673    ast_free(dpr);
07674    return NULL;
07675 }

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

Definition at line 4795 of file chan_iax2.c.

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

Referenced by iax2_send(), and update_packet().

04796 {
04797    int padding;
04798    unsigned char *workspace;
04799    workspace = alloca(*datalen + 32);
04800    if (!workspace)
04801       return -1;
04802    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
04803       struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
04804       if (iaxdebug)
04805          ast_debug(1, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
04806       padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
04807       padding = 16 + (padding & 0xf);
04808       memcpy(workspace, poo, padding);
04809       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
04810       workspace[15] &= 0xf0;
04811       workspace[15] |= (padding & 0xf);
04812       if (iaxdebug)
04813          ast_debug(1, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]);
04814       *datalen += padding;
04815       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
04816       if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
04817          memcpy(poo, workspace + *datalen - 32, 32);
04818    } else {
04819       struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh;
04820       if (iaxdebug)
04821          ast_debug(1, "Encoding mini frame with length %d\n", *datalen);
04822       padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
04823       padding = 16 + (padding & 0xf);
04824       memcpy(workspace, poo, padding);
04825       memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
04826       workspace[15] &= 0xf0;
04827       workspace[15] |= (padding & 0x0f);
04828       *datalen += padding;
04829       memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
04830       if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
04831          memcpy(poo, workspace + *datalen - 32, 32);
04832    }
04833    return 0;
04834 }

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

Definition at line 7062 of file chan_iax2.c.

References __expire_registry(), and schedule_action.

Referenced by handle_cli_iax2_prune_realtime(), handle_cli_iax2_unregister(), reg_source_db(), and update_registry().

07063 {
07064 #ifdef SCHED_MULTITHREADED
07065    if (schedule_action(__expire_registry, data))
07066 #endif      
07067       __expire_registry(data);
07068    return 0;
07069 }

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

References ARRAY_LEN, ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_copy_string(), ast_free, ast_frfree, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, chan, errno, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, iax2_dprequest(), IAX_STATE_STARTED, LOG_WARNING, iax2_dpcache::orig, iax2_dpcache::peercontext, and iax2_dpcache::waiters.

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

11689 {
11690    struct iax2_dpcache *dp = NULL;
11691    struct timeval tv = ast_tvnow();
11692    int x, com[2], timeout, old = 0, outfd, abort, callno;
11693    struct ast_channel *c = NULL;
11694    struct ast_frame *f = NULL;
11695 
11696    AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) {
11697       if (ast_tvcmp(tv, dp->expiry) > 0) {
11698          AST_LIST_REMOVE_CURRENT(cache_list);
11699          if ((dp->flags & CACHE_FLAG_PENDING) || dp->callno)
11700             ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = blah, callno = %d)\n", dp->flags, dp->callno);
11701          else
11702             ast_free(dp);
11703          continue;
11704       }
11705       if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten))
11706          break;
11707    }
11708    AST_LIST_TRAVERSE_SAFE_END;
11709 
11710    if (!dp) {
11711       /* No matching entry.  Create a new one. */
11712       /* First, can we make a callno? */
11713       if ((callno = cache_get_callno_locked(data)) < 0) {
11714          ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
11715          return NULL;
11716       }
11717       if (!(dp = ast_calloc(1, sizeof(*dp)))) {
11718          ast_mutex_unlock(&iaxsl[callno]);
11719          return NULL;
11720       }
11721       ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext));
11722       ast_copy_string(dp->exten, exten, sizeof(dp->exten));
11723       dp->expiry = ast_tvnow();
11724       dp->orig = dp->expiry;
11725       /* Expires in 30 mins by default */
11726       dp->expiry.tv_sec += iaxdefaultdpcache;
11727       dp->flags = CACHE_FLAG_PENDING;
11728       for (x = 0; x < ARRAY_LEN(dp->waiters); x++)
11729          dp->waiters[x] = -1;
11730       /* Insert into the lists */
11731       AST_LIST_INSERT_TAIL(&dpcache, dp, cache_list);
11732       AST_LIST_INSERT_TAIL(&iaxs[callno]->dpentries, dp, peer_list);
11733       /* Send the request if we're already up */
11734       if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
11735          iax2_dprequest(dp, callno);
11736       ast_mutex_unlock(&iaxsl[callno]);
11737    }
11738 
11739    /* By here we must have a dp */
11740    if (dp->flags & CACHE_FLAG_PENDING) {
11741       /* Okay, here it starts to get nasty.  We need a pipe now to wait
11742          for a reply to come back so long as it's pending */
11743       for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
11744          /* Find an empty slot */
11745          if (dp->waiters[x] < 0)
11746             break;
11747       }
11748       if (x >= ARRAY_LEN(dp->waiters)) {
11749          ast_log(LOG_WARNING, "No more waiter positions available\n");
11750          return NULL;
11751       }
11752       if (pipe(com)) {
11753          ast_log(LOG_WARNING, "Unable to create pipe for comm\n");
11754          return NULL;
11755       }
11756       dp->waiters[x] = com[1];
11757       /* Okay, now we wait */
11758       timeout = iaxdefaulttimeout * 1000;
11759       /* Temporarily unlock */
11760       AST_LIST_UNLOCK(&dpcache);
11761       /* Defer any dtmf */
11762       if (chan)
11763          old = ast_channel_defer_dtmf(chan);
11764       abort = 0;
11765       while(timeout) {
11766          c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
11767          if (outfd > -1)
11768             break;
11769          if (!c)
11770             continue;
11771          if (!(f = ast_read(c))) {
11772             abort = 1;
11773             break;
11774          }
11775          ast_frfree(f);
11776       }
11777       if (!timeout) {
11778          ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
11779       }
11780       AST_LIST_LOCK(&dpcache);
11781       dp->waiters[x] = -1;
11782       close(com[1]);
11783       close(com[0]);
11784       if (abort) {
11785          /* Don't interpret anything, just abort.  Not sure what th epoint
11786            of undeferring dtmf on a hung up channel is but hey whatever */
11787          if (!old && chan)
11788             ast_channel_undefer_dtmf(chan);
11789          return NULL;
11790       }
11791       if (!(dp->flags & CACHE_FLAG_TIMEOUT)) {
11792          /* Now to do non-independent analysis the results of our wait */
11793          if (dp->flags & CACHE_FLAG_PENDING) {
11794             /* Still pending... It's a timeout.  Wake everybody up.  Consider it no longer
11795                pending.  Don't let it take as long to timeout. */
11796             dp->flags &= ~CACHE_FLAG_PENDING;
11797             dp->flags |= CACHE_FLAG_TIMEOUT;
11798             /* Expire after only 60 seconds now.  This is designed to help reduce backlog in heavily loaded
11799                systems without leaving it unavailable once the server comes back online */
11800             dp->expiry.tv_sec = dp->orig.tv_sec + 60;
11801             for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
11802                if (dp->waiters[x] > -1) {
11803                   if (write(dp->waiters[x], "asdf", 4) < 0) {
11804                      ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
11805                   }
11806                }
11807             }
11808          }
11809       }
11810       /* Our caller will obtain the rest */
11811       if (!old && chan)
11812          ast_channel_undefer_dtmf(chan);
11813    }
11814    return dp;  
11815 }

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

References __find_callno().

Referenced by iax2_poke_peer(), and socket_process().

01854                                                                                                                                     {
01855 
01856    return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame);
01857 }

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

References __find_callno().

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

01859                                                                                                                                            {
01860 
01861    return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame);
01862 }

static struct iax2_thread* find_idle_thread ( void   )  [static]

Definition at line 1060 of file chan_iax2.c.

References ast_atomic_fetchadd_int(), ast_calloc, ast_cond_destroy(), ast_cond_init(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_init(), ast_pthread_create_detached_background, iax2_process_thread(), IAX_THREAD_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxdynamicthreadnum, iaxmaxthreadcount, iax2_trunk_peer::list, and thread.

Referenced by __schedule_action(), and socket_read().

01061 {
01062    struct iax2_thread *thread = NULL;
01063 
01064    /* Pop the head of the idle list off */
01065    AST_LIST_LOCK(&idle_list);
01066    thread = AST_LIST_REMOVE_HEAD(&idle_list, list);
01067    AST_LIST_UNLOCK(&idle_list);
01068 
01069    /* If we popped a thread off the idle list, just return it */
01070    if (thread) {
01071       memset(&thread->ffinfo, 0, sizeof(thread->ffinfo));
01072       return thread;
01073    }
01074 
01075    /* Pop the head of the dynamic list off */
01076    AST_LIST_LOCK(&dynamic_list);
01077    thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list);
01078    AST_LIST_UNLOCK(&dynamic_list);
01079 
01080    /* If we popped a thread off the dynamic list, just return it */
01081    if (thread) {
01082       memset(&thread->ffinfo, 0, sizeof(thread->ffinfo));
01083       return thread;
01084    }
01085 
01086    /* If we can't create a new dynamic thread for any reason, return no thread at all */
01087    if (iaxdynamicthreadcount >= iaxmaxthreadcount || !(thread = ast_calloc(1, sizeof(*thread))))
01088       return NULL;
01089 
01090    /* Set default values */
01091    ast_atomic_fetchadd_int(&iaxdynamicthreadcount, 1);
01092    thread->threadnum = ast_atomic_fetchadd_int(&iaxdynamicthreadnum, 1);
01093    thread->type = IAX_THREAD_TYPE_DYNAMIC;
01094 
01095    /* Initialize lock and condition */
01096    ast_mutex_init(&thread->lock);
01097    ast_cond_init(&thread->cond, NULL);
01098 
01099    /* Create thread and send it on it's way */
01100    if (ast_pthread_create_detached_background(&thread->threadid, NULL, iax2_process_thread, thread)) {
01101       ast_cond_destroy(&thread->cond);
01102       ast_mutex_destroy(&thread->lock);
01103       ast_free(thread);
01104       return NULL;
01105    }
01106 
01107    /* this thread is not processing a full frame (since it is idle),
01108       so ensure that the field for the full frame call number is empty */
01109    memset(&thread->ffinfo, 0, sizeof(thread->ffinfo));
01110 
01111    /* Wait for the thread to be ready before returning it to the caller */
01112    while (!thread->ready_for_signal)
01113       usleep(1);
01114 
01115    return thread;
01116 }

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

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

01322 {
01323    struct iax2_peer *peer = NULL;
01324    struct iax2_peer tmp_peer = {
01325       .name = name,
01326    };
01327 
01328    peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
01329 
01330    /* Now go for realtime if applicable */
01331    if(!peer && realtime)
01332       peer = realtime_peer(name, NULL);
01333 
01334    return peer;
01335 }

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

Definition at line 4568 of file chan_iax2.c.

References iax2_trunk_peer::addr, ast_calloc, ast_debug, ast_inet_ntoa(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_init(), ast_mutex_lock(), ast_tvnow(), inaddrcmp(), iax2_trunk_peer::list, and iax2_trunk_peer::lock.

Referenced by iax2_trunk_queue(), and socket_process_meta().

04569 {
04570    struct iax2_trunk_peer *tpeer = NULL;
04571    
04572    /* Finds and locks trunk peer */
04573    AST_LIST_LOCK(&tpeers);
04574 
04575    AST_LIST_TRAVERSE(&tpeers, tpeer, list) {
04576       if (!inaddrcmp(&tpeer->addr, sin)) {
04577          ast_mutex_lock(&tpeer->lock);
04578          break;
04579       }
04580    }
04581 
04582    if (!tpeer) {
04583       if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) {
04584          ast_mutex_init(&tpeer->lock);
04585          tpeer->lastsent = 9999;
04586          memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
04587          tpeer->trunkact = ast_tvnow();
04588          ast_mutex_lock(&tpeer->lock);
04589          tpeer->sockfd = fd;
04590 #ifdef SO_NO_CHECK
04591          setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
04592 #endif
04593          ast_debug(1, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port));
04594          AST_LIST_INSERT_TAIL(&tpeers, tpeer, list);
04595       }
04596    }
04597 
04598    AST_LIST_UNLOCK(&tpeers);
04599 
04600    return tpeer;
04601 }

static struct iax2_user* find_user ( const char *  name  )  [static]

Definition at line 1349 of file chan_iax2.c.

References ao2_find(), iax2_user::name, and OBJ_POINTER.

01350 {
01351    struct iax2_user tmp_user = {
01352       .name = name,
01353    };
01354 
01355    return ao2_find(users, &tmp_user, OBJ_POINTER);
01356 }

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

Definition at line 4381 of file chan_iax2.c.

References ast_tvdiff_ms(), ast_tvnow(), and ast_tvzero().

Referenced by socket_process_meta().

04382 {
04383    long ms; /* NOT unsigned */
04384    if (ast_tvzero(iaxs[callno]->rxcore)) {
04385       /* Initialize rxcore time if appropriate */
04386       iaxs[callno]->rxcore = ast_tvnow();
04387       /* Round to nearest 20ms so traces look pretty */
04388       iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
04389    }
04390    /* Calculate difference between trunk and channel */
04391    ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore);
04392    /* Return as the sum of trunk time and the difference between trunk and real time */
04393    return ms + ts;
04394 }

static void free_context ( struct iax2_context con  )  [static]

Definition at line 10244 of file chan_iax2.c.

References ast_free, and iax2_context::next.

Referenced by build_user(), and user_destructor().

10245 {
10246    struct iax2_context *conl;
10247    while(con) {
10248       conl = con;
10249       con = con->next;
10250       ast_free(conl);
10251    }
10252 }

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

Definition at line 11938 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::capability, chan, iax2_peer::cid_name, iax2_peer::cid_num, iax2_peer::context, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iax2_peer::mailbox, peer_status(), peer_unref(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.

11939 {
11940    struct iax2_peer *peer;
11941    char *peername, *colname;
11942 
11943    peername = ast_strdupa(data);
11944 
11945    /* if our channel, return the IP address of the endpoint of current channel */
11946    if (!strcmp(peername,"CURRENTCHANNEL")) {
11947            unsigned short callno;
11948       if (chan->tech != &iax2_tech)
11949          return -1;
11950       callno = PTR_TO_CALLNO(chan->tech_pvt);   
11951       ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len);
11952       return 0;
11953    }
11954 
11955    if ((colname = strchr(peername, ',')))
11956       *colname++ = '\0';
11957    else
11958       colname = "ip";
11959 
11960    if (!(peer = find_peer(peername, 1)))
11961       return -1;
11962 
11963    if (!strcasecmp(colname, "ip")) {
11964       ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len);
11965    } else  if (!strcasecmp(colname, "status")) {
11966       peer_status(peer, buf, len); 
11967    } else  if (!strcasecmp(colname, "mailbox")) {
11968       ast_copy_string(buf, peer->mailbox, len);
11969    } else  if (!strcasecmp(colname, "context")) {
11970       ast_copy_string(buf, peer->context, len);
11971    } else  if (!strcasecmp(colname, "expire")) {
11972       snprintf(buf, len, "%d", peer->expire);
11973    } else  if (!strcasecmp(colname, "dynamic")) {
11974       ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len);
11975    } else  if (!strcasecmp(colname, "callerid_name")) {
11976       ast_copy_string(buf, peer->cid_name, len);
11977    } else  if (!strcasecmp(colname, "callerid_num")) {
11978       ast_copy_string(buf, peer->cid_num, len);
11979    } else  if (!strcasecmp(colname, "codecs")) {
11980       ast_getformatname_multiple(buf, len -1, peer->capability);
11981    } else  if (!strncasecmp(colname, "codec[", 6)) {
11982       char *codecnum, *ptr;
11983       int index = 0, codec = 0;
11984       
11985       codecnum = strchr(colname, '[');
11986       *codecnum = '\0';
11987       codecnum++;
11988       if ((ptr = strchr(codecnum, ']'))) {
11989          *ptr = '\0';
11990       }
11991       index = atoi(codecnum);
11992       if((codec = ast_codec_pref_index(&peer->prefs, index))) {
11993          ast_copy_string(buf, ast_getformatname(codec), len);
11994       }
11995    }
11996 
11997    peer_unref(peer);
11998 
11999    return 0;
12000 }

static int get_auth_methods ( const char *  value  )  [static]

Definition at line 10465 of file chan_iax2.c.

References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.

Referenced by build_peer(), and build_user().

10466 {
10467    int methods = 0;
10468    if (strstr(value, "rsa"))
10469       methods |= IAX_AUTH_RSA;
10470    if (strstr(value, "md5"))
10471       methods |= IAX_AUTH_MD5;
10472    if (strstr(value, "plaintext"))
10473       methods |= IAX_AUTH_PLAINTEXT;
10474    return methods;
10475 }

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

Definition at line 1198 of file chan_iax2.c.

References ast_true(), and IAX_ENCRYPT_AES128.

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

01199 {
01200    int e;
01201    if (!strcasecmp(s, "aes128"))
01202       e = IAX_ENCRYPT_AES128;
01203    else if (ast_true(s))
01204       e = IAX_ENCRYPT_AES128;
01205    else
01206       e = 0;
01207    return e;
01208 }

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

Definition at line 3056 of file chan_iax2.c.

References __get_from_jb(), and schedule_action.

Referenced by update_jbsched().

03057 {
03058 #ifdef SCHED_MULTITHREADED
03059    if (schedule_action(__get_from_jb, data))
03060 #endif      
03061       __get_from_jb(data);
03062    return 0;
03063 }

static char* handle_cli_iax2_provision ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 10100 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax2_provision(), iax_prov_complete_template(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

10101 {
10102    int force = 0;
10103    int res;
10104 
10105    switch (cmd) {
10106    case CLI_INIT:
10107       e->command = "iax2 provision";
10108       e->usage = 
10109          "Usage: iax2 provision <host> <template> [forced]\n"
10110          "       Provisions the given peer or IP address using a template\n"
10111          "       matching either 'template' or '*' if the template is not\n"
10112          "       found.  If 'forced' is specified, even empty provisioning\n"
10113          "       fields will be provisioned as empty fields.\n";
10114       return NULL;
10115    case CLI_GENERATE:
10116       if (a->pos == 3)
10117          return iax_prov_complete_template(a->line, a->word, a->pos, a->n);
10118       return NULL;
10119    }
10120 
10121    if (a->argc < 4)
10122       return CLI_SHOWUSAGE;
10123    if (a->argc > 4) {
10124       if (!strcasecmp(a->argv[4], "forced"))
10125          force = 1;
10126       else
10127          return CLI_SHOWUSAGE;
10128    }
10129    res = iax2_provision(NULL, -1, a->argv[2], a->argv[3], force);
10130    if (res < 0)
10131       ast_cli(a->fd, "Unable to find peer/address '%s'\n", a->argv[2]);
10132    else if (res < 1)
10133       ast_cli(a->fd, "No template (including wildcard) matching '%s'\n", a->argv[3]);
10134    else
10135       ast_cli(a->fd, "Provisioning '%s' with template '%s'%s\n", a->argv[2], a->argv[3], force ? ", forced" : "");
10136    return CLI_SUCCESS;
10137 }

static char* handle_cli_iax2_prune_realtime ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2508 of file chan_iax2.c.

References ao2_unlink(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_set_flag, ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_show_peer(), expire_registry(), ast_cli_args::fd, find_peer(), find_user(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, ast_cli_args::line, ast_cli_args::n, peer_ref(), peer_unref(), ast_cli_args::pos, prune_peers(), prune_users(), ast_cli_entry::usage, user, user_unref(), and ast_cli_args::word.

02509 {
02510    struct iax2_peer *peer = NULL;
02511    struct iax2_user *user = NULL;
02512 
02513    switch (cmd) {
02514    case CLI_INIT:
02515       e->command = "iax2 prune realtime";
02516       e->usage =
02517          "Usage: iax2 prune realtime [<peername>|all]\n"
02518          "       Prunes object(s) from the cache\n";
02519       return NULL;
02520    case CLI_GENERATE:
02521       return complete_iax2_show_peer(a->line, a->word, a->pos, a->n);
02522    }
02523    if (a->argc != 4)
02524         return CLI_SHOWUSAGE;
02525    if (!strcmp(a->argv[3], "all")) {
02526       prune_users();
02527       prune_peers();
02528       ast_cli(a->fd, "Cache flushed successfully.\n");
02529       return CLI_SUCCESS;
02530    }
02531    peer = find_peer(a->argv[3], 0);
02532    user = find_user(a->argv[3]);
02533    if (peer || user) {
02534       if (peer) {
02535          if (ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
02536             ast_set_flag(peer, IAX_RTAUTOCLEAR);
02537             expire_registry(peer_ref(peer));
02538             ast_cli(a->fd, "Peer %s was removed from the cache.\n", a->argv[3]);
02539          } else {
02540             ast_cli(a->fd, "Peer %s is not eligible for this operation.\n", a->argv[3]);
02541          }
02542          peer_unref(peer);
02543       }
02544       if (user) {
02545          if (ast_test_flag(user, IAX_RTCACHEFRIENDS)) {
02546             ast_set_flag(user, IAX_RTAUTOCLEAR);
02547             ast_cli(a->fd, "User %s was removed from the cache.\n", a->argv[3]);
02548          } else {
02549             ast_cli(a->fd, "User %s is not eligible for this operation.\n", a->argv[3]);
02550          }
02551          ao2_unlink(users,user);
02552          user_unref(user);
02553       }
02554    } else {
02555       ast_cli(a->fd, "%s was not found in the cache.\n", a->argv[3]);
02556    }
02557 
02558    return CLI_SUCCESS;
02559 }

static char* handle_cli_iax2_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 11593 of file chan_iax2.c.

References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, reload_config(), and ast_cli_entry::usage.

11594 {
11595    switch (cmd) {
11596    case CLI_INIT:
11597       e->command = "iax2 reload";
11598       e->usage =
11599          "Usage: iax2 reload\n"
11600          "       Reloads IAX configuration from iax.conf\n";
11601       return NULL;
11602    case CLI_GENERATE:
11603       return NULL;
11604    }
11605 
11606    reload_config();
11607 
11608    return CLI_SUCCESS;
11609 }

static char* handle_cli_iax2_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5776 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

05777 {
05778    switch (cmd) {
05779    case CLI_INIT:
05780       e->command = "iax2 set debug {on|off}";
05781       e->usage =
05782          "Usage: iax2 set debug {on|off}\n"
05783          "       Enables/Disables dumping of IAX packets for debugging purposes.\n";
05784       return NULL;
05785    case CLI_GENERATE:
05786       return NULL;
05787    }
05788 
05789    if (a->argc != e->args)
05790       return CLI_SHOWUSAGE;
05791 
05792    if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
05793       iaxdebug = 1;
05794       ast_cli(a->fd, "IAX2 Debugging Enabled\n");
05795    } else {
05796       iaxdebug = 0;
05797       ast_cli(a->fd, "IAX2 Debugging Disabled\n");
05798    }
05799    return CLI_SUCCESS;
05800 }

static char* handle_cli_iax2_set_debug_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5752 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

05753 {
05754    switch (cmd) {
05755    case CLI_INIT:
05756       e->command = "iax2 set debug [off]";
05757       e->usage =
05758          "Usage: iax2 set debug [off]\n"
05759          "       Enables/Disables dumping of IAX packets for debugging purposes.\n";
05760       return NULL;
05761    case CLI_GENERATE:
05762       return NULL;
05763    }
05764    if (a->argc < 3 || a->argc > 4)
05765       return CLI_SHOWUSAGE;
05766    if (a->argc == 3) {
05767       iaxdebug = 1;
05768       ast_cli(a->fd, "IAX2 Debugging Enabled\n");
05769    } else {
05770       iaxdebug = 0;
05771       ast_cli(a->fd, "IAX2 Debugging Disabled\n");
05772    }
05773    return CLI_SUCCESS;
05774 }

static char* handle_cli_iax2_set_debug_jb ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5881 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), and ast_cli_entry::usage.

05882 {
05883    switch (cmd) {
05884    case CLI_INIT:
05885       e->command = "iax2 set debug jb {on|off}";
05886       e->usage =
05887          "Usage: iax2 set debug jb {on|off}\n"
05888          "       Enables/Disables jitterbuffer debugging information\n";
05889       return NULL;
05890    case CLI_GENERATE:
05891       return NULL;
05892    }
05893 
05894    if (a->argc != e->args)
05895       return CLI_SHOWUSAGE;
05896    
05897    if (!strncasecmp(a->argv[e->args -1], "on", 2)) {
05898       jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
05899       ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Enabled\n");
05900    } else {
05901       jb_setoutput(jb_error_output, jb_warning_output, NULL);
05902       ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Disabled\n");
05903    }
05904    return CLI_SUCCESS;
05905 }

static char* handle_cli_iax2_set_debug_jb_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5855 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), and ast_cli_entry::usage.

05856 {
05857    switch (cmd) {
05858    case CLI_INIT:
05859       e->command = "iax2 set debug jb [off]";
05860       e->usage =
05861          "Usage: iax2 set debug jb [off]\n"
05862          "       Enables/Disables jitterbuffer debugging information\n";
05863       return NULL;
05864    case CLI_GENERATE:
05865       return NULL;
05866    }
05867 
05868    if (a->argc < 4 || a->argc > 5)
05869       return CLI_SHOWUSAGE;
05870    
05871    if (a->argc == 4) {
05872       jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output);
05873       ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Enabled\n");
05874    } else {
05875       jb_setoutput(jb_error_output, jb_warning_output, NULL);
05876       ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Disabled\n");
05877    }
05878    return CLI_SUCCESS;
05879 }

static char* handle_cli_iax2_set_debug_trunk ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5829 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

05830 {
05831    switch (cmd) {
05832    case CLI_INIT:
05833       e->command = "iax2 set debug trunk {on|off}";
05834       e->usage =
05835          "Usage: iax2 set debug trunk {on|off}\n"
05836          "       Enables/Disables debugging of IAX trunking\n";
05837       return NULL;
05838    case CLI_GENERATE:
05839       return NULL;
05840    }
05841 
05842    if (a->argc != e->args)
05843       return CLI_SHOWUSAGE;
05844 
05845    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
05846       iaxtrunkdebug = 1;
05847       ast_cli(a->fd, "IAX2 Trunk Debugging Enabled\n");
05848    } else {
05849       iaxtrunkdebug = 0;
05850       ast_cli(a->fd, "IAX2 Trunk Debugging Disabled\n");
05851    }
05852    return CLI_SUCCESS;
05853 }

static char* handle_cli_iax2_set_debug_trunk_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5803 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

05804 {
05805    switch (cmd) {
05806    case CLI_INIT:
05807       e->command = "iax2 set debug trunk [off]";
05808       e->usage =
05809          "Usage: iax2 set debug trunk [off]\n"
05810          "       Enables/Disables debugging of IAX trunking\n";
05811       return NULL;
05812    case CLI_GENERATE:
05813       return NULL;
05814    }
05815 
05816    if (a->argc < 4 || a->argc > 5)
05817       return CLI_SHOWUSAGE;
05818 
05819    if (a->argc == 4) {
05820       iaxtrunkdebug = 1;
05821       ast_cli(a->fd, "IAX2 Trunk Debugging Enabled\n");
05822    } else {
05823       iaxtrunkdebug = 0;
05824       ast_cli(a->fd, "IAX2 Trunk Debugging Disabled\n");
05825    }
05826    return CLI_SUCCESS;
05827 }

static char* handle_cli_iax2_set_mtu ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Set trunk MTU from CLI.

Definition at line 2815 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, MAX_TRUNK_MTU, and ast_cli_entry::usage.

02816 {
02817    int mtuv;
02818 
02819    switch (cmd) {
02820    case CLI_INIT:
02821       e->command = "iax2 set mtu";
02822       e->usage =
02823          "Usage: iax2 set mtu <value>\n"
02824          "       Set the system-wide IAX IP mtu to <value> bytes net or\n"
02825          "       zero to disable. Disabling means that the operating system\n"
02826          "       must handle fragmentation of UDP packets when the IAX2 trunk\n"
02827          "       packet exceeds the UDP payload size. This is substantially\n"
02828          "       below the IP mtu. Try 1240 on ethernets. Must be 172 or\n"
02829          "       greater for G.711 samples.\n";
02830       return NULL;
02831    case CLI_GENERATE:
02832       return NULL;
02833    }
02834 
02835    if (a->argc != 4)
02836       return CLI_SHOWUSAGE; 
02837    if (strncasecmp(a->argv[3], "default", strlen(a->argv[3])) == 0)
02838       mtuv = MAX_TRUNK_MTU;
02839    else
02840       mtuv = atoi(a->argv[3]);
02841 
02842    if (mtuv == 0) {
02843       ast_cli(a->fd, "Trunk MTU control disabled (mtu was %d)\n", global_max_trunk_mtu); 
02844       global_max_trunk_mtu = 0; 
02845       return CLI_SUCCESS; 
02846    }
02847    if (mtuv < 172 || mtuv > 4000) {
02848       ast_cli(a->fd, "Trunk MTU must be between 172 and 4000\n"); 
02849       return CLI_SHOWUSAGE; 
02850    }
02851    ast_cli(a->fd, "Trunk MTU changed from %d to %d\n", global_max_trunk_mtu, mtuv); 
02852    global_max_trunk_mtu = mtuv; 
02853    return CLI_SUCCESS;
02854 }

static char* handle_cli_iax2_show_cache ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2856 of file chan_iax2.c.

References ARRAY_LEN, ast_cli(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_tvnow(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, CACHE_FLAG_TRANSMITTED, CACHE_FLAG_UNKNOWN, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, iax2_dpcache::expiry, iax2_dpcache::exten, ast_cli_args::fd, iax2_dpcache::flags, iax2_dpcache::peercontext, s, ast_cli_entry::usage, and iax2_dpcache::waiters.

02857 {
02858    struct iax2_dpcache *dp = NULL;
02859    char tmp[1024], *pc = NULL;
02860    int s, x, y;
02861    struct timeval tv = ast_tvnow();
02862 
02863    switch (cmd) {
02864    case CLI_INIT:
02865       e->command = "iax2 show cache";
02866       e->usage =
02867          "Usage: iax2 show cache\n"
02868          "       Display currently cached IAX Dialplan results.\n";
02869       return NULL;
02870    case CLI_GENERATE:
02871       return NULL;
02872    }
02873 
02874    AST_LIST_LOCK(&dpcache);
02875 
02876    ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
02877 
02878    AST_LIST_TRAVERSE(&dpcache, dp, cache_list) {
02879       s = dp->expiry.tv_sec - tv.tv_sec;
02880       tmp[0] = '\0';
02881       if (dp->flags & CACHE_FLAG_EXISTS)
02882          strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1);
02883       if (dp->flags & CACHE_FLAG_NONEXISTENT)
02884          strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1);
02885       if (dp->flags & CACHE_FLAG_CANEXIST)
02886          strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1);
02887       if (dp->flags & CACHE_FLAG_PENDING)
02888          strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1);
02889       if (dp->flags & CACHE_FLAG_TIMEOUT)
02890          strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1);
02891       if (dp->flags & CACHE_FLAG_TRANSMITTED)
02892          strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1);
02893       if (dp->flags & CACHE_FLAG_MATCHMORE)
02894          strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1);
02895       if (dp->flags & CACHE_FLAG_UNKNOWN)
02896          strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1);
02897       /* Trim trailing pipe */
02898       if (!ast_strlen_zero(tmp)) {
02899          tmp[strlen(tmp) - 1] = '\0';
02900       } else {
02901          ast_copy_string(tmp, "(none)", sizeof(tmp));
02902       }
02903       y = 0;
02904       pc = strchr(dp->peercontext, '@');
02905       if (!pc) {
02906          pc = dp->peercontext;
02907       } else {
02908          pc++;
02909       }
02910       for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
02911          if (dp->waiters[x] > -1)
02912             y++;
02913       }
02914       if (s > 0) {
02915          ast_cli(a->fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
02916       } else {
02917          ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
02918       }
02919    }
02920 
02921    AST_LIST_LOCK(&dpcache);
02922 
02923    return CLI_SUCCESS;
02924 }

static char* handle_cli_iax2_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5579 of file chan_iax2.c.

References ast_cli_args::argc, ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, jb_info::current, ast_cli_args::fd, FORMAT, FORMAT2, iax_frame_subclass2str(), IAX_USEJITTERBUF, jb_getinfo(), jb_info::jitter, MARK_IAX_SUBCLASS_TX, jb_info::min, S_OR, and ast_cli_entry::usage.

05580 {
05581 #define FORMAT2 "%-20.20s  %-15.15s  %-10.10s  %-11.11s  %-11.11s  %-7.7s  %-6.6s  %-6.6s  %s  %s  %9s\n"
05582 #define FORMAT  "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  %-5.5dms  %-4.4dms  %-4.4dms  %-6.6s  %s%s  %3s%s\n"
05583 #define FORMATB "%-20.20s  %-15.15s  %-10.10s  %5.5d/%5.5d  %5.5d/%5.5d  [Native Bridged to ID=%5.5d]\n"
05584    int x;
05585    int numchans = 0;
05586    char first_message[10] = { 0, };
05587    char last_message[10] = { 0, };
05588 
05589    switch (cmd) {
05590    case CLI_INIT:
05591       e->command = "iax2 show channels";
05592       e->usage =
05593          "Usage: iax2 show channels\n"
05594          "       Lists all currently active IAX channels.\n";
05595       return NULL;
05596    case CLI_GENERATE:
05597       return NULL;
05598    }
05599 
05600    if (a->argc != 3)
05601       return CLI_SHOWUSAGE;
05602    ast_cli(a->fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format", "FirstMsg", "LastMsg");
05603    for (x = 0; x < ARRAY_LEN(iaxs); x++) {
05604       ast_mutex_lock(&iaxsl[x]);
05605       if (iaxs[x]) {
05606          int lag, jitter, localdelay;
05607          jb_info jbinfo;
05608          if (ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) {
05609             jb_getinfo(iaxs[x]->jb, &jbinfo);
05610             jitter = jbinfo.jitter;
05611             localdelay = jbinfo.current - jbinfo.min;
05612          } else {
05613             jitter = -1;
05614             localdelay = 0;
05615          }
05616 
05617          iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message));
05618          iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message));
05619          lag = iaxs[x]->remote_rr.delay;
05620          ast_cli(a->fd, FORMAT,
05621             iaxs[x]->owner ? iaxs[x]->owner->name : "(None)",
05622             ast_inet_ntoa(iaxs[x]->addr.sin_addr),
05623             S_OR(iaxs[x]->username, "(None)"),
05624             iaxs[x]->callno, iaxs[x]->peercallno,
05625             iaxs[x]->oseqno, iaxs[x]->iseqno,
05626             lag,
05627             jitter,
05628             localdelay,
05629             ast_getformatname(iaxs[x]->voiceformat),
05630             (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
05631             first_message,
05632             (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:",
05633             last_message);
05634          numchans++;
05635       }
05636       ast_mutex_unlock(&iaxsl[x]);
05637    }
05638    ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
05639    return CLI_SUCCESS;
05640 #undef FORMAT
05641 #undef FORMAT2
05642 #undef FORMATB
05643 }

static char* handle_cli_iax2_show_firmware ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5430 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, ast_cli_args::fd, iax_firmware::fwh, iax_firmware::list, ast_cli_entry::usage, and ast_iax2_firmware_header::version.

05431 {
05432    struct iax_firmware *cur = NULL;
05433 
05434    switch (cmd) {
05435    case CLI_INIT:
05436       e->command = "iax2 show firmware";
05437       e->usage =
05438          "Usage: iax2 show firmware\n"
05439          "       Lists all known IAX firmware images.\n";
05440       return NULL;
05441    case CLI_GENERATE:
05442       return NULL;
05443    }
05444 
05445    if (a->argc != 3 && a->argc != 4)
05446       return CLI_SHOWUSAGE;
05447 
05448    ast_cli(a->fd, "%-15.15s  %-15.15s %-15.15s\n", "Device", "Version", "Size");
05449    AST_LIST_LOCK(&firmwares);
05450    AST_LIST_TRAVERSE(&firmwares, cur, list) {
05451       if ((a->argc == 3) || (!strcasecmp(a->argv[3], (char *) cur->fwh->devname)))  {
05452          ast_cli(a->fd, "%-15.15s  %-15d %-15d\n", cur->fwh->devname, 
05453             ntohs(cur->fwh->version), (int)ntohl(cur->fwh->datalen));
05454       }
05455    }
05456    AST_LIST_UNLOCK(&firmwares);
05457 
05458    return CLI_SUCCESS;
05459 }

static char* handle_cli_iax2_show_netstats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5729 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli(), ast_cli_netstats(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

05730 {
05731    int numchans = 0;
05732 
05733    switch (cmd) {
05734    case CLI_INIT:
05735       e->command = "iax2 show netstats";
05736       e->usage =
05737          "Usage: iax2 show netstats\n"
05738          "       Lists network status for all currently active IAX channels.\n";
05739       return NULL;
05740    case CLI_GENERATE:
05741       return NULL;
05742    }
05743    if (a->argc != 3)
05744       return CLI_SHOWUSAGE;
05745    ast_cli(a->fd, "                           -------- LOCAL ---------------------  -------- REMOTE --------------------\n");
05746    ast_cli(a->fd, "Channel               RTT  Jit  Del  Lost   %%  Drop  OOO  Kpkts  Jit  Del  Lost   %%  Drop  OOO  Kpkts FirstMsg    LastMsg\n");
05747    numchans = ast_cli_netstats(NULL, a->fd, 1);
05748    ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : "");
05749    return CLI_SUCCESS;
05750 }

static char* handle_cli_iax2_show_peer ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Show one peer in detail.

Definition at line 2675 of file chan_iax2.c.

References iax2_peer::addr, ast_cli_args::argc, ast_cli_args::argv, 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, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_show_peer(), iax2_peer::context, iax2_peer::defaddr, iax2_peer::expire, ast_cli_args::fd, find_peer(), iax2_peer::ha, IAX_DYNAMIC, IAX_TRUNK, ast_cli_args::line, iax2_peer::mailbox, ast_cli_args::n, iax2_peer::name, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, ast_cli_args::pos, iax2_peer::prefs, iax2_peer::secret, iax2_peer::smoothing, status, ast_cli_entry::usage, iax2_peer::username, and ast_cli_args::word.

02676 {
02677    char status[30];
02678    char cbuf[256];
02679    struct iax2_peer *peer;
02680    char codec_buf[512];
02681    int x = 0, codec = 0, load_realtime = 0;
02682 
02683    switch (cmd) {
02684    case CLI_INIT:
02685       e->command = "iax2 show peer";
02686       e->usage =
02687          "Usage: iax2 show peer <name>\n"
02688          "       Display details on specific IAX peer\n";
02689       return NULL;
02690    case CLI_GENERATE:
02691       return complete_iax2_show_peer(a->line, a->word, a->pos, a->n);
02692    }
02693 
02694    if (a->argc < 4)
02695       return CLI_SHOWUSAGE;
02696 
02697    load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? 1 : 0;
02698 
02699    peer = find_peer(a->argv[3], load_realtime);
02700    if (peer) {
02701       ast_cli(a->fd, "\n\n");
02702       ast_cli(a->fd, "  * Name       : %s\n", peer->name);
02703       ast_cli(a->fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret) ? "<Not set>" : "<Set>");
02704       ast_cli(a->fd, "  Context      : %s\n", peer->context);
02705       ast_cli(a->fd, "  Mailbox      : %s\n", peer->mailbox);
02706       ast_cli(a->fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No");
02707       ast_cli(a->fd, "  Trunk        : %s\n", ast_test_flag(peer, IAX_TRUNK) ? "Yes" : "No");
02708       ast_cli(a->fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
02709       ast_cli(a->fd, "  Expire       : %d\n", peer->expire);
02710       ast_cli(a->fd, "  ACL          : %s\n", (peer->ha ? "Yes" : "No"));
02711       ast_cli(a->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));
02712       ast_cli(a->fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
02713       ast_cli(a->fd, "  Username     : %s\n", peer->username);
02714       ast_cli(a->fd, "  Codecs       : ");
02715       ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
02716       ast_cli(a->fd, "%s\n", codec_buf);
02717 
02718       ast_cli(a->fd, "  Codec Order  : (");
02719       for(x = 0; x < 32 ; x++) {
02720          codec = ast_codec_pref_index(&peer->prefs,x);
02721          if(!codec)
02722             break;
02723          ast_cli(a->fd, "%s", ast_getformatname(codec));
02724          if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1))
02725             ast_cli(a->fd, "|");
02726       }
02727 
02728       if (!x)
02729          ast_cli(a->fd, "none");
02730       ast_cli(a->fd, ")\n");
02731 
02732       ast_cli(a->fd, "  Status       : ");
02733       peer_status(peer, status, sizeof(status));   
02734       ast_cli(a->fd, "%s\n",status);
02735       ast_cli(a->fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
02736       ast_cli(a->fd, "\n");
02737       peer_unref(peer);
02738    } else {
02739       ast_cli(a->fd, "Peer %s not found.\n", a->argv[3]);
02740       ast_cli(a->fd, "\n");
02741    }
02742 
02743    return CLI_SUCCESS;
02744 }

static char* handle_cli_iax2_show_peers ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5398 of file chan_iax2.c.

References __iax2_show_peers(), ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and ast_cli_entry::usage.

05399 {
05400    switch (cmd) {
05401    case CLI_INIT:
05402       e->command = "iax2 show peers";
05403       e->usage =
05404          "Usage: iax2 show peers [registered] [like <pattern>]\n"
05405          "       Lists all known IAX2 peers.\n"
05406          "       Optional 'registered' argument lists only peers with known addresses.\n"
05407          "       Optional regular expression pattern is used to filter the peer list.\n";
05408       return NULL;
05409    case CLI_GENERATE:
05410       return NULL;
05411    }
05412 
05413    switch (__iax2_show_peers(0, a->fd, NULL, a->argc, a->argv)) {
05414    case RESULT_SHOWUSAGE:
05415       return CLI_SHOWUSAGE;
05416    case RESULT_FAILURE:
05417       return CLI_FAILURE;
05418    default:
05419       return CLI_SUCCESS;
05420    }
05421 }

static char* handle_cli_iax2_show_registry ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5538 of file chan_iax2.c.

References iax2_registry::addr, ast_cli_args::argc, ast_cli(), ast_copy_string(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, iax2_registry::dnsmgr, iax2_registry::entry, ast_cli_args::fd, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), iax2_registry::us, ast_cli_entry::usage, and iax2_registry::username.

05539 {
05540 #define FORMAT2 "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8.8s  %s\n"
05541 #define FORMAT  "%-20.20s  %-6.6s  %-10.10s  %-20.20s %8d  %s\n"
05542    struct iax2_registry *reg = NULL;
05543    char host[80];
05544    char perceived[80];
05545    int counter = 0;
05546 
05547    switch (cmd) {
05548    case CLI_INIT:
05549       e->command = "iax2 show registry";
05550       e->usage =
05551          "Usage: iax2 show registry\n"
05552          "       Lists all registration requests and status.\n";
05553       return NULL;
05554    case CLI_GENERATE:
05555       return NULL;
05556    }
05557    if (a->argc != 3)
05558       return CLI_SHOWUSAGE;
05559    ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State");
05560    AST_LIST_LOCK(&registrations);
05561    AST_LIST_TRAVERSE(&registrations, reg, entry) {
05562       snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port));
05563       if (reg->us.sin_addr.s_addr) 
05564          snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
05565       else
05566          ast_copy_string(perceived, "<Unregistered>", sizeof(perceived));
05567       ast_cli(a->fd, FORMAT, host, 
05568                (reg->dnsmgr) ? "Y" : "N", 
05569                reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
05570       counter++;
05571    }
05572    AST_LIST_UNLOCK(&registrations);
05573    ast_cli(a->fd, "%d IAX2 registrations.\n", counter);
05574    return CLI_SUCCESS;
05575 #undef FORMAT
05576 #undef FORMAT2
05577 }

static char* handle_cli_iax2_show_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2771 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax_frame::final, iax_get_frames(), iax_get_iframes(), iax_get_oframes(), iax2_trunk_peer::list, iax_frame::retries, and ast_cli_entry::usage.

02772 {
02773    struct iax_frame *cur;
02774    int cnt = 0, dead = 0, final = 0;
02775 
02776    switch (cmd) {
02777    case CLI_INIT:
02778       e->command = "iax2 show stats";
02779       e->usage =
02780          "Usage: iax2 show stats\n"
02781          "       Display statistics on IAX channel driver.\n";
02782       return NULL;
02783    case CLI_GENERATE:
02784       return NULL;
02785    }
02786 
02787    if (a->argc != 3)
02788       return CLI_SHOWUSAGE;
02789 
02790    AST_LIST_LOCK(&frame_queue);
02791    AST_LIST_TRAVERSE(&frame_queue, cur, list) {
02792       if (cur->retries < 0)
02793          dead++;
02794       if (cur->final)
02795          final++;
02796       cnt++;
02797    }
02798    AST_LIST_UNLOCK(&frame_queue);
02799 
02800    ast_cli(a->fd, "    IAX Statistics\n");
02801    ast_cli(a->fd, "---------------------\n");
02802    ast_cli(a->fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes());
02803    ast_cli(a->fd, "%d timed and %d untimed transmits; MTU %d/%d/%d\n", trunk_timed, trunk_untimed,
02804       trunk_maxmtu, trunk_nmaxmtu, global_max_trunk_mtu);
02805    ast_cli(a->fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt);
02806 
02807    trunk_timed = trunk_untimed = 0;
02808    if (trunk_maxmtu > trunk_nmaxmtu)
02809       trunk_nmaxmtu = trunk_maxmtu;
02810 
02811    return CLI_SUCCESS;
02812 }

static char* handle_cli_iax2_show_threads ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5262 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, IAX_THREAD_TYPE_DYNAMIC, iaxthreadcount, iax2_thread::list, thread, and ast_cli_entry::usage.

05263 {
05264    struct iax2_thread *thread = NULL;
05265    time_t t;
05266    int threadcount = 0, dynamiccount = 0;
05267    char type;
05268 
05269    switch (cmd) {
05270    case CLI_INIT:
05271       e->command = "iax2 show threads";
05272       e->usage =
05273          "Usage: iax2 show threads\n"
05274          "       Lists status of IAX helper threads\n";
05275       return NULL;
05276    case CLI_GENERATE:
05277       return NULL;
05278    }
05279    if (a->argc != 3)
05280       return CLI_SHOWUSAGE;
05281       
05282    ast_cli(a->fd, "IAX2 Thread Information\n");
05283    time(&t);
05284    ast_cli(a->fd, "Idle Threads:\n");
05285    AST_LIST_LOCK(&idle_list);
05286    AST_LIST_TRAVERSE(&idle_list, thread, list) {
05287 #ifdef DEBUG_SCHED_MULTITHREAD
05288       ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n", 
05289          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
05290 #else
05291       ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n", 
05292          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
05293 #endif
05294       threadcount++;
05295    }
05296    AST_LIST_UNLOCK(&idle_list);
05297    ast_cli(a->fd, "Active Threads:\n");
05298    AST_LIST_LOCK(&active_list);
05299    AST_LIST_TRAVERSE(&active_list, thread, list) {
05300       if (thread->type == IAX_THREAD_TYPE_DYNAMIC)
05301          type = 'D';
05302       else
05303          type = 'P';
05304 #ifdef DEBUG_SCHED_MULTITHREAD
05305       ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d, func='%s'\n", 
05306          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
05307 #else
05308       ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 
05309          type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
05310 #endif
05311       threadcount++;
05312    }
05313    AST_LIST_UNLOCK(&active_list);
05314    ast_cli(a->fd, "Dynamic Threads:\n");
05315    AST_LIST_LOCK(&dynamic_list);
05316    AST_LIST_TRAVERSE(&dynamic_list, thread, list) {
05317 #ifdef DEBUG_SCHED_MULTITHREAD
05318       ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n",
05319          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc);
05320 #else
05321       ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n",
05322          thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions);
05323 #endif
05324       dynamiccount++;
05325    }
05326    AST_LIST_UNLOCK(&dynamic_list);
05327    ast_cli(a->fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount);
05328    return CLI_SUCCESS;
05329 }

static char* handle_cli_iax2_show_users ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5061 of file chan_iax2.c.

References ao2_iterator_init(), ao2_iterator_next(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_strlen_zero(), ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, FORMAT2, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, ast_cli_entry::usage, user, and user_unref().

05062 {
05063    regex_t regexbuf;
05064    int havepattern = 0;
05065 
05066 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
05067 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
05068 
05069    struct iax2_user *user = NULL;
05070    char auth[90];
05071    char *pstr = "";
05072    struct ao2_iterator i;
05073 
05074    switch (cmd) {
05075    case CLI_INIT:
05076       e->command = "iax2 show users [like]";
05077       e->usage =
05078          "Usage: iax2 show users [like <pattern>]\n"
05079          "       Lists all known IAX2 users.\n"
05080          "       Optional regular expression pattern is used to filter the user list.\n";
05081       return NULL;
05082    case CLI_GENERATE:
05083       return NULL;
05084    }
05085 
05086    switch (a->argc) {
05087    case 5:
05088       if (!strcasecmp(a->argv[3], "like")) {
05089          if (regcomp(&regexbuf, a->argv[4], REG_EXTENDED | REG_NOSUB))
05090             return CLI_SHOWUSAGE;
05091          havepattern = 1;
05092       } else
05093          return CLI_SHOWUSAGE;
05094    case 3:
05095       break;
05096    default:
05097       return CLI_SHOWUSAGE;
05098    }
05099 
05100    ast_cli(a->fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
05101    i = ao2_iterator_init(users, 0);
05102    for (user = ao2_iterator_next(&i); user; 
05103       user_unref(user), user = ao2_iterator_next(&i)) {
05104       if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
05105          continue;
05106       
05107       if (!ast_strlen_zero(user->secret)) {
05108          ast_copy_string(auth,user->secret, sizeof(auth));
05109       } else if (!ast_strlen_zero(user->inkeys)) {
05110          snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
05111       } else
05112          ast_copy_string(auth, "-no secret-", sizeof(auth));
05113       
05114       if(ast_test_flag(user,IAX_CODEC_NOCAP))
05115          pstr = "REQ Only";
05116       else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
05117          pstr = "Disabled";
05118       else
05119          pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
05120       
05121       ast_cli(a->fd, FORMAT2, user->name, auth, user->authmethods, 
05122          user->contexts ? user->contexts->context : context,
05123          user->ha ? "Yes" : "No", pstr);
05124    }
05125 
05126    if (havepattern)
05127       regfree(&regexbuf);
05128 
05129    return CLI_SUCCESS;
05130 #undef FORMAT
05131 #undef FORMAT2
05132 }

static char* handle_cli_iax2_test_losspct ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2561 of file chan_iax2.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

02562 {
02563    switch (cmd) {
02564    case CLI_INIT:
02565       e->command = "iax2 test losspct";
02566       e->usage =
02567          "Usage: iax2 test losspct <percentage>\n"
02568          "       For testing, throws away <percentage> percent of incoming packets\n";
02569       return NULL;
02570    case CLI_GENERATE:
02571       return NULL;
02572    }
02573    if (a->argc != 4)
02574       return CLI_SHOWUSAGE;
02575 
02576    test_losspct = atoi(a->argv[3]);
02577 
02578    return CLI_SUCCESS;
02579 }

static char* handle_cli_iax2_unregister ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5331 of file chan_iax2.c.

References ao2_find(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_unregister(), iax2_peer::expire, expire_registry(), ast_cli_args::fd, find_peer(), ast_cli_args::line, ast_cli_args::n, iax2_peer::name, OBJ_POINTER, peer_ref(), peer_unref(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

05332 {
05333    struct iax2_peer *p;
05334 
05335    switch (cmd) {
05336    case CLI_INIT:
05337       e->command = "iax2 unregister";
05338       e->usage =
05339          "Usage: iax2 unregister <peername>\n"
05340          "       Unregister (force expiration) an IAX2 peer from the registry.\n";
05341       return NULL;
05342    case CLI_GENERATE:
05343       return complete_iax2_unregister(a->line, a->word, a->pos, a->n);
05344    }
05345 
05346    if (a->argc != 3)
05347       return CLI_SHOWUSAGE;
05348 
05349    p = find_peer(a->argv[2], 1);
05350    if (p) {
05351       if (p->expire > 0) {
05352          struct iax2_peer tmp_peer = {
05353             .name = a->argv[2],
05354          };
05355          struct iax2_peer *peer;
05356 
05357          peer = ao2_find(peers, &tmp_peer, OBJ_POINTER);
05358          if (peer) {
05359             expire_registry(peer_ref(peer)); /* will release its own reference when done */
05360             peer_unref(peer); /* ref from ao2_find() */
05361             ast_cli(a->fd, "Peer %s unregistered\n", a->argv[2]);
05362          } else {
05363             ast_cli(a->fd, "Peer %s not found\n", a->argv[2]);
05364          }
05365       } else {
05366          ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]);
05367       }
05368    } else {
05369       ast_cli(a->fd, "Peer unknown: %s. Not unregistered\n", a->argv[2]);
05370    }
05371    return CLI_SUCCESS;
05372 }

static void handle_deferred_full_frames ( struct iax2_thread thread  )  [static]

Handle any deferred full frames for this thread.

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

07904 {
07905    struct iax2_pkt_buf *pkt_buf;
07906 
07907    ast_mutex_lock(&thread->lock);
07908 
07909    while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) {
07910       ast_mutex_unlock(&thread->lock);
07911 
07912       thread->buf = pkt_buf->buf;
07913       thread->buf_len = pkt_buf->len;
07914       thread->buf_size = pkt_buf->len + 1;
07915       
07916       socket_process(thread);
07917 
07918       thread->buf = NULL;
07919       ast_free(pkt_buf);
07920 
07921       ast_mutex_lock(&thread->lock);
07922    }
07923 
07924    ast_mutex_unlock(&thread->lock);
07925 }

static int handle_error ( void   )  [static]

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

02229 {
02230    /* XXX Ideally we should figure out why an error occurred and then abort those
02231       rather than continuing to try.  Unfortunately, the published interface does
02232       not seem to work XXX */
02233 #if 0
02234    struct sockaddr_in *sin;
02235    int res;
02236    struct msghdr m;
02237    struct sock_extended_err e;
02238    m.msg_name = NULL;
02239    m.msg_namelen = 0;
02240    m.msg_iov = NULL;
02241    m.msg_control = &e;
02242    m.msg_controllen = sizeof(e);
02243    m.msg_flags = 0;
02244    res = recvmsg(netsocket, &m, MSG_ERRQUEUE);
02245    if (res < 0)
02246       ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno));
02247    else {
02248       if (m.msg_controllen) {
02249          sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e);
02250          if (sin) 
02251             ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr));
02252          else
02253             ast_log(LOG_WARNING, "No address detected??\n");
02254       } else {
02255          ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno));
02256       }
02257    }
02258 #endif
02259    return 0;
02260 }

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

Acknowledgment received for OUR registration.

Definition at line 6869 of file chan_iax2.c.

References iax2_registry::addr, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_verb, EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_replace(), ies, inaddrcmp(), LOG_WARNING, manager_event, iax2_registry::messages, iax2_registry::refresh, REG_STATE_REGISTERED, iax2_registry::regstate, sched, and iax2_registry::us.

Referenced by socket_process().

06870 {
06871    struct iax2_registry *reg;
06872    /* Start pessimistic */
06873    char peer[256] = "";
06874    char msgstatus[60];
06875    int refresh = 60;
06876    char ourip[256] = "<Unspecified>";
06877    struct sockaddr_in oldus;
06878    struct sockaddr_in us;
06879    int oldmsgs;
06880 
06881    memset(&us, 0, sizeof(us));
06882    if (ies->apparent_addr)
06883       memmove(&us, ies->apparent_addr, sizeof(us));
06884    if (ies->username)
06885       ast_copy_string(peer, ies->username, sizeof(peer));
06886    if (ies->refresh)
06887       refresh = ies->refresh;
06888    if (ies->calling_number) {
06889       /* We don't do anything with it really, but maybe we should */
06890    }
06891    reg = iaxs[callno]->reg;
06892    if (!reg) {
06893       ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer);
06894       return -1;
06895    }
06896    memcpy(&oldus, &reg->us, sizeof(oldus));
06897    oldmsgs = reg->messages;
06898    if (inaddrcmp(&reg->addr, sin)) {
06899       ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr));
06900       return -1;
06901    }
06902    memcpy(&reg->us, &us, sizeof(reg->us));
06903    if (ies->msgcount >= 0)
06904       reg->messages = ies->msgcount & 0xffff;      /* only low 16 bits are used in the transmission of the IE */
06905    /* always refresh the registration at the interval requested by the server
06906       we are registering to
06907    */
06908    reg->refresh = refresh;
06909    reg->expire = iax2_sched_replace(reg->expire, sched, 
06910       (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
06911    if (inaddrcmp(&oldus, &reg->us) || (reg->messages != oldmsgs)) {
06912          if (reg->messages > 255)
06913             snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8);
06914          else if (reg->messages > 1)
06915             snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages);
06916          else if (reg->messages > 0)
06917             ast_copy_string(msgstatus, " with 1 new message waiting\n", sizeof(msgstatus));
06918          else
06919             ast_copy_string(msgstatus, " with no messages waiting\n", sizeof(msgstatus));
06920          snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port));
06921       ast_verb(3, "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus);
06922       manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr));
06923    }
06924    reg->regstate = REG_STATE_REGISTERED;
06925    return 0;
06926 }

static void iax2_ami_channelupdate ( struct chan_iax2_pvt pvt  )  [static]

Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers.

Definition at line 988 of file chan_iax2.c.

References chan_iax2_pvt::callno, EVENT_FLAG_SYSTEM, manager_event, ast_channel::name, chan_iax2_pvt::owner, chan_iax2_pvt::peer, and chan_iax2_pvt::peercallno.

Referenced by ast_iax2_new(), and iax2_answer().

00989 {
00990    manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
00991       "Channel: %s\r\nChanneltype: IAX2\r\nIAX2-callno-local: %d\r\nIAX2-callno-remote: %d\r\nIAX2-peer: %s\r\n",
00992       pvt->owner ? pvt->owner->name : "",
00993       pvt->callno, pvt->peercallno, pvt->peer ? pvt->peer : "");
00994 }

static int iax2_answer ( struct ast_channel c  )  [static]

Definition at line 4148 of file chan_iax2.c.

References AST_CONTROL_ANSWER, ast_debug, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), iax2_ami_channelupdate(), PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.

04149 {
04150    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04151    ast_debug(1, "Answering IAX2 call\n");
04152    ast_mutex_lock(&iaxsl[callno]);
04153    if (iaxs[callno])
04154       iax2_ami_channelupdate(iaxs[callno]);
04155    ast_mutex_unlock(&iaxsl[callno]);
04156    return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
04157 }

static int iax2_append_register ( const char *  hostname,
const char *  username,
const char *  secret,
const char *  porta 
) [static]

Definition at line 6928 of file chan_iax2.c.

References ast_calloc, ast_copy_string(), ast_dnsmgr_lookup(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, iax2_registry::entry, IAX_DEFAULT_PORTNO, and IAX_DEFAULT_REG_EXPIRE.

Referenced by iax2_register().

06930 {
06931    struct iax2_registry *reg;
06932 
06933    if (!(reg = ast_calloc(1, sizeof(*reg))))
06934       return -1;
06935 
06936    if (ast_dnsmgr_lookup(hostname, &reg->addr.sin_addr, &reg->dnsmgr) < 0) {
06937       ast_free(reg);
06938       return -1;
06939    }
06940 
06941    ast_copy_string(reg->username, username, sizeof(reg->username));
06942 
06943    if (secret)
06944       ast_copy_string(reg->secret, secret, sizeof(reg->secret));
06945 
06946    reg->expire = -1;
06947    reg->refresh = IAX_DEFAULT_REG_EXPIRE;
06948    reg->addr.sin_family = AF_INET;
06949    reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO);
06950 
06951    AST_LIST_LOCK(&registrations);
06952    AST_LIST_INSERT_HEAD(&registrations, reg, entry);
06953    AST_LIST_UNLOCK(&registrations);
06954    
06955    return 0;
06956 }

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 3989 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_verb, f, iax2_tech, lock_both(), PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, tv, and unlock_both().

03990 {
03991    struct ast_channel *cs[3];
03992    struct ast_channel *who, *other;
03993    int to = -1;
03994    int res = -1;
03995    int transferstarted=0;
03996    struct ast_frame *f;
03997    unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt);
03998    unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt);
03999    struct timeval waittimer = {0, 0}, tv;
04000 
04001    /* We currently do not support native bridging if a timeoutms value has been provided */
04002    if (timeoutms > 0) {
04003       return AST_BRIDGE_FAILED;
04004    }
04005 
04006    timeoutms = -1;
04007 
04008    lock_both(callno0, callno1);
04009    if (!iaxs[callno0] || !iaxs[callno1]) {
04010       unlock_both(callno0, callno1);
04011       return AST_BRIDGE_FAILED;
04012    }
04013    /* Put them in native bridge mode */
04014    if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
04015       iaxs[callno0]->bridgecallno = callno1;
04016       iaxs[callno1]->bridgecallno = callno0;
04017    }
04018    /* If the bridge got retried, don't queue up more packets - the transfer request will be retransmitted as necessary */
04019    if (iaxs[callno0]->transferring && iaxs[callno1]->transferring) {
04020       transferstarted = 1;
04021    }
04022    unlock_both(callno0, callno1);
04023 
04024    /* If not, try to bridge until we can execute a transfer, if we can */
04025    cs[0] = c0;
04026    cs[1] = c1;
04027    for (/* ever */;;) {
04028       /* Check in case we got masqueraded into */
04029       if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) {
04030          ast_verb(3, "Can't masquerade, we're different...\n");
04031          /* Remove from native mode */
04032          if (c0->tech == &iax2_tech) {
04033             ast_mutex_lock(&iaxsl[callno0]);
04034             iaxs[callno0]->bridgecallno = 0;
04035             ast_mutex_unlock(&iaxsl[callno0]);
04036          }
04037          if (c1->tech == &iax2_tech) {
04038             ast_mutex_lock(&iaxsl[callno1]);
04039             iaxs[callno1]->bridgecallno = 0;
04040             ast_mutex_unlock(&iaxsl[callno1]);
04041          }
04042          return AST_BRIDGE_FAILED_NOWARN;
04043       }
04044       if (c0->nativeformats != c1->nativeformats) {
04045             char buf0[255];
04046             char buf1[255];
04047             ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats);
04048             ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats);
04049          ast_verb(3, "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1);
04050          /* Remove from native mode */
04051          lock_both(callno0, callno1);
04052          if (iaxs[callno0])
04053             iaxs[callno0]->bridgecallno = 0;
04054          if (iaxs[callno1])
04055             iaxs[callno1]->bridgecallno = 0;
04056          unlock_both(callno0, callno1);
04057          return AST_BRIDGE_FAILED_NOWARN;
04058       }
04059       /* check if transfered and if we really want native bridging */
04060       if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) {
04061          /* Try the transfer */
04062          if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) ||
04063                      ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA)))
04064             ast_log(LOG_WARNING, "Unable to start the transfer\n");
04065          transferstarted = 1;
04066       }
04067       if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
04068          /* Call has been transferred.  We're no longer involved */
04069          tv = ast_tvnow();
04070          if (ast_tvzero(waittimer)) {
04071             waittimer = tv;
04072          } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
04073             c0->_softhangup |= AST_SOFTHANGUP_DEV;
04074             c1->_softhangup |= AST_SOFTHANGUP_DEV;
04075             *fo = NULL;
04076             *rc = c0;
04077             res = AST_BRIDGE_COMPLETE;
04078             break;
04079          }
04080       }
04081       to = 1000;
04082       who = ast_waitfor_n(cs, 2, &to);
04083       if (timeoutms > -1) {
04084          timeoutms -= (1000 - to);
04085          if (timeoutms < 0)
04086             timeoutms = 0;
04087       }
04088       if (!who) {
04089          if (!timeoutms) {
04090             res = AST_BRIDGE_RETRY;
04091             break;
04092          }
04093          if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
04094             res = AST_BRIDGE_FAILED;
04095             break;
04096          }
04097          continue;
04098       }
04099       f = ast_read(who);
04100       if (!f) {
04101          *fo = NULL;
04102          *rc = who;
04103          res = AST_BRIDGE_COMPLETE;
04104          break;
04105       }
04106       if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS) && (f->subclass != AST_CONTROL_SRCUPDATE)) {
04107          *fo = f;
04108          *rc = who;
04109          res =  AST_BRIDGE_COMPLETE;
04110          break;
04111       }
04112       other = (who == c0) ? c1 : c0;  /* the 'other' channel */
04113       if ((f->frametype == AST_FRAME_VOICE) ||
04114          (f->frametype == AST_FRAME_TEXT) ||
04115          (f->frametype == AST_FRAME_VIDEO) || 
04116          (f->frametype == AST_FRAME_IMAGE) ||
04117          (f->frametype == AST_FRAME_DTMF) ||
04118          (f->frametype == AST_FRAME_CONTROL)) {
04119          /* monitored dtmf take out of the bridge.
04120           * check if we monitor the specific source.
04121           */
04122          int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
04123          if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
04124             *rc = who;
04125             *fo = f;
04126             res = AST_BRIDGE_COMPLETE;
04127             /* Remove from native mode */
04128             break;
04129          }
04130          /* everything else goes to the other side */
04131          ast_write(other, f);
04132       }
04133       ast_frfree(f);
04134       /* Swap who gets priority */
04135       cs[2] = cs[0];
04136       cs[0] = cs[1];
04137       cs[1] = cs[2];
04138    }
04139    lock_both(callno0, callno1);
04140    if(iaxs[callno0])
04141       iaxs[callno0]->bridgecallno = 0;
04142    if(iaxs[callno1])
04143       iaxs[callno1]->bridgecallno = 0;
04144    unlock_both(callno0, callno1);
04145    return res;
04146 }

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

Definition at line 3642 of file chan_iax2.c.

References ast_channel::_state, ast_channel::adsicpe, ast_channel_datastore_find(), ast_copy_string(), ast_debug, AST_FRAME_IAX, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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, ast_var_name(), ast_var_value(), 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(), ast_datastore::data, iax2_datetime(), iax2_sched_add(), iax2_variable_datastore_info, IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_raw(), 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_OSPTOKEN, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VARIABLE, IAX_IE_VERSION, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPTOKEN_SIZE, IAX_PROTO_VERSION, IAX_SENDANI, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, parse_dial_string(), PTR_TO_CALLNO, sched, secret, send_command(), ast_channel::tech_pvt, and var.

03643 {
03644    struct sockaddr_in sin;
03645    char *l=NULL, *n=NULL, *tmpstr;
03646    struct iax_ie_data ied;
03647    char *defaultrdest = "s";
03648    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03649    struct parsed_dial_string pds;
03650    struct create_addr_info cai;
03651    struct ast_var_t *var;
03652    struct ast_datastore *variablestore = ast_channel_datastore_find(c, &iax2_variable_datastore_info, NULL);
03653    const char* osp_token_ptr;
03654    unsigned int osp_token_length;
03655    unsigned char osp_block_index;
03656    unsigned int osp_block_length;
03657    unsigned char osp_buffer[256];
03658 
03659    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
03660       ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
03661       return -1;
03662    }
03663 
03664    memset(&cai, 0, sizeof(cai));
03665    cai.encmethods = iax2_encryption;
03666 
03667    memset(&pds, 0, sizeof(pds));
03668    tmpstr = ast_strdupa(dest);
03669    parse_dial_string(tmpstr, &pds);
03670 
03671    if (ast_strlen_zero(pds.peer)) {
03672       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest);
03673       return -1;
03674    }
03675 
03676    if (!pds.exten) {
03677       pds.exten = defaultrdest;
03678    }
03679 
03680    if (create_addr(pds.peer, c, &sin, &cai)) {
03681       ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer);
03682       return -1;
03683    }
03684 
03685    if (!pds.username && !ast_strlen_zero(cai.username))
03686       pds.username = cai.username;
03687    if (!pds.password && !ast_strlen_zero(cai.secret))
03688       pds.password = cai.secret;
03689    if (!pds.key && !ast_strlen_zero(cai.outkey))
03690       pds.key = cai.outkey;
03691    if (!pds.context && !ast_strlen_zero(cai.peercontext))
03692       pds.context = cai.peercontext;
03693 
03694    /* Keep track of the context for outgoing calls too */
03695    ast_copy_string(c->context, cai.context, sizeof(c->context));
03696 
03697    if (pds.port)
03698       sin.sin_port = htons(atoi(pds.port));
03699 
03700    l = c->cid.cid_num;
03701    n = c->cid.cid_name;
03702 
03703    /* Now build request */ 
03704    memset(&ied, 0, sizeof(ied));
03705 
03706    /* On new call, first IE MUST be IAX version of caller */
03707    iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION);
03708    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten);
03709    if (pds.options && strchr(pds.options, 'a')) {
03710       /* Request auto answer */
03711       iax_ie_append(&ied, IAX_IE_AUTOANSWER);
03712    }
03713 
03714    iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs);
03715 
03716    if (l) {
03717       iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
03718       iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03719    } else {
03720       if (n)
03721          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres);
03722       else
03723          iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
03724    }
03725 
03726    iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton);
03727    iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
03728 
03729    if (n)
03730       iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
03731    if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani)
03732       iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani);
03733 
03734    if (!ast_strlen_zero(c->language))
03735       iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
03736    if (!ast_strlen_zero(c->cid.cid_dnid))
03737       iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
03738    if (!ast_strlen_zero(c->cid.cid_rdnis))
03739       iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis);
03740 
03741    if (pds.context)
03742       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
03743 
03744    if (pds.username)
03745       iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username);
03746 
03747    if (cai.encmethods)
03748       iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods);
03749 
03750    ast_mutex_lock(&iaxsl[callno]);
03751 
03752    if (!ast_strlen_zero(c->context))
03753       ast_string_field_set(iaxs[callno], context, c->context);
03754 
03755    if (pds.username)
03756       ast_string_field_set(iaxs[callno], username, pds.username);
03757 
03758    iaxs[callno]->encmethods = cai.encmethods;
03759 
03760    iaxs[callno]->adsi = cai.adsi;
03761    
03762    ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret);
03763    ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest);
03764 
03765    if (pds.key)
03766       ast_string_field_set(iaxs[callno], outkey, pds.key);
03767    if (pds.password)
03768       ast_string_field_set(iaxs[callno], secret, pds.password);
03769 
03770    iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
03771    iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
03772    iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
03773    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone));
03774 
03775    if (iaxs[callno]->maxtime) {
03776       /* Initialize pingtime and auto-congest time */
03777       iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
03778       iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
03779    } else if (autokill) {
03780       iaxs[callno]->pingtime = autokill / 2;
03781       iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno));
03782    }
03783 
03784    /* Check if there is an OSP token set by IAXCHANINFO function */
03785    osp_token_ptr = iaxs[callno]->osptoken;
03786    if (!ast_strlen_zero(osp_token_ptr)) {
03787       if ((osp_token_length = strlen(osp_token_ptr)) <= IAX_MAX_OSPTOKEN_SIZE) {
03788          osp_block_index = 0;
03789          while (osp_token_length > 0) {
03790             osp_block_length = IAX_MAX_OSPBLOCK_SIZE < osp_token_length ? IAX_MAX_OSPBLOCK_SIZE : osp_token_length;
03791             osp_buffer[0] = osp_block_index;
03792             memcpy(osp_buffer + 1, osp_token_ptr, osp_block_length);
03793             iax_ie_append_raw(&ied, IAX_IE_OSPTOKEN, osp_buffer, osp_block_length + 1);
03794             osp_block_index++;
03795             osp_token_ptr += osp_block_length;
03796             osp_token_length -= osp_block_length;
03797          } 
03798       } else
03799          ast_log(LOG_WARNING, "OSP token is too long\n");
03800    } else if (iaxdebug)
03801       ast_debug(1, "OSP token is undefined\n");
03802 
03803    /* send the command using the appropriate socket for this peer */
03804    iaxs[callno]->sockfd = cai.sockfd;
03805 
03806    /* Add remote vars */
03807    if (variablestore) {
03808       AST_LIST_HEAD(, ast_var_t) *variablelist = variablestore->data;
03809       ast_debug(1, "Found an IAX variable store on this channel\n");
03810       AST_LIST_LOCK(variablelist);
03811       AST_LIST_TRAVERSE(variablelist, var, entries) {
03812          char tmp[256];
03813          int i;
03814          ast_debug(1, "Found IAXVAR '%s' with value '%s' (to transmit)\n", ast_var_name(var), ast_var_value(var));
03815          /* Automatically divide the value up into sized chunks */
03816          for (i = 0; i < strlen(ast_var_value(var)); i += 255 - (strlen(ast_var_name(var)) + 1)) {
03817             snprintf(tmp, sizeof(tmp), "%s=%s", ast_var_name(var), ast_var_value(var) + i);
03818             iax_ie_append_str(&ied, IAX_IE_VARIABLE, tmp);
03819          }
03820       }
03821       AST_LIST_UNLOCK(variablelist);
03822    }
03823 
03824    /* Transmit the string in a "NEW" request */
03825    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
03826 
03827    ast_mutex_unlock(&iaxsl[callno]);
03828    ast_setstate(c, AST_STATE_RINGING);
03829 
03830    return 0;
03831 }

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

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_CANEXIST, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.

11842 {
11843    int res = 0;
11844    struct iax2_dpcache *dp = NULL;
11845 #if 0
11846    ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
11847 #endif
11848    if ((priority != 1) && (priority != 2))
11849       return 0;
11850 
11851    AST_LIST_LOCK(&dpcache);
11852    if ((dp = find_cache(chan, data, context, exten, priority))) {
11853       if (dp->flags & CACHE_FLAG_CANEXIST)
11854          res = 1;
11855    } else {
11856       ast_log(LOG_WARNING, "Unable to make DP cache\n");
11857    }
11858    AST_LIST_UNLOCK(&dpcache);
11859 
11860    return res;
11861 }

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

Definition at line 3549 of file chan_iax2.c.

References ast_localtime(), ast_strlen_zero(), ast_tvnow(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.

Referenced by iax2_call(), and update_registry().

03550 {
03551    struct timeval t = ast_tvnow();
03552    struct ast_tm tm;
03553    unsigned int tmp;
03554    ast_localtime(&t, &tm, ast_strlen_zero(tz) ? NULL : tz);
03555    tmp  = (tm.tm_sec >> 1) & 0x1f;        /* 5 bits of seconds */
03556    tmp |= (tm.tm_min & 0x3f) << 5;        /* 6 bits of minutes */
03557    tmp |= (tm.tm_hour & 0x1f) << 11;      /* 5 bits of hours */
03558    tmp |= (tm.tm_mday & 0x1f) << 16;      /* 5 bits of day of month */
03559    tmp |= ((tm.tm_mon + 1) & 0xf) << 21;     /* 4 bits of month */
03560    tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */
03561    return tmp;
03562 }

static void iax2_destroy ( int  callno  )  [static]

Definition at line 2334 of file chan_iax2.c.

References ao2_ref(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), ast_tvnow(), chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), remove_by_transfercallno(), chan_iax2_pvt::transfercallno, 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().

02335 {
02336    struct chan_iax2_pvt *pvt = NULL;
02337    struct ast_channel *owner = NULL;
02338 
02339 retry:
02340    pvt = iaxs[callno];
02341    lastused[callno] = ast_tvnow();
02342    
02343    owner = pvt ? pvt->owner : NULL;
02344 
02345    if (owner) {
02346       if (ast_channel_trylock(owner)) {
02347          ast_debug(3, "Avoiding IAX destroy deadlock\n");
02348          ast_mutex_unlock(&iaxsl[callno]);
02349          usleep(1);
02350          ast_mutex_lock(&iaxsl[callno]);
02351          goto retry;
02352       }
02353    }
02354 
02355    if (!owner) {
02356       iaxs[callno] = NULL;
02357    }
02358 
02359    if (pvt) {
02360       if (!owner) {
02361          pvt->owner = NULL;
02362       } else {
02363          /* If there's an owner, prod it to give up */
02364          /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup()
02365           * because we already hold the owner channel lock. */
02366          ast_queue_hangup(owner);
02367       }
02368 
02369       if (pvt->peercallno) {
02370          remove_by_peercallno(pvt);
02371       }
02372 
02373       if (pvt->transfercallno) {
02374          remove_by_transfercallno(pvt);
02375       }
02376 
02377       if (!owner) {
02378          ao2_ref(pvt, -1);
02379          pvt = NULL;
02380       }
02381    }
02382 
02383    if (owner) {
02384       ast_channel_unlock(owner);
02385    }
02386 
02387    if (callno & 0x4000) {
02388       update_max_trunk();
02389    }
02390 }

static void iax2_destroy_helper ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1399 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, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, iax2_user::name, OBJ_POINTER, chan_iax2_pvt::pingid, sched, user, user_unref(), and chan_iax2_pvt::username.

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

01400 {
01401    /* Decrement AUTHREQ count if needed */
01402    if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
01403       struct iax2_user *user;
01404       struct iax2_user tmp_user = {
01405          .name = pvt->username,
01406       };
01407 
01408       user = ao2_find(users, &tmp_user, OBJ_POINTER);
01409       if (user) {
01410          ast_atomic_fetchadd_int(&user->curauthreq, -1);
01411          user_unref(user); 
01412       }
01413 
01414       ast_clear_flag(pvt, IAX_MAXAUTHREQ);
01415    }
01416    /* No more pings or lagrq's */
01417    AST_SCHED_DEL(sched, pvt->pingid);
01418    AST_SCHED_DEL(sched, pvt->lagid);
01419    AST_SCHED_DEL(sched, pvt->autoid);
01420    AST_SCHED_DEL(sched, pvt->authid);
01421    AST_SCHED_DEL(sched, pvt->initid);
01422    AST_SCHED_DEL(sched, pvt->jbid);
01423 }

static int iax2_devicestate ( void *  data  )  [static]

Part of the device state notification system ---.

Definition at line 12080 of file chan_iax2.c.

References iax2_peer::addr, ast_debug, 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, parse_dial_string(), and peer_unref().

12081 {
12082    struct parsed_dial_string pds;
12083    char *tmp = ast_strdupa(data);
12084    struct iax2_peer *p;
12085    int res = AST_DEVICE_INVALID;
12086 
12087    memset(&pds, 0, sizeof(pds));
12088    parse_dial_string(tmp, &pds);
12089 
12090    if (ast_strlen_zero(pds.peer)) {
12091       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
12092       return res;
12093    }
12094    
12095    ast_debug(3, "Checking device state for device %s\n", pds.peer);
12096 
12097    /* SLD: FIXME: second call to find_peer during registration */
12098    if (!(p = find_peer(pds.peer, 1)))
12099       return res;
12100 
12101    res = AST_DEVICE_UNAVAILABLE;
12102    ast_debug(3, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n",
12103       pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms);
12104    
12105    if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
12106        (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) {
12107       /* Peer is registered, or have default IP address
12108          and a valid registration */
12109       if (p->historicms == 0 || p->historicms <= p->maxms)
12110          /* let the core figure out whether it is in use or not */
12111          res = AST_DEVICE_UNKNOWN;  
12112    }
12113 
12114    peer_unref(p);
12115 
12116    return res;
12117 }

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

Definition at line 3173 of file chan_iax2.c.

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

03174 {
03175    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
03176 }

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

Definition at line 3178 of file chan_iax2.c.

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

03179 {
03180    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
03181 }

static int iax2_do_register ( struct iax2_registry reg  )  [static]

Definition at line 9959 of file chan_iax2.c.

References iax2_registry::addr, ast_debug, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_replace(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, LOG_WARNING, NEW_FORCE, iax2_registry::refresh, 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().

09960 {
09961    struct iax_ie_data ied;
09962    if (iaxdebug)
09963       ast_debug(1, "Sending registration request for '%s'\n", reg->username);
09964 
09965    if (reg->dnsmgr && 
09966        ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) {
09967       /* Maybe the IP has changed, force DNS refresh */
09968       ast_dnsmgr_refresh(reg->dnsmgr);
09969    }
09970    
09971    /*
09972     * if IP has Changed, free allocated call to create a new one with new IP
09973     * call has the pointer to IP and must be updated to the new one
09974     */
09975    if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) {
09976       int callno = reg->callno;
09977       ast_mutex_lock(&iaxsl[callno]);
09978       iax2_destroy(callno);
09979       ast_mutex_unlock(&iaxsl[callno]);
09980       reg->callno = 0;
09981    }
09982    if (!reg->addr.sin_addr.s_addr) {
09983       if (iaxdebug)
09984          ast_debug(1, "Unable to send registration request for '%s' without IP address\n", reg->username);
09985       /* Setup the next registration attempt */
09986       reg->expire = iax2_sched_replace(reg->expire, sched, 
09987          (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
09988       return -1;
09989    }
09990 
09991    if (!reg->callno) {
09992       ast_debug(3, "Allocate call number\n");
09993       reg->callno = find_callno_locked(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
09994       if (reg->callno < 1) {
09995          ast_log(LOG_WARNING, "Unable to create call for registration\n");
09996          return -1;
09997       } else
09998          ast_debug(3, "Registration created on call %d\n", reg->callno);
09999       iaxs[reg->callno]->reg = reg;
10000       ast_mutex_unlock(&iaxsl[reg->callno]);
10001    }
10002    /* Setup the next registration a little early */
10003    reg->expire = iax2_sched_replace(reg->expire, sched, 
10004       (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg);
10005    /* Send the request */
10006    memset(&ied, 0, sizeof(ied));
10007    iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
10008    iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
10009    send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
10010    reg->regstate = REG_STATE_REGSENT;
10011    return 0;
10012 }

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

Definition at line 6724 of file chan_iax2.c.

References __iax2_do_register_s(), and schedule_action.

Referenced by iax2_ack_registry(), and iax2_do_register().

06725 {
06726 #ifdef SCHED_MULTITHREADED
06727    if (schedule_action(__iax2_do_register_s, data))
06728 #endif      
06729       __iax2_do_register_s(data);
06730    return 0;
06731 }

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

Definition at line 7449 of file chan_iax2.c.

References AST_FRAME_IAX, auto_hangup(), CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_replace(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, sched, and send_command().

Referenced by find_cache(), and socket_process().

07450 {
07451    struct iax_ie_data ied;
07452    /* Auto-hangup with 30 seconds of inactivity */
07453    iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 
07454       sched, 30000, auto_hangup, (void *)(long)callno);
07455    memset(&ied, 0, sizeof(ied));
07456    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten);
07457    send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1);
07458    dp->flags |= CACHE_FLAG_TRANSMITTED;
07459 }

static void * iax2_dup_variable_datastore ( void *   )  [static]

Definition at line 1003 of file chan_iax2.c.

References ast_calloc, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_name(), ast_var_value(), ast_var_t::entries, and LOG_ERROR.

01004 {
01005    AST_LIST_HEAD(, ast_var_t) *oldlist = old, *newlist;
01006    struct ast_var_t *oldvar, *newvar;
01007 
01008    newlist = ast_calloc(sizeof(*newlist), 1);
01009    if (!newlist) {
01010       ast_log(LOG_ERROR, "Unable to duplicate iax2 variables\n");
01011       return NULL;
01012    }
01013 
01014    AST_LIST_HEAD_INIT(newlist);
01015    AST_LIST_LOCK(oldlist);
01016    AST_LIST_TRAVERSE(oldlist, oldvar, entries) {
01017       newvar = ast_var_assign(ast_var_name(oldvar), ast_var_value(oldvar));
01018       if (newvar)
01019          AST_LIST_INSERT_TAIL(newlist, newvar, entries);
01020       else
01021          ast_log(LOG_ERROR, "Unable to duplicate iax2 variable '%s'\n", ast_var_name(oldvar));
01022    }
01023    AST_LIST_UNLOCK(oldlist);
01024    return newlist;
01025 }

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

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_verb, CACHE_FLAG_EXISTS, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_exec(), and pbx_findapp().

11888 {
11889    char odata[256];
11890    char req[256];
11891    char *ncontext;
11892    struct iax2_dpcache *dp = NULL;
11893    struct ast_app *dial = NULL;
11894 #if 0
11895    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);
11896 #endif
11897    if (priority == 2) {
11898       /* Indicate status, can be overridden in dialplan */
11899       const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS");
11900       if (dialstatus) {
11901          dial = pbx_findapp(dialstatus);
11902          if (dial) 
11903             pbx_exec(chan, dial, "");
11904       }
11905       return -1;
11906    } else if (priority != 1)
11907       return -1;
11908 
11909    AST_LIST_LOCK(&dpcache);
11910    if ((dp = find_cache(chan, data, context, exten, priority))) {
11911       if (dp->flags & CACHE_FLAG_EXISTS) {
11912          ast_copy_string(odata, data, sizeof(odata));
11913          ncontext = strchr(odata, '/');
11914          if (ncontext) {
11915             *ncontext = '\0';
11916             ncontext++;
11917             snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext);
11918          } else {
11919             snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten);
11920          }
11921          ast_verb(3, "Executing Dial('%s')\n", req);
11922       } else {
11923          AST_LIST_UNLOCK(&dpcache);
11924          ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
11925          return -1;
11926       }
11927    }
11928    AST_LIST_UNLOCK(&dpcache);
11929 
11930    if ((dial = pbx_findapp("Dial")))
11931       return pbx_exec(chan, dial, req);
11932    else
11933       ast_log(LOG_WARNING, "No dial application registered\n");
11934 
11935    return -1;
11936 }

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

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_EXISTS, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.

11819 {
11820    int res = 0;
11821    struct iax2_dpcache *dp = NULL;
11822 #if 0
11823    ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
11824 #endif
11825    if ((priority != 1) && (priority != 2))
11826       return 0;
11827 
11828    AST_LIST_LOCK(&dpcache);
11829    if ((dp = find_cache(chan, data, context, exten, priority))) {
11830       if (dp->flags & CACHE_FLAG_EXISTS)
11831          res = 1;
11832    } else {
11833       ast_log(LOG_WARNING, "Unable to make DP cache\n");
11834    }
11835    AST_LIST_UNLOCK(&dpcache);
11836 
11837    return res;
11838 }

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

Definition at line 3200 of file chan_iax2.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, PTR_TO_CALLNO, and ast_channel::tech_pvt.

03201 {
03202    unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt);
03203    ast_mutex_lock(&iaxsl[callno]);
03204    if (iaxs[callno])
03205       iaxs[callno]->owner = newchan;
03206    else
03207       ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
03208    ast_mutex_unlock(&iaxsl[callno]);
03209    return 0;
03210 }

static void iax2_frame_free ( struct iax_frame fr  )  [static]

Definition at line 1425 of file chan_iax2.c.

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

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

01426 {
01427    AST_SCHED_DEL(sched, fr->retrans);
01428    iax_frame_free(fr);
01429 }

static void iax2_free_variable_datastore ( void *   )  [static]

Definition at line 1027 of file chan_iax2.c.

References ast_free, AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and ast_var_t::entries.

01028 {
01029    AST_LIST_HEAD(, ast_var_t) *oldlist = old;
01030    struct ast_var_t *oldvar;
01031 
01032    AST_LIST_LOCK(oldlist);
01033    while ((oldvar = AST_LIST_REMOVE_HEAD(oldlist, entries))) {
01034       ast_free(oldvar);
01035    }
01036    AST_LIST_UNLOCK(oldlist);
01037    AST_LIST_HEAD_DESTROY(oldlist);
01038    ast_free(oldlist);
01039 }

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

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

01370 {
01371    struct iax2_peer *peer = NULL;
01372    int res = 0;
01373    struct ao2_iterator i;
01374 
01375    i = ao2_iterator_init(peers, 0);
01376    while ((peer = ao2_iterator_next(&i))) {
01377       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
01378           (peer->addr.sin_port == sin.sin_port)) {
01379          ast_copy_string(host, peer->name, len);
01380          peer_unref(peer);
01381          res = 1;
01382          break;
01383       }
01384       peer_unref(peer);
01385    }
01386 
01387    if (!peer) {
01388       peer = realtime_peer(NULL, &sin);
01389       if (peer) {
01390          ast_copy_string(host, peer->name, len);
01391          peer_unref(peer);
01392          res = 1;
01393       }
01394    }
01395 
01396    return res;
01397 }

static int iax2_getpeertrunk ( struct sockaddr_in  sin  )  [static]

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

04217 {
04218    struct iax2_peer *peer;
04219    int res = 0;
04220    struct ao2_iterator i;
04221 
04222    i = ao2_iterator_init(peers, 0);
04223    while ((peer = ao2_iterator_next(&i))) {
04224       if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
04225           (peer->addr.sin_port == sin.sin_port)) {
04226          res = ast_test_flag(peer, IAX_TRUNK);
04227          peer_unref(peer);
04228          break;
04229       }
04230       peer_unref(peer);
04231    }
04232 
04233    return res;
04234 }

static int iax2_hangup ( struct ast_channel c  )  [static]

Definition at line 3833 of file chan_iax2.c.

References ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_test_flag, ast_verb, CALLNO_TO_PTR, ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, LOG_ERROR, LOG_WARNING, ast_channel::name, PTR_TO_CALLNO, sched, scheduled_destroy(), send_command_final(), and ast_channel::tech_pvt.

03834 {
03835    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03836    struct iax_ie_data ied;
03837    int alreadygone;
03838    memset(&ied, 0, sizeof(ied));
03839    ast_mutex_lock(&iaxsl[callno]);
03840    if (callno && iaxs[callno]) {
03841       ast_debug(1, "We're hanging up %s now...\n", c->name);
03842       alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
03843       /* Send the hangup unless we have had a transmission error or are already gone */
03844       iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
03845       if (!iaxs[callno]->error && !alreadygone) {
03846          if (send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1)) {
03847             ast_log(LOG_WARNING, "No final packet could be sent for callno %d\n", callno);
03848          }
03849          if (!iaxs[callno]) {
03850             ast_mutex_unlock(&iaxsl[callno]);
03851             return 0;
03852          }
03853       }
03854       /* Explicitly predestroy it */
03855       iax2_predestroy(callno);
03856       /* If we were already gone to begin with, destroy us now */
03857       if (iaxs[callno] && alreadygone) {
03858          ast_debug(1, "Really destroying %s now...\n", c->name);
03859          iax2_destroy(callno);
03860       } else if (iaxs[callno]) {
03861          if (ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) {
03862             ast_log(LOG_ERROR, "Unable to schedule iax2 callno %d destruction?!!  Destroying immediately.\n", callno);
03863             iax2_destroy(callno);
03864          }
03865       }
03866    } else if (c->tech_pvt) {
03867       /* If this call no longer exists, but the channel still
03868        * references it we need to set the channel's tech_pvt to null
03869        * to avoid ast_channel_free() trying to free it.
03870        */
03871       c->tech_pvt = NULL;
03872    }
03873    ast_mutex_unlock(&iaxsl[callno]);
03874    ast_verb(3, "Hungup '%s'\n", c->name);
03875    return 0;
03876 }

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

Definition at line 4159 of file chan_iax2.c.

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

04160 {
04161    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04162    struct chan_iax2_pvt *pvt;
04163    int res = 0;
04164 
04165    if (iaxdebug)
04166       ast_debug(1, "Indicating condition %d\n", condition);
04167 
04168    ast_mutex_lock(&iaxsl[callno]);
04169    pvt = iaxs[callno];
04170 
04171    if (wait_for_peercallno(pvt)) {
04172       res = -1;
04173       goto done;
04174    }
04175 
04176    switch (condition) {
04177    case AST_CONTROL_HOLD:
04178       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
04179          ast_moh_start(c, data, pvt->mohinterpret);
04180          goto done;
04181       }
04182       break;
04183    case AST_CONTROL_UNHOLD:
04184       if (strcasecmp(pvt->mohinterpret, "passthrough")) {
04185          ast_moh_stop(c);
04186          goto done;
04187       }
04188    }
04189 
04190    res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
04191 
04192 done:
04193    ast_mutex_unlock(&iaxsl[callno]);
04194 
04195    return res;
04196 }

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

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_MATCHMORE, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.

11865 {
11866    int res = 0;
11867    struct iax2_dpcache *dp = NULL;
11868 #if 0
11869    ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
11870 #endif
11871    if ((priority != 1) && (priority != 2))
11872       return 0;
11873 
11874    AST_LIST_LOCK(&dpcache);
11875    if ((dp = find_cache(chan, data, context, exten, priority))) {
11876       if (dp->flags & CACHE_FLAG_MATCHMORE)
11877          res = 1;
11878    } else {
11879       ast_log(LOG_WARNING, "Unable to make DP cache\n");
11880    }
11881    AST_LIST_UNLOCK(&dpcache);
11882 
11883    return res;
11884 }

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

Definition at line 10162 of file chan_iax2.c.

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

Referenced by iax2_poke_peer().

10163 {
10164    struct iax2_peer *peer = (struct iax2_peer *)data;
10165    peer->pokeexpire = -1;
10166 #ifdef SCHED_MULTITHREADED
10167    if (schedule_action(__iax2_poke_noanswer, data))
10168 #endif      
10169       __iax2_poke_noanswer(data);
10170    peer_unref(peer);
10171    return 0;
10172 }

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

Definition at line 10183 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, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, iax2_peer::name, NEW_FORCE, peer_ref(), peer_unref(), 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().

10184 {
10185    int callno;
10186    if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) {
10187       /* IF we have no IP without dnsmgr, or this isn't to be monitored, return
10188         immediately after clearing things out */
10189       peer->lastms = 0;
10190       peer->historicms = 0;
10191       peer->pokeexpire = -1;
10192       peer->callno = 0;
10193       return 0;
10194    }
10195 
10196    /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */
10197    if ((callno = peer->callno) > 0) {
10198       ast_log(LOG_NOTICE, "Still have a callno...\n");
10199       ast_mutex_lock(&iaxsl[callno]);
10200       iax2_destroy(callno);
10201       ast_mutex_unlock(&iaxsl[callno]);
10202    }
10203    if (heldcall)
10204       ast_mutex_unlock(&iaxsl[heldcall]);
10205    callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
10206    if (heldcall)
10207       ast_mutex_lock(&iaxsl[heldcall]);
10208    if (peer->callno < 1) {
10209       ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name);
10210       return -1;
10211    }
10212 
10213    /* Speed up retransmission times for this qualify call */
10214    iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1;
10215    iaxs[peer->callno]->peerpoke = peer;
10216 
10217    if (peer->pokeexpire > -1) {
10218       if (!ast_sched_del(sched, peer->pokeexpire)) {
10219          peer->pokeexpire = -1;
10220          peer_unref(peer);
10221       }
10222    }
10223  
10224    /* Queue up a new task to handle no reply */
10225    /* If the host is already unreachable then use the unreachable interval instead */
10226    if (peer->lastms < 0)
10227       peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer));
10228    else
10229       peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer));
10230 
10231    if (peer->pokeexpire == -1)
10232       peer_unref(peer);
10233 
10234    /* And send the poke */
10235    ast_mutex_lock(&iaxsl[callno]);
10236    if (iaxs[callno]) {
10237       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1);
10238    }
10239    ast_mutex_unlock(&iaxsl[callno]);
10240 
10241    return 0;
10242 }

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

Definition at line 10174 of file chan_iax2.c.

References iax2_poke_peer().

Referenced by load_module().

10175 {
10176    struct iax2_peer *peer = obj;
10177 
10178    iax2_poke_peer(peer, 0);
10179 
10180    return 0;
10181 }

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

Definition at line 7489 of file chan_iax2.c.

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

Referenced by __iax2_poke_noanswer(), and socket_process().

07490 {
07491    struct iax2_peer *peer = (struct iax2_peer *)data;
07492    peer->pokeexpire = -1;
07493 #ifdef SCHED_MULTITHREADED
07494    if (schedule_action(__iax2_poke_peer_s, data))
07495 #endif      
07496       __iax2_poke_peer_s(data);
07497    return 0;
07498 }

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

References ast_module_unref(), ast_set_flag, ast_test_flag, iax2_destroy_helper(), iax2_queue_hangup(), IAX_ALREADYGONE, chan_iax2_pvt::owner, and ast_channel::tech_pvt.

Referenced by iax2_hangup(), and send_command_final().

02312 {
02313    struct ast_channel *c = NULL;
02314    struct chan_iax2_pvt *pvt = iaxs[callno];
02315 
02316    if (!pvt)
02317       return -1;
02318 
02319    if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
02320       iax2_destroy_helper(pvt);
02321       ast_set_flag(pvt, IAX_ALREADYGONE); 
02322    }
02323 
02324    if ((c = pvt->owner)) {
02325       c->tech_pvt = NULL;
02326       iax2_queue_hangup(callno);
02327       pvt->owner = NULL;
02328       ast_module_unref(ast_module_info->self);
02329    }
02330 
02331    return 0;
02332 }

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

Definition at line 9834 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_THREAD_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), and thread.

Referenced by find_idle_thread(), and start_network_thread().

09835 {
09836    struct iax2_thread *thread = data;
09837    struct timeval tv;
09838    struct timespec ts;
09839    int put_into_idle = 0;
09840 
09841    ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
09842    pthread_cleanup_push(iax2_process_thread_cleanup, data);
09843    for(;;) {
09844       /* Wait for something to signal us to be awake */
09845       ast_mutex_lock(&thread->lock);
09846 
09847       /* Flag that we're ready to accept signals */
09848       thread->ready_for_signal = 1;
09849       
09850       /* Put into idle list if applicable */
09851       if (put_into_idle)
09852          insert_idle_thread(thread);
09853 
09854       if (thread->type == IAX_THREAD_TYPE_DYNAMIC) {
09855          struct iax2_thread *t = NULL;
09856          /* Wait to be signalled or time out */
09857          tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
09858          ts.tv_sec = tv.tv_sec;
09859          ts.tv_nsec = tv.tv_usec * 1000;
09860          if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
09861             /* This thread was never put back into the available dynamic
09862              * thread list, so just go away. */
09863             if (!put_into_idle) {
09864                ast_mutex_unlock(&thread->lock);
09865                break;
09866             }
09867             AST_LIST_LOCK(&dynamic_list);
09868             /* Account for the case where this thread is acquired *right* after a timeout */
09869             if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list)))
09870                ast_atomic_fetchadd_int(&iaxdynamicthreadcount, -1);
09871             AST_LIST_UNLOCK(&dynamic_list);
09872             if (t) {
09873                /* This dynamic thread timed out waiting for a task and was
09874                 * not acquired immediately after the timeout, 
09875                 * so it's time to go away. */
09876                ast_mutex_unlock(&thread->lock);
09877                break;
09878             }
09879             /* Someone grabbed our thread *right* after we timed out.
09880              * Wait for them to set us up with something to do and signal
09881              * us to continue. */
09882             tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
09883             ts.tv_sec = tv.tv_sec;
09884             ts.tv_nsec = tv.tv_usec * 1000;
09885             if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
09886             {
09887                ast_mutex_unlock(&thread->lock);
09888                break;
09889             }
09890          }
09891       } else {
09892          ast_cond_wait(&thread->cond, &thread->lock);
09893       }
09894 
09895       /* Go back into our respective list */
09896       put_into_idle = 1;
09897 
09898       ast_mutex_unlock(&thread->lock);
09899 
09900       if (thread->iostate == IAX_IOSTATE_IDLE)
09901          continue;
09902 
09903       /* Add ourselves to the active list now */
09904       AST_LIST_LOCK(&active_list);
09905       AST_LIST_INSERT_HEAD(&active_list, thread, list);
09906       AST_LIST_UNLOCK(&active_list);
09907 
09908       /* See what we need to do */
09909       switch(thread->iostate) {
09910       case IAX_IOSTATE_READY:
09911          thread->actions++;
09912          thread->iostate = IAX_IOSTATE_PROCESSING;
09913          socket_process(thread);
09914          handle_deferred_full_frames(thread);
09915          break;
09916       case IAX_IOSTATE_SCHEDREADY:
09917          thread->actions++;
09918          thread->iostate = IAX_IOSTATE_PROCESSING;
09919 #ifdef SCHED_MULTITHREADED
09920          thread->schedfunc(thread->scheddata);
09921 #endif      
09922       default:
09923          break;
09924       }
09925       time(&thread->checktime);
09926       thread->iostate = IAX_IOSTATE_IDLE;
09927 #ifdef DEBUG_SCHED_MULTITHREAD
09928       thread->curfunc[0]='\0';
09929 #endif      
09930 
09931       /* Now... remove ourselves from the active list, and return to the idle list */
09932       AST_LIST_LOCK(&active_list);
09933       AST_LIST_REMOVE(&active_list, thread, list);
09934       AST_LIST_UNLOCK(&active_list);
09935 
09936       /* Make sure another frame didn't sneak in there after we thought we were done. */
09937       handle_deferred_full_frames(thread);
09938    }
09939 
09940    /*!\note For some reason, idle threads are exiting without being removed
09941     * from an idle list, which is causing memory corruption.  Forcibly remove
09942     * it from the list, if it's there.
09943     */
09944    AST_LIST_LOCK(&idle_list);
09945    AST_LIST_REMOVE(&idle_list, thread, list);
09946    AST_LIST_UNLOCK(&idle_list);
09947 
09948    AST_LIST_LOCK(&dynamic_list);
09949    AST_LIST_REMOVE(&dynamic_list, thread, list);
09950    AST_LIST_UNLOCK(&dynamic_list);
09951 
09952    /* I am exiting here on my own volition, I need to clean up my own data structures
09953    * Assume that I am no longer in any of the lists (idle, active, or dynamic)
09954    */
09955    pthread_cleanup_pop(1);
09956    return NULL;
09957 }

static void iax2_process_thread_cleanup ( void *  data  )  [static]

Definition at line 9825 of file chan_iax2.c.

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

Referenced by iax2_process_thread().

09826 {
09827    struct iax2_thread *thread = data;
09828    ast_mutex_destroy(&thread->lock);
09829    ast_cond_destroy(&thread->cond);
09830    ast_free(thread);
09831    ast_atomic_dec_and_test(&iaxactivethreadcount);
09832 }

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

Definition at line 10014 of file chan_iax2.c.

References ast_debug, AST_FRAME_IAX, ast_mutex_unlock(), ast_set_flag, auto_hangup(), iax_ie_data::buf, create_addr(), find_callno_locked(), iax2_sched_replace(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), NEW_FORCE, iax_ie_data::pos, sched, and send_command().

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

10015 {
10016    /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning
10017       is found for template */
10018    struct iax_ie_data provdata;
10019    struct iax_ie_data ied;
10020    unsigned int sig;
10021    struct sockaddr_in sin;
10022    int callno;
10023    struct create_addr_info cai;
10024 
10025    memset(&cai, 0, sizeof(cai));
10026 
10027    ast_debug(1, "Provisioning '%s' from template '%s'\n", dest, template);
10028 
10029    if (iax_provision_build(&provdata, &sig, template, force)) {
10030       ast_debug(1, "No provisioning found for template '%s'\n", template);
10031       return 0;
10032    }
10033 
10034    if (end) {
10035       memcpy(&sin, end, sizeof(sin));
10036       cai.sockfd = sockfd;
10037    } else if (create_addr(dest, NULL, &sin, &cai))
10038       return -1;
10039 
10040    /* Build the rest of the message */
10041    memset(&ied, 0, sizeof(ied));
10042    iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
10043 
10044    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10045    if (!callno)
10046       return -1;
10047 
10048    if (iaxs[callno]) {
10049       /* Schedule autodestruct in case they don't ever give us anything back */
10050       iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 
10051          sched, 15000, auto_hangup, (void *)(long)callno);
10052       ast_set_flag(iaxs[callno], IAX_PROVISION);
10053       /* Got a call number now, so go ahead and send the provisioning information */
10054       send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1);
10055    }
10056    ast_mutex_unlock(&iaxsl[callno]);
10057 
10058    return 1;
10059 }

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

References ast_channel_trylock, ast_channel_unlock, ast_queue_control_data(), DEADLOCK_AVOIDANCE, and chan_iax2_pvt::owner.

Referenced by socket_process().

01938 {
01939    for (;;) {
01940       if (iaxs[callno] && iaxs[callno]->owner) {
01941          if (ast_channel_trylock(iaxs[callno]->owner)) {
01942             /* Avoid deadlock by pausing and trying again */
01943             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01944          } else {
01945             ast_queue_control_data(iaxs[callno]->owner, control, data, datalen);
01946             ast_channel_unlock(iaxs[callno]->owner);
01947             break;
01948          }
01949       } else
01950          break;
01951    }
01952    return 0;
01953 }

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

References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, and chan_iax2_pvt::owner.

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

01875 {
01876    for (;;) {
01877       if (iaxs[callno] && iaxs[callno]->owner) {
01878          if (ast_channel_trylock(iaxs[callno]->owner)) {
01879             /* Avoid deadlock by pausing and trying again */
01880             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01881          } else {
01882             ast_queue_frame(iaxs[callno]->owner, f);
01883             ast_channel_unlock(iaxs[callno]->owner);
01884             break;
01885          }
01886       } else
01887          break;
01888    }
01889    return 0;
01890 }

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

References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, and chan_iax2_pvt::owner.

Referenced by iax2_predestroy().

01906 {
01907    for (;;) {
01908       if (iaxs[callno] && iaxs[callno]->owner) {
01909          if (ast_channel_trylock(iaxs[callno]->owner)) {
01910             /* Avoid deadlock by pausing and trying again */
01911             DEADLOCK_AVOIDANCE(&iaxsl[callno]);
01912          } else {
01913             ast_queue_hangup(iaxs[callno]->owner);
01914             ast_channel_unlock(iaxs[callno]->owner);
01915             break;
01916          }
01917       } else
01918          break;
01919    }
01920    return 0;
01921 }

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

Definition at line 3942 of file chan_iax2.c.

References ast_log(), ast_null_frame, and LOG_NOTICE.

03943 {
03944    ast_log(LOG_NOTICE, "I should never be called!\n");
03945    return &ast_null_frame;
03946 }

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

Definition at line 6958 of file chan_iax2.c.

References ast_copy_string(), ast_log(), copy(), hostname, iax2_append_register(), LOG_WARNING, secret, and strsep().

Referenced by set_config().

06959 {
06960    char copy[256];
06961    char *username, *hostname, *secret;
06962    char *porta;
06963    char *stringp=NULL;
06964    
06965    if (!value)
06966       return -1;
06967 
06968    ast_copy_string(copy, value, sizeof(copy));
06969    stringp = copy;
06970    username = strsep(&stringp, "@");
06971    hostname = strsep(&stringp, "@");
06972 
06973    if (!hostname) {
06974       ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno);
06975       return -1;
06976    }
06977 
06978    stringp = username;
06979    username = strsep(&stringp, ":");
06980    secret = strsep(&stringp, ":");
06981    stringp = hostname;
06982    hostname = strsep(&stringp, ":");
06983    porta = strsep(&stringp, ":");
06984    
06985    if (porta && !atoi(porta)) {
06986       ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno);
06987       return -1;
06988    }
06989 
06990    return iax2_append_register(hostname, username, secret, porta);
06991 }

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

Definition at line 10254 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, LOG_WARNING, make_trunk(), ast_channel::name, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), ast_channel::readformat, and ast_channel::writeformat.

10255 {
10256    int callno;
10257    int res;
10258    int fmt, native;
10259    struct sockaddr_in sin;
10260    struct ast_channel *c;
10261    struct parsed_dial_string pds;
10262    struct create_addr_info cai;
10263    char *tmpstr;
10264 
10265    memset(&pds, 0, sizeof(pds));
10266    tmpstr = ast_strdupa(data);
10267    parse_dial_string(tmpstr, &pds);
10268 
10269    if (ast_strlen_zero(pds.peer)) {
10270       ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data);
10271       return NULL;
10272    }
10273           
10274    memset(&cai, 0, sizeof(cai));
10275    cai.capability = iax2_capability;
10276 
10277    ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
10278    
10279    /* Populate our address from the given */
10280    if (create_addr(pds.peer, NULL, &sin, &cai)) {
10281       *cause = AST_CAUSE_UNREGISTERED;
10282       return NULL;
10283    }
10284 
10285    if (pds.port)
10286       sin.sin_port = htons(atoi(pds.port));
10287 
10288    callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
10289    if (callno < 1) {
10290       ast_log(LOG_WARNING, "Unable to create call\n");
10291       *cause = AST_CAUSE_CONGESTION;
10292       return NULL;
10293    }
10294 
10295    /* If this is a trunk, update it now */
10296    ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 
10297    if (ast_test_flag(&cai, IAX_TRUNK)) {
10298       int new_callno;
10299       if ((new_callno = make_trunk(callno, 1)) != -1)
10300          callno = new_callno;
10301    }
10302    iaxs[callno]->maxtime = cai.maxtime;
10303    if (cai.found)
10304       ast_string_field_set(iaxs[callno], host, pds.peer);
10305 
10306    c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
10307 
10308    ast_mutex_unlock(&iaxsl[callno]);
10309 
10310    if (c) {
10311       /* Choose a format we can live with */
10312       if (c->nativeformats & format) 
10313          c->nativeformats &= format;
10314       else {
10315          native = c->nativeformats;
10316          fmt = format;
10317          res = ast_translator_best_choice(&fmt, &native);
10318          if (res < 0) {
10319             ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n",
10320                ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name);
10321             ast_hangup(c);
10322             return NULL;
10323          }
10324          c->nativeformats = native;
10325       }
10326       c->readformat = ast_best_codec(c->nativeformats);
10327       c->writeformat = c->readformat;
10328    }
10329 
10330    return c;
10331 }

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

Definition at line 1155 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(), iax2_call(), iax2_poke_peer(), make_trunk(), network_thread(), reg_source_db(), socket_process(), and update_registry().

01156 {
01157    int res;
01158 
01159    res = ast_sched_add(con, when, callback, data);
01160    signal_condition(&sched_lock, &sched_cond);
01161 
01162    return res;
01163 }

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

Definition at line 1147 of file chan_iax2.c.

References AST_SCHED_REPLACE, sched_lock, and signal_condition().

Referenced by auth_fail(), iax2_ack_registry(), iax2_do_register(), iax2_dprequest(), iax2_provision(), and update_jbsched().

01148 {
01149    AST_SCHED_REPLACE(id, con, when, callback, data);
01150    signal_condition(&sched_lock, &sched_cond);
01151 
01152    return id;
01153 }

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 4864 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, iax_frame::ecx, iax_frame::encmethods, encrypt_frame(), f, iax_frame::final, chan_iax2_pvt::first_iax_message, 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::last_iax_message, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, LOG_WARNING, MARK_IAX_SUBCLASS_TX, MAX_RETRY_TIME, MIN_RETRY_TIME, iax_frame::mydcx, 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, iax_frame::semirand, 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().

04865 {
04866    /* Queue a packet for delivery on a given private structure.  Use "ts" for
04867       timestamp, or calculate if ts is 0.  Send immediately without retransmission
04868       or delayed, with retransmission */
04869    struct ast_iax2_full_hdr *fh;
04870    struct ast_iax2_mini_hdr *mh;
04871    struct ast_iax2_video_hdr *vh;
04872    struct {
04873       struct iax_frame fr2;
04874       unsigned char buffer[4096];
04875    } frb;
04876    struct iax_frame *fr;
04877    int res;
04878    int sendmini=0;
04879    unsigned int lastsent;
04880    unsigned int fts;
04881 
04882    frb.fr2.afdatalen = sizeof(frb.buffer);
04883 
04884    if (!pvt) {
04885       ast_log(LOG_WARNING, "No private structure for packet?\n");
04886       return -1;
04887    }
04888    
04889    lastsent = pvt->lastsent;
04890 
04891    /* Calculate actual timestamp */
04892    fts = calc_timestamp(pvt, ts, f);
04893 
04894    /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out
04895     * (the endpoint should detect the lost packet itself).  But, we want to do this here, so that we
04896     * increment the "predicted timestamps" for voice, if we're predicting */
04897    if(f->frametype == AST_FRAME_VOICE && f->datalen == 0)
04898        return 0;
04899 
04900 
04901    if ((ast_test_flag(pvt, IAX_TRUNK) || 
04902          (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) ||
04903          ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L))))
04904       /* High two bytes are the same on timestamp, or sending on a trunk */ &&
04905        (f->frametype == AST_FRAME_VOICE) 
04906       /* is a voice frame */ &&
04907       (f->subclass == pvt->svoiceformat) 
04908       /* is the same type */ ) {
04909          /* Force immediate rather than delayed transmission */
04910          now = 1;
04911          /* Mark that mini-style frame is appropriate */
04912          sendmini = 1;
04913    }
04914    if ( f->frametype == AST_FRAME_VIDEO ) {
04915       /*
04916        * If the lower 15 bits of the timestamp roll over, or if
04917        * the video format changed then send a full frame.
04918        * Otherwise send a mini video frame
04919        */
04920       if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) &&
04921           ((f->subclass & ~0x1) == pvt->svideoformat)
04922          ) {
04923          now = 1;
04924          sendmini = 1;
04925       } else {
04926          now = 0;
04927          sendmini = 0;
04928       }
04929       pvt->lastvsent = fts;
04930    }
04931    if (f->frametype == AST_FRAME_IAX) {
04932       /* 0x8000 marks this message as TX:, this bit will be stripped later */
04933       pvt->last_iax_message = f->subclass | MARK_IAX_SUBCLASS_TX;
04934       if (!pvt->first_iax_message) {
04935          pvt->first_iax_message = pvt->last_iax_message;
04936       }
04937    }
04938    /* Allocate an iax_frame */
04939    if (now) {
04940       fr = &frb.fr2;
04941    } else
04942       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));
04943    if (!fr) {
04944       ast_log(LOG_WARNING, "Out of memory\n");
04945       return -1;
04946    }
04947    /* Copy our prospective frame into our immediate or retransmitted wrapper */
04948    iax_frame_wrap(fr, f);
04949 
04950    fr->ts = fts;
04951    fr->callno = pvt->callno;
04952    fr->transfer = transfer;
04953    fr->final = final;
04954    fr->encmethods = 0;
04955    if (!sendmini) {
04956       /* We need a full frame */
04957       if (seqno > -1)
04958          fr->oseqno = seqno;
04959       else
04960          fr->oseqno = pvt->oseqno++;
04961       fr->iseqno = pvt->iseqno;
04962       fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr));
04963       fh->scallno = htons(fr->callno | IAX_FLAG_FULL);
04964       fh->ts = htonl(fr->ts);
04965       fh->oseqno = fr->oseqno;
04966       if (transfer) {
04967          fh->iseqno = 0;
04968       } else
04969          fh->iseqno = fr->iseqno;
04970       /* Keep track of the last thing we've acknowledged */
04971       if (!transfer)
04972          pvt->aseqno = fr->iseqno;
04973       fh->type = fr->af.frametype & 0xFF;
04974       if (fr->af.frametype == AST_FRAME_VIDEO)
04975          fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6);
04976       else
04977          fh->csub = compress_subclass(fr->af.subclass);
04978       if (transfer) {
04979          fr->dcallno = pvt->transfercallno;
04980       } else
04981          fr->dcallno = pvt->peercallno;
04982       fh->dcallno = htons(fr->dcallno);
04983       fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr);
04984       fr->data = fh;
04985       fr->retries = 0;
04986       /* Retry after 2x the ping time has passed */
04987       fr->retrytime = pvt->pingtime * 2;
04988       if (fr->retrytime < MIN_RETRY_TIME)
04989          fr->retrytime = MIN_RETRY_TIME;
04990       if (fr->retrytime > MAX_RETRY_TIME)
04991          fr->retrytime = MAX_RETRY_TIME;
04992       /* Acks' don't get retried */
04993       if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK))
04994          fr->retries = -1;
04995       else if (f->frametype == AST_FRAME_VOICE)
04996          pvt->svoiceformat = f->subclass;
04997       else if (f->frametype == AST_FRAME_VIDEO)
04998          pvt->svideoformat = f->subclass & ~0x1;
04999       if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
05000          if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
05001             if (iaxdebug) {
05002                if (fr->transfer)
05003                   iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
05004                else
05005                   iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
05006             }
05007             encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
05008             fr->encmethods = pvt->encmethods;
05009             fr->ecx = pvt->ecx;
05010             fr->mydcx = pvt->mydcx;
05011             memcpy(fr->semirand, pvt->semirand, sizeof(fr->semirand));
05012          } else
05013             ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
05014       }
05015 
05016       if (now) {
05017          res = send_packet(fr);
05018       } else
05019          res = iax2_transmit(fr);
05020    } else {
05021       if (ast_test_flag(pvt, IAX_TRUNK)) {
05022          iax2_trunk_queue(pvt, fr);
05023          res = 0;
05024       } else if (fr->af.frametype == AST_FRAME_VIDEO) {
05025          /* Video frame have no sequence number */
05026          fr->oseqno = -1;
05027          fr->iseqno = -1;
05028          vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr));
05029          vh->zeros = 0;
05030          vh->callno = htons(0x8000 | fr->callno);
05031          vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0));
05032          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr);
05033          fr->data = vh;
05034          fr->retries = -1;
05035          res = send_packet(fr);        
05036       } else {
05037          /* Mini-frames have no sequence number */
05038          fr->oseqno = -1;
05039          fr->iseqno = -1;
05040          /* Mini frame will do */
05041          mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr));
05042          mh->callno = htons(fr->callno);
05043          mh->ts = htons(fr->ts & 0xFFFF);
05044          fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr);
05045          fr->data = mh;
05046          fr->retries = -1;
05047          if (pvt->transferring == TRANSFER_MEDIAPASS)
05048             fr->transfer = 1;
05049          if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
05050             if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
05051                encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen);
05052             } else
05053                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
05054          }
05055          res = send_packet(fr);
05056       }
05057    }
05058    return res;
05059 }

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

Definition at line 3195 of file chan_iax2.c.

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

03196 {
03197    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1);
03198 }

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

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

03191 {
03192    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
03193 }

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

Definition at line 3183 of file chan_iax2.c.

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

03184 {
03185    
03186    return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT,
03187       0, 0, (unsigned char *)text, strlen(text) + 1, -1);
03188 }

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

Definition at line 3900 of file chan_iax2.c.

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

03901 {
03902    struct ast_option_header *h;
03903    int res;
03904 
03905    switch (option) {
03906    case AST_OPTION_TXGAIN:
03907    case AST_OPTION_RXGAIN:
03908       /* these two cannot be sent, because they require a result */
03909       errno = ENOSYS;
03910       return -1;
03911    default:
03912    {
03913       unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
03914       struct chan_iax2_pvt *pvt;
03915 
03916       ast_mutex_lock(&iaxsl[callno]);
03917       pvt = iaxs[callno];
03918 
03919       if (wait_for_peercallno(pvt)) {
03920          ast_mutex_unlock(&iaxsl[callno]);
03921          return -1;
03922       }
03923 
03924       ast_mutex_unlock(&iaxsl[callno]);
03925 
03926       if (!(h = ast_malloc(datalen + sizeof(*h)))) {
03927          return -1;
03928       }
03929 
03930       h->flag = AST_OPTION_FLAG_REQUEST;
03931       h->option = htons(option);
03932       memcpy(h->data, data, datalen);
03933       res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
03934                  AST_CONTROL_OPTION, 0, (unsigned char *) h,
03935                  datalen + sizeof(*h), -1);
03936       ast_free(h);
03937       return res;
03938    }
03939    }
03940 }

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

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

03949 {
03950    int res;
03951    struct iax_ie_data ied0;
03952    struct iax_ie_data ied1;
03953    unsigned int transferid = (unsigned int)ast_random();
03954    memset(&ied0, 0, sizeof(ied0));
03955    iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
03956    iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
03957    iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
03958 
03959    memset(&ied1, 0, sizeof(ied1));
03960    iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
03961    iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
03962    iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
03963    
03964    res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
03965    if (res)
03966       return -1;
03967    res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
03968    if (res)
03969       return -1;
03970    iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03971    iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
03972    return 0;
03973 }

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

Definition at line 4198 of file chan_iax2.c.

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

04199 {
04200    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
04201    struct iax_ie_data ied = { "", };
04202    char tmp[256], *context;
04203    ast_copy_string(tmp, dest, sizeof(tmp));
04204    context = strchr(tmp, '@');
04205    if (context) {
04206       *context = '\0';
04207       context++;
04208    }
04209    iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
04210    if (context)
04211       iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
04212    ast_debug(1, "Transferring '%s' to '%s'\n", c->name, dest);
04213    return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
04214 }

static int iax2_transmit ( struct iax_frame fr  )  [static]

Definition at line 3155 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, iax2_trunk_peer::list, sched_lock, iax_frame::sentyet, and signal_condition().

Referenced by iax2_send().

03156 {
03157    /* Lock the queue and place this packet at the end */
03158    /* By setting this to 0, the network thread will send it for us, and
03159       queue retransmission if necessary */
03160    fr->sentyet = 0;
03161    AST_LIST_LOCK(&frame_queue);
03162    AST_LIST_INSERT_TAIL(&frame_queue, fr, list);
03163    AST_LIST_UNLOCK(&frame_queue);
03164    /* Wake up the network and scheduler thread */
03165    if (netthreadid != AST_PTHREADT_NULL)
03166       pthread_kill(netthreadid, SIGURG);
03167    signal_condition(&sched_lock, &sched_cond);
03168    return 0;
03169 }

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

Definition at line 7543 of file chan_iax2.c.

References iax2_trunk_peer::trunkact.

Referenced by timing_read().

07544 {
07545    /* Drop when trunk is about 5 seconds idle */
07546    if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 
07547       return 1;
07548    return 0;
07549 }

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

Definition at line 4603 of file chan_iax2.c.

References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_tvnow(), 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, ast_iax2_meta_trunk_mini::mini, send_trunk(), 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().

04604 {
04605    struct ast_frame *f;
04606    struct iax2_trunk_peer *tpeer;
04607    void *tmp, *ptr;
04608    struct timeval now;
04609    int res; 
04610    struct ast_iax2_meta_trunk_entry *met;
04611    struct ast_iax2_meta_trunk_mini *mtm;
04612 
04613    f = &fr->af;
04614    tpeer = find_tpeer(&pvt->addr, pvt->sockfd);
04615    if (tpeer) {
04616       if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) {
04617          /* Need to reallocate space */
04618          if (tpeer->trunkdataalloc < trunkmaxsize) {
04619             if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) {
04620                ast_mutex_unlock(&tpeer->lock);
04621                return -1;
04622             }
04623             
04624             tpeer->trunkdataalloc += DEFAULT_TRUNKDATA;
04625             tpeer->trunkdata = tmp;
04626             ast_debug(1, "Expanded trunk '%s:%d' to %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), tpeer->trunkdataalloc);
04627          } else {
04628             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));
04629             ast_mutex_unlock(&tpeer->lock);
04630             return -1;
04631          }
04632       }
04633 
04634       /* Append to meta frame */
04635       ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen;
04636       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) {
04637          mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
04638          mtm->len = htons(f->datalen);
04639          mtm->mini.callno = htons(pvt->callno);
04640          mtm->mini.ts = htons(0xffff & fr->ts);
04641          ptr += sizeof(struct ast_iax2_meta_trunk_mini);
04642          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini);
04643       } else {
04644          met = (struct ast_iax2_meta_trunk_entry *)ptr;
04645          /* Store call number and length in meta header */
04646          met->callno = htons(pvt->callno);
04647          met->len = htons(f->datalen);
04648          /* Advance pointers/decrease length past trunk entry header */
04649          ptr += sizeof(struct ast_iax2_meta_trunk_entry);
04650          tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry);
04651       }
04652       /* Copy actual trunk data */
04653       memcpy(ptr, f->data, f->datalen);
04654       tpeer->trunkdatalen += f->datalen;
04655 
04656       tpeer->calls++;
04657 
04658       /* track the largest mtu we actually have sent */
04659       if (tpeer->trunkdatalen + f->datalen + 4 > trunk_maxmtu) 
04660          trunk_maxmtu = tpeer->trunkdatalen + f->datalen + 4 ; 
04661 
04662       /* if we have enough for a full MTU, ship it now without waiting */
04663       if (global_max_trunk_mtu > 0 && tpeer->trunkdatalen + f->datalen + 4 >= global_max_trunk_mtu) {
04664          now = ast_tvnow();
04665          res = send_trunk(tpeer, &now); 
04666          trunk_untimed ++; 
04667       }
04668 
04669       ast_mutex_unlock(&tpeer->lock);
04670    }
04671    return 0;
04672 }

static int iax2_vnak ( int  callno  )  [static]

Definition at line 7461 of file chan_iax2.c.

References AST_FRAME_IAX, IAX_COMMAND_VNAK, and send_command_immediate().

Referenced by socket_process(), and socket_process_meta().

07462 {
07463    return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno);
07464 }

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

Definition at line 5907 of file chan_iax2.c.

References ast_debug, AST_FRAME_NULL, AST_FRAME_VOICE, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, errno, f, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, PTR_TO_CALLNO, and ast_channel::tech_pvt.

05908 {
05909    unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
05910    int res = -1;
05911    ast_mutex_lock(&iaxsl[callno]);
05912    if (iaxs[callno]) {
05913    /* If there's an outstanding error, return failure now */
05914       if (!iaxs[callno]->error) {
05915          if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
05916             res = 0;
05917             /* Don't waste bandwidth sending null frames */
05918          else if (f->frametype == AST_FRAME_NULL)
05919             res = 0;
05920          else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH))
05921             res = 0;
05922          else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
05923             res = 0;
05924          else
05925          /* Simple, just queue for transmission */
05926             res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
05927       } else {
05928          ast_debug(1, "Write error: %s\n", strerror(errno));
05929       }
05930    }
05931    /* If it's already gone, just return */
05932    ast_mutex_unlock(&iaxsl[callno]);
05933    return res;
05934 }

static int iax_check_version ( char *  dev  )  [static]

Definition at line 2103 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_iax2_firmware_header::devname, iax_firmware::fwh, iax2_trunk_peer::list, and ast_iax2_firmware_header::version.

Referenced by update_registry().

02104 {
02105    int res = 0;
02106    struct iax_firmware *cur = NULL;
02107 
02108    if (ast_strlen_zero(dev))
02109       return 0;
02110 
02111    AST_LIST_LOCK(&firmwares);
02112    AST_LIST_TRAVERSE(&firmwares, cur, list) {
02113       if (!strcmp(dev, (char *)cur->fwh->devname)) {
02114          res = ntohs(cur->fwh->version);
02115          break;
02116       }
02117    }
02118    AST_LIST_UNLOCK(&firmwares);
02119 
02120    return res;
02121 }

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

Definition at line 797 of file chan_iax2.c.

References ast_verbose().

Referenced by load_module().

00798 {
00799    if (iaxdebug)
00800       ast_verbose("%s", data);
00801 }

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

Definition at line 803 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by load_module().

00804 {
00805    ast_log(LOG_WARNING, "%s", data);
00806 }

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

Definition at line 2123 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_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, and iax2_trunk_peer::list.

Referenced by socket_process().

02124 {
02125    int res = -1;
02126    unsigned int bs = desc & 0xff;
02127    unsigned int start = (desc >> 8) & 0xffffff;
02128    unsigned int bytes;
02129    struct iax_firmware *cur;
02130 
02131    if (ast_strlen_zero((char *)dev) || !bs)
02132       return -1;
02133 
02134    start *= bs;
02135    
02136    AST_LIST_LOCK(&firmwares);
02137    AST_LIST_TRAVERSE(&firmwares, cur, list) {
02138       if (strcmp((char *)dev, (char *)cur->fwh->devname))
02139          continue;
02140       iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
02141       if (start < ntohl(cur->fwh->datalen)) {
02142          bytes = ntohl(cur->fwh->datalen) - start;
02143          if (bytes > bs)
02144             bytes = bs;
02145          iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
02146       } else {
02147          bytes = 0;
02148          iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
02149       }
02150       if (bytes == bs)
02151          res = 0;
02152       else
02153          res = 1;
02154       break;
02155    }
02156    AST_LIST_UNLOCK(&firmwares);
02157 
02158    return res;
02159 }

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

Definition at line 7720 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_free, ast_hangup(), ast_log(), ast_pthread_create_detached_background, AST_STATE_DOWN, ast_channel::context, ast_channel::exten, iax_park_thread(), LOG_WARNING, ast_channel::name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.

Referenced by socket_process().

07721 {
07722    struct iax_dual *d;
07723    struct ast_channel *chan1m, *chan2m;
07724    pthread_t th;
07725    chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
07726    chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
07727    if (chan2m && chan1m) {
07728       /* Make formats okay */
07729       chan1m->readformat = chan1->readformat;
07730       chan1m->writeformat = chan1->writeformat;
07731       ast_channel_masquerade(chan1m, chan1);
07732       /* Setup the extensions and such */
07733       ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
07734       ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
07735       chan1m->priority = chan1->priority;
07736       
07737       /* We make a clone of the peer channel too, so we can play
07738          back the announcement */
07739       /* Make formats okay */
07740       chan2m->readformat = chan2->readformat;
07741       chan2m->writeformat = chan2->writeformat;
07742       ast_channel_masquerade(chan2m, chan2);
07743       /* Setup the extensions and such */
07744       ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
07745       ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
07746       chan2m->priority = chan2->priority;
07747       if (ast_do_masquerade(chan2m)) {
07748          ast_log(LOG_WARNING, "Masquerade failed :(\n");
07749          ast_hangup(chan2m);
07750          return -1;
07751       }
07752    } else {
07753       if (chan1m)
07754          ast_hangup(chan1m);
07755       if (chan2m)
07756          ast_hangup(chan2m);
07757       return -1;
07758    }
07759    if ((d = ast_calloc(1, sizeof(*d)))) {
07760       d->chan1 = chan1m;
07761       d->chan2 = chan2m;
07762       if (!ast_pthread_create_detached_background(&th, NULL, iax_park_thread, d)) {
07763          return 0;
07764       }
07765       ast_free(d);
07766    }
07767    return -1;
07768 }

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

Definition at line 7700 of file chan_iax2.c.

References ast_free, ast_frfree, ast_hangup(), ast_log(), ast_park_call(), ast_read(), iax_dual::chan1, iax_dual::chan2, ext, f, and LOG_NOTICE.

Referenced by iax_park().

07701 {
07702    struct ast_channel *chan1, *chan2;
07703    struct iax_dual *d;
07704    struct ast_frame *f;
07705    int ext;
07706    int res;
07707    d = stuff;
07708    chan1 = d->chan1;
07709    chan2 = d->chan2;
07710    ast_free(d);
07711    f = ast_read(chan1);
07712    if (f)
07713       ast_frfree(f);
07714    res = ast_park_call(chan1, chan2, 0, &ext);
07715    ast_hangup(chan2);
07716    ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext);
07717    return NULL;
07718 }

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

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

01523 {
01524    struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable);
01525    if (new) {
01526       size_t afdatalen = new->afdatalen;
01527       memcpy(new, fr, sizeof(*new));
01528       iax_frame_wrap(new, &fr->af);
01529       new->afdatalen = afdatalen;
01530       new->data = NULL;
01531       new->datalen = 0;
01532       new->direction = DIRECTION_INGRESS;
01533       new->retrans = -1;
01534    }
01535    return new;
01536 }

static void insert_idle_thread ( struct iax2_thread thread  )  [static]

Definition at line 1045 of file chan_iax2.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, IAX_THREAD_TYPE_DYNAMIC, iax2_trunk_peer::list, and thread.

Referenced by iax2_process_thread().

01046 {
01047    if (thread->type == IAX_THREAD_TYPE_DYNAMIC) {
01048       AST_LIST_LOCK(&dynamic_list);
01049       AST_LIST_INSERT_TAIL(&dynamic_list, thread, list);
01050       AST_LIST_UNLOCK(&dynamic_list);
01051    } else {
01052       AST_LIST_LOCK(&idle_list);
01053       AST_LIST_INSERT_TAIL(&idle_list, thread, list);
01054       AST_LIST_UNLOCK(&idle_list);
01055    }
01056 
01057    return;
01058 }

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

Definition at line 832 of file chan_iax2.c.

References ast_verbose().

Referenced by handle_cli_iax2_set_debug_jb(), and handle_cli_iax2_set_debug_jb_deprecated().

00833 {
00834    va_list args;
00835    char buf[1024];
00836 
00837    va_start(args, fmt);
00838    vsnprintf(buf, sizeof(buf), fmt, args);
00839    va_end(args);
00840 
00841    ast_verbose("%s", buf);
00842 }

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

Definition at line 808 of file chan_iax2.c.

References ast_log(), and LOG_ERROR.

Referenced by handle_cli_iax2_set_debug_jb(), handle_cli_iax2_set_debug_jb_deprecated(), and load_module().

00809 {
00810    va_list args;
00811    char buf[1024];
00812 
00813    va_start(args, fmt);
00814    vsnprintf(buf, sizeof(buf), fmt, args);
00815    va_end(args);
00816 
00817    ast_log(LOG_ERROR, "%s", buf);
00818 }

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

Definition at line 820 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by handle_cli_iax2_set_debug_jb(), handle_cli_iax2_set_debug_jb_deprecated(), and load_module().

00821 {
00822    va_list args;
00823    char buf[1024];
00824 
00825    va_start(args, fmt);
00826    vsnprintf(buf, sizeof(buf), fmt, args);
00827    va_end(args);
00828 
00829    ast_log(LOG_WARNING, "%s", buf);
00830 }

static int load_module ( void   )  [static]

Load IAX2 module, load configuraiton ---.

Definition at line 12398 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_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_register_application, ast_register_switch(), ast_verb, cli_iax2, config, iax2_registry::entry, errno, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, 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(), iax_transfercallno_pvts, iaxpeer_function, iaxvar_function, io, io_context_create(), io_context_destroy(), jb_error_output(), jb_setoutput(), jb_warning_output(), LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, netsock, outsock, papp, pdescrip, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), psyn, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched, sched_context_create(), sched_context_destroy(), set_config(), start_network_thread(), transfercallno_pvt_cmp_cb(), transfercallno_pvt_hash_cb(), user_cmp_cb(), and user_hash_cb().

12399 {
12400    char *config = "iax.conf";
12401    int x = 0;
12402    struct iax2_registry *reg = NULL;
12403 
12404    peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
12405    if (!peers)
12406       return AST_MODULE_LOAD_FAILURE;
12407    users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb);
12408    if (!users) {
12409       ao2_ref(peers, -1);
12410       return AST_MODULE_LOAD_FAILURE;
12411    }
12412    iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
12413    if (!iax_peercallno_pvts) {
12414       ao2_ref(peers, -1);
12415       ao2_ref(users, -1);
12416       return AST_MODULE_LOAD_FAILURE;
12417    }
12418    iax_transfercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, transfercallno_pvt_hash_cb, transfercallno_pvt_cmp_cb);
12419    if (!iax_transfercallno_pvts) {
12420       ao2_ref(peers, -1);
12421       ao2_ref(users, -1);
12422       ao2_ref(iax_peercallno_pvts, -1);
12423       return AST_MODULE_LOAD_FAILURE;
12424    }
12425    ast_custom_function_register(&iaxpeer_function);
12426    ast_custom_function_register(&iaxvar_function);
12427 
12428    iax_set_output(iax_debug_output);
12429    iax_set_error(iax_error_output);
12430    jb_setoutput(jb_error_output, jb_warning_output, NULL);
12431    
12432 #ifdef HAVE_DAHDI
12433 #ifdef DAHDI_TIMERACK
12434    timingfd = open("/dev/dahdi/timer", O_RDWR);
12435    if (timingfd < 0)
12436 #endif
12437       timingfd = open("/dev/dahdi/pseudo", O_RDWR);
12438    if (timingfd < 0) 
12439       ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
12440 #endif      
12441 
12442    memset(iaxs, 0, sizeof(iaxs));
12443 
12444    for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
12445       ast_mutex_init(&iaxsl[x]);
12446    }
12447 
12448    ast_cond_init(&sched_cond, NULL);
12449 
12450    if (!(sched = sched_context_create())) {
12451       ast_log(LOG_ERROR, "Failed to create scheduler context\n");
12452       return AST_MODULE_LOAD_FAILURE;
12453    }
12454 
12455    if (!(io = io_context_create())) {
12456       ast_log(LOG_ERROR, "Failed to create I/O context\n");
12457       sched_context_destroy(sched);
12458       return AST_MODULE_LOAD_FAILURE;
12459    }
12460 
12461    if (!(netsock = ast_netsock_list_alloc())) {
12462       ast_log(LOG_ERROR, "Failed to create netsock list\n");
12463       io_context_destroy(io);
12464       sched_context_destroy(sched);
12465       return AST_MODULE_LOAD_FAILURE;
12466    }
12467    ast_netsock_init(netsock);
12468    
12469    outsock = ast_netsock_list_alloc();
12470    if (!outsock) {
12471       ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
12472       io_context_destroy(io);
12473       sched_context_destroy(sched);
12474       return AST_MODULE_LOAD_FAILURE;
12475    }
12476    ast_netsock_init(outsock);
12477 
12478    ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));
12479 
12480    ast_register_application(papp, iax2_prov_app, psyn, pdescrip);
12481    
12482    ast_manager_register( "IAXpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peers, "List IAX Peers" );
12483    ast_manager_register( "IAXpeerlist", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peer_list, "List IAX Peers" );
12484    ast_manager_register( "IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats, "Show IAX Netstats" );
12485 
12486    if(set_config(config, 0) == -1)
12487       return AST_MODULE_LOAD_DECLINE;
12488 
12489    if (ast_channel_register(&iax2_tech)) {
12490       ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2");
12491       __unload_module();
12492       return AST_MODULE_LOAD_FAILURE;
12493    }
12494 
12495    if (ast_register_switch(&iax2_switch)) 
12496       ast_log(LOG_ERROR, "Unable to register IAX switch\n");
12497 
12498    if (start_network_thread()) {
12499       ast_log(LOG_ERROR, "Unable to start network thread\n");
12500       __unload_module();
12501       return AST_MODULE_LOAD_FAILURE;
12502    } else
12503       ast_verb(2, "IAX Ready and Listening\n");
12504 
12505    AST_LIST_LOCK(&registrations);
12506    AST_LIST_TRAVERSE(&registrations, reg, entry)
12507       iax2_do_register(reg);
12508    AST_LIST_UNLOCK(&registrations); 
12509    
12510    ao2_callback(peers, 0, peer_set_sock_cb, NULL);
12511    ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
12512 
12513 
12514    reload_firmware(0);
12515    iax_provision_reload(0);
12516 
12517    return AST_MODULE_LOAD_SUCCESS;
12518 }

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

Definition at line 3975 of file chan_iax2.c.

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

Referenced by iax2_bridge().

03976 {
03977    ast_mutex_lock(&iaxsl[callno0]);
03978    while (ast_mutex_trylock(&iaxsl[callno1])) {
03979       DEADLOCK_AVOIDANCE(&iaxsl[callno0]);
03980    }
03981 }

static void log_jitterstats ( unsigned short  callno  )  [static]

Definition at line 7843 of file chan_iax2.c.

References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, jb_info::current, EVENT_FLAG_REPORTING, jb_info::frames_dropped, jb_info::frames_in, jb_info::frames_lost, jb_info::frames_ooo, IAX_USEJITTERBUF, ast_channel::jb, jb_getinfo(), jb_info::jitter, jb_info::losspct, manager_event, and jb_info::min.

Referenced by socket_process().

07844 {
07845    int localjitter = -1, localdelay = 0, locallost = -1, locallosspct = -1, localdropped = 0, localooo = -1, localpackets = -1;
07846    jb_info jbinfo;
07847 
07848    ast_mutex_lock(&iaxsl[callno]);
07849    if (iaxs[callno] && iaxs[callno]->owner && iaxs[callno]->owner->name) {
07850       if(ast_test_flag(iaxs[callno], IAX_USEJITTERBUF)) {
07851          jb_getinfo(iaxs[callno]->jb, &jbinfo);
07852          localjitter = jbinfo.jitter;
07853          localdelay = jbinfo.current - jbinfo.min;
07854          locallost = jbinfo.frames_lost;
07855          locallosspct = jbinfo.losspct/1000;
07856          localdropped = jbinfo.frames_dropped;
07857          localooo = jbinfo.frames_ooo;
07858          localpackets = jbinfo.frames_in;
07859       }
07860       ast_debug(3, "JB STATS:%s ping=%d ljitterms=%d ljbdelayms=%d ltotlost=%d lrecentlosspct=%d ldropped=%d looo=%d lrecvd=%d rjitterms=%d rjbdelayms=%d rtotlost=%d rrecentlosspct=%d rdropped=%d rooo=%d rrecvd=%d\n",
07861          iaxs[callno]->owner->name,
07862          iaxs[callno]->pingtime,
07863          localjitter,
07864          localdelay,
07865          locallost,
07866          locallosspct,
07867          localdropped,
07868          localooo,
07869          localpackets,
07870          iaxs[callno]->remote_rr.jitter,
07871          iaxs[callno]->remote_rr.delay,
07872          iaxs[callno]->remote_rr.losscnt,
07873          iaxs[callno]->remote_rr.losspct/1000,
07874          iaxs[callno]->remote_rr.dropped,
07875          iaxs[callno]->remote_rr.ooo,
07876          iaxs[callno]->remote_rr.packets);
07877       manager_event(EVENT_FLAG_REPORTING, "JitterBufStats", "Owner: %s\r\nPing: %d\r\nLocalJitter: %d\r\nLocalJBDelay: %d\r\nLocalTotalLost: %d\r\nLocalLossPercent: %d\r\nLocalDropped: %d\r\nLocalooo: %d\r\nLocalReceived: %d\r\nRemoteJitter: %d\r\nRemoteJBDelay: %d\r\nRemoteTotalLost: %d\r\nRemoteLossPercent: %d\r\nRemoteDropped: %d\r\nRemoteooo: %d\r\nRemoteReceived: %d\r\n",
07878          iaxs[callno]->owner->name,
07879          iaxs[callno]->pingtime,
07880          localjitter,
07881          localdelay,
07882          locallost,
07883          locallosspct,
07884          localdropped,
07885          localooo,
07886          localpackets,
07887          iaxs[callno]->remote_rr.jitter,
07888          iaxs[callno]->remote_rr.delay,
07889          iaxs[callno]->remote_rr.losscnt,
07890          iaxs[callno]->remote_rr.losspct/1000,
07891          iaxs[callno]->remote_rr.dropped,
07892          iaxs[callno]->remote_rr.ooo,
07893          iaxs[callno]->remote_rr.packets);
07894    }
07895    ast_mutex_unlock(&iaxsl[callno]);
07896 }

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

Definition at line 1593 of file chan_iax2.c.

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

Referenced by iax2_request(), and socket_process().

01594 {
01595    int x;
01596    int res= 0;
01597    struct timeval now = ast_tvnow();
01598    if (iaxs[callno]->oseqno) {
01599       ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n");
01600       return -1;
01601    }
01602    if (callno & TRUNK_CALL_START) {
01603       ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno);
01604       return -1;
01605    }
01606    for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
01607       ast_mutex_lock(&iaxsl[x]);
01608       if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
01609          /*!
01610           * \note We delete these before switching the slot, because if
01611           * they fire in the meantime, they will generate a warning.
01612           */
01613          AST_SCHED_DEL(sched, iaxs[callno]->pingid);
01614          AST_SCHED_DEL(sched, iaxs[callno]->lagid);
01615          iaxs[x] = iaxs[callno];
01616          iaxs[x]->callno = x;
01617          iaxs[callno] = NULL;
01618          /* Update the two timers that should have been started */
01619          iaxs[x]->pingid = iax2_sched_add(sched, 
01620             ping_time * 1000, send_ping, (void *)(long)x);
01621          iaxs[x]->lagid = iax2_sched_add(sched, 
01622             lagrq_time * 1000, send_lagrq, (void *)(long)x);
01623          if (locked)
01624             ast_mutex_unlock(&iaxsl[callno]);
01625          res = x;
01626          if (!locked)
01627             ast_mutex_unlock(&iaxsl[x]);
01628          break;
01629       }
01630       ast_mutex_unlock(&iaxsl[x]);
01631    }
01632    if (x >= ARRAY_LEN(iaxs) - 1) {
01633       ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
01634       return -1;
01635    }
01636    ast_debug(1, "Made call %d into trunk call %d\n", callno, x);
01637    /* We move this call from a non-trunked to a trunked call */
01638    update_max_trunk();
01639    update_max_nontrunk();
01640    return res;
01641 }

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

Definition at line 5423 of file chan_iax2.c.

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

Referenced by load_module().

05424 {
05425    ast_cli_netstats(s, -1, 0);
05426    astman_append(s, "\r\n");
05427    return RESULT_SUCCESS;
05428 }

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

callback to display iax peers in manager format

Definition at line 5475 of file chan_iax2.c.

References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), IAX_DYNAMIC, iax2_peer::mask, iax2_peer::name, peer_status(), peer_unref(), RESULT_SUCCESS, s, status, and iax2_peer::username.

Referenced by load_module().

05476 {
05477    struct iax2_peer *peer = NULL;
05478    int peer_count = 0;
05479    char nm[20];
05480    char status[20];
05481    const char *id = astman_get_header(m,"ActionID");
05482    char idtext[256] = "";
05483    struct ao2_iterator i;
05484 
05485    if (!ast_strlen_zero(id))
05486       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
05487 
05488    astman_append(s, "Response: Success\r\n%sMessage: IAX Peer status list will follow\r\n\r\n", idtext);
05489 
05490 
05491    i = ao2_iterator_init(peers, 0);
05492    for (peer = ao2_iterator_next(&i); peer; peer_unref(peer), peer = ao2_iterator_next(&i)) {
05493 
05494       astman_append(s, "Event: PeerEntry\r\n%sChanneltype: IAX\r\n", idtext);
05495       if (!ast_strlen_zero(peer->username)) {
05496          astman_append(s, "ObjectName: %s\r\nObjectUsername: %s\r\n", peer->name, peer->username);
05497       } else {
05498          astman_append(s, "ObjectName: %s\r\n", peer->name);
05499       }
05500       astman_append(s, "ChanObjectType: peer\r\n");
05501       astman_append(s, "IPaddress: %s\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-");
05502       ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm));
05503       astman_append(s, "Mask: %s\r\n", nm);
05504       astman_append(s, "Port: %d\r\n", ntohs(peer->addr.sin_port));
05505       astman_append(s, "Dynamic: %s\r\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No");
05506       peer_status(peer, status, sizeof(status));
05507       astman_append(s, "Status: %s\r\n\r\n", status);
05508       peer_count++;
05509    }
05510 
05511    astman_append(s, "Event: PeerlistComplete\r\n%sListItems: %d\r\n\r\n", idtext, peer_count);
05512    return RESULT_SUCCESS;
05513 }

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

callback to display iax peers in manager

Definition at line 5462 of file chan_iax2.c.

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

Referenced by load_module().

05463 {
05464    char *a[] = { "iax2", "show", "users" };
05465    const char *id = astman_get_header(m,"ActionID");
05466    char idtext[256] = "";
05467 
05468    if (!ast_strlen_zero(id))
05469       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
05470    astman_send_ack(s, m, "Peer status list will follow");
05471    return __iax2_show_peers(1, -1, s, 3, a );
05472 } 

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

Definition at line 1542 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(), lua_find_extension(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and transfercallno_pvt_cmp_cb().

01543 {
01544    if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01545       (cur->addr.sin_port == sin->sin_port)) {
01546       /* This is the main host */
01547       if ( (cur->peercallno == 0 || cur->peercallno == callno) &&
01548           (check_dcallno ? dcallno == cur->callno : 1) ) {
01549          /* That's us.  Be sure we keep track of the peer call number */
01550          return 1;
01551       }
01552    }
01553    if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) &&
01554        (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) {
01555       /* We're transferring */
01556       if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno))
01557          return 1;
01558    }
01559    return 0;
01560 }

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

Definition at line 4702 of file chan_iax2.c.

References ast_aes_decrypt, ast_log(), and LOG_WARNING.

Referenced by decode_frame().

04703 {
04704 #if 0
04705    /* Debug with "fake encryption" */
04706    int x;
04707    if (len % 16)
04708       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04709    for (x=0;x<len;x++)
04710       dst[x] = src[x] ^ 0xff;
04711 #else 
04712    unsigned char lastblock[16] = { 0 };
04713    int x;
04714    while(len > 0) {
04715       ast_aes_decrypt(src, dst, dcx);
04716       for (x=0;x<16;x++)
04717          dst[x] ^= lastblock[x];
04718       memcpy(lastblock, src, sizeof(lastblock));
04719       dst += 16;
04720       src += 16;
04721       len -= 16;
04722    }
04723 #endif
04724 }

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

Definition at line 4726 of file chan_iax2.c.

References ast_aes_encrypt, ast_log(), and LOG_WARNING.

Referenced by encrypt_frame().

04727 {
04728 #if 0
04729    /* Debug with "fake encryption" */
04730    int x;
04731    if (len % 16)
04732       ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
04733    for (x=0;x<len;x++)
04734       dst[x] = src[x] ^ 0xff;
04735 #else
04736    unsigned char curblock[16] = { 0 };
04737    int x;
04738    while(len > 0) {
04739       for (x=0;x<16;x++)
04740          curblock[x] ^= src[x];
04741       ast_aes_encrypt(curblock, dst, ecx);
04742       memcpy(curblock, dst, sizeof(curblock)); 
04743       dst += 16;
04744       src += 16;
04745       len -= 16;
04746    }
04747 #endif
04748 }

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

Definition at line 6242 of file chan_iax2.c.

References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.

Referenced by authenticate_reply(), and socket_process().

06243 {
06244    /* Select exactly one common encryption if there are any */
06245    p->encmethods &= enc;
06246    if (p->encmethods) {
06247       if (p->encmethods & IAX_ENCRYPT_AES128)
06248          p->encmethods = IAX_ENCRYPT_AES128;
06249       else
06250          p->encmethods = 0;
06251    }
06252 }

static void mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 979 of file chan_iax2.c.

00980 {
00981    /* The MWI subscriptions exist just so the core knows we care about those
00982     * mailboxes.  However, we just grab the events out of the cache when it
00983     * is time to send MWI, since it is only sent with a REGACK. */
00984 }

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

Definition at line 10362 of file chan_iax2.c.

References ast_debug, 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_mutex_trylock(), ast_mutex_unlock(), attempt_transmit(), f, iax2_sched_add(), iax_frame_free(), io, iax_frame::list, sched, send_packet(), and timing_read().

Referenced by start_network_thread().

10363 {
10364    /* Our job is simple: Send queued messages, retrying if necessary.  Read frames 
10365       from the network, and queue them for delivery to the channels */
10366    int res, count, wakeup;
10367    struct iax_frame *f;
10368 
10369    if (timingfd > -1)
10370       ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL);
10371    
10372    for(;;) {
10373       pthread_testcancel();
10374 
10375       /* Go through the queue, sending messages which have not yet been
10376          sent, and scheduling retransmissions if appropriate */
10377       AST_LIST_LOCK(&frame_queue);
10378       count = 0;
10379       wakeup = -1;
10380       AST_LIST_TRAVERSE_SAFE_BEGIN(&frame_queue, f, list) {
10381          if (f->sentyet)
10382             continue;
10383          
10384          /* Try to lock the pvt, if we can't... don't fret - defer it till later */
10385          if (ast_mutex_trylock(&iaxsl[f->callno])) {
10386             wakeup = 1;
10387             continue;
10388          }
10389 
10390          f->sentyet = 1;
10391 
10392          if (iaxs[f->callno]) {
10393             send_packet(f);
10394             count++;
10395          } 
10396 
10397          ast_mutex_unlock(&iaxsl[f->callno]);
10398 
10399          if (f->retries < 0) {
10400             /* This is not supposed to be retransmitted */
10401             AST_LIST_REMOVE_CURRENT(list);
10402             /* Free the iax frame */
10403             iax_frame_free(f);
10404          } else {
10405             /* We need reliable delivery.  Schedule a retransmission */
10406             f->retries++;
10407             f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f);
10408          }
10409       }
10410       AST_LIST_TRAVERSE_SAFE_END;
10411       AST_LIST_UNLOCK(&frame_queue);
10412 
10413       pthread_testcancel();
10414       if (count >= 20)
10415          ast_debug(1, "chan_iax2: Sent %d queued outbound frames all at once\n", count);
10416 
10417       /* Now do the IO, and run scheduled tasks */
10418       res = ast_io_wait(io, wakeup);
10419       if (res >= 0) {
10420          if (res >= 20)
10421             ast_debug(1, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res);
10422       }
10423    }
10424    return NULL;
10425 }

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

Definition at line 1484 of file chan_iax2.c.

References ao2_alloc(), ao2_ref(), AST_LIST_HEAD_INIT_NOLOCK, 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(), jb_conf::resync_threshold, and jb_conf::target_extra.

Referenced by __find_callno().

01485 {
01486    struct chan_iax2_pvt *tmp;
01487    jb_conf jbconf;
01488 
01489    if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) {
01490       return NULL;
01491    }
01492 
01493    if (ast_string_field_init(tmp, 32)) {
01494       ao2_ref(tmp, -1);
01495       tmp = NULL;
01496       return NULL;
01497    }
01498       
01499    tmp->prefs = prefs;
01500    tmp->pingid = -1;
01501    tmp->lagid = -1;
01502    tmp->autoid = -1;
01503    tmp->authid = -1;
01504    tmp->initid = -1;
01505 
01506    ast_string_field_set(tmp,exten, "s");
01507    ast_string_field_set(tmp,host, host);
01508 
01509    tmp->jb = jb_new();
01510    tmp->jbid = -1;
01511    jbconf.max_jitterbuf = maxjitterbuffer;
01512    jbconf.resync_threshold = resyncthreshold;
01513    jbconf.max_contig_interp = maxjitterinterps;
01514    jbconf.target_extra = jittertargetextra;
01515    jb_setconf(tmp->jb,&jbconf);
01516 
01517    AST_LIST_HEAD_INIT_NOLOCK(&tmp->dpentries);
01518 
01519    return tmp;
01520 }

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

References ast_strip_quoted(), ast_strlen_zero(), parsed_dial_string::context, parsed_dial_string::exten, parsed_dial_string::key, parsed_dial_string::options, parsed_dial_string::password, parsed_dial_string::peer, parsed_dial_string::port, strsep(), and parsed_dial_string::username.

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

03603 {
03604    if (ast_strlen_zero(data))
03605       return;
03606 
03607    pds->peer = strsep(&data, "/");
03608    pds->exten = strsep(&data, "/");
03609    pds->options = data;
03610 
03611    if (pds->exten) {
03612       data = pds->exten;
03613       pds->exten = strsep(&data, "@");
03614       pds->context = data;
03615    }
03616 
03617    if (strchr(pds->peer, '@')) {
03618       data = pds->peer;
03619       pds->username = strsep(&data, "@");
03620       pds->peer = data;
03621    }
03622 
03623    if (pds->username) {
03624       data = pds->username;
03625       pds->username = strsep(&data, ":");
03626       pds->password = data;
03627    }
03628 
03629    data = pds->peer;
03630    pds->peer = strsep(&data, ":");
03631    pds->port = data;
03632 
03633    /* check for a key name wrapped in [] in the secret position, if found,
03634       move it to the key field instead
03635    */
03636    if (pds->password && (pds->password[0] == '[')) {
03637       pds->key = ast_strip_quoted(pds->password, "[", "]");
03638       pds->password = NULL;
03639    }
03640 }

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

References CMP_MATCH, and iax2_peer::name.

Referenced by load_module().

01291 {
01292    struct iax2_peer *peer = obj, *peer2 = arg;
01293 
01294    return !strcmp(peer->name, peer2->name) ? CMP_MATCH : 0;
01295 }

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

Definition at line 11059 of file chan_iax2.c.

References ast_set_flag, and IAX_DELME.

Referenced by delete_users().

11060 {
11061    struct iax2_peer *peer = obj;
11062 
11063    ast_set_flag(peer, IAX_DELME);
11064 
11065    return 0;
11066 }

static void peer_destructor ( void *  obj  )  [static]

Definition at line 10578 of file chan_iax2.c.

References ast_dnsmgr_release(), ast_event_unsubscribe(), 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(), iax2_peer::mwi_event_sub, and register_peer_exten().

Referenced by build_peer().

10579 {
10580    struct iax2_peer *peer = obj;
10581    int callno = peer->callno;
10582 
10583    ast_free_ha(peer->ha);
10584 
10585    if (callno > 0) {
10586       ast_mutex_lock(&iaxsl[callno]);
10587       iax2_destroy(callno);
10588       ast_mutex_unlock(&iaxsl[callno]);
10589    }
10590 
10591    register_peer_exten(peer, 0);
10592 
10593    if (peer->dnsmgr)
10594       ast_dnsmgr_release(peer->dnsmgr);
10595 
10596    if (peer->mwi_event_sub)
10597       ast_event_unsubscribe(peer->mwi_event_sub);
10598 
10599    ast_string_field_free_memory(peer);
10600 }

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

References ast_str_hash(), and iax2_peer::name.

Referenced by load_module().

01281 {
01282    const struct iax2_peer *peer = obj;
01283 
01284    return ast_str_hash(peer->name);
01285 }

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

Definition at line 1337 of file chan_iax2.c.

References ao2_ref().

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

01338 {
01339    ao2_ref(peer, +1);
01340    return peer;
01341 }

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

Definition at line 12352 of file chan_iax2.c.

References iax2_peer::sockfd.

Referenced by load_module().

12353 {
12354    struct iax2_peer *peer = obj;
12355 
12356    if (peer->sockfd < 0)
12357       peer->sockfd = defaultsockfd;
12358 
12359    return 0;
12360 }

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

References ast_debug, 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, outsock, socket_read(), iax2_peer::sockfd, and strsep().

Referenced by build_peer().

10507 {
10508    struct sockaddr_in sin;
10509    int nonlocal = 1;
10510    int port = IAX_DEFAULT_PORTNO;
10511    int sockfd = defaultsockfd;
10512    char *tmp;
10513    char *addr;
10514    char *portstr;
10515 
10516    if (!(tmp = ast_strdupa(srcaddr)))
10517       return -1;
10518 
10519    addr = strsep(&tmp, ":");
10520    portstr = tmp;
10521 
10522    if (portstr) {
10523       port = atoi(portstr);
10524       if (port < 1)
10525          port = IAX_DEFAULT_PORTNO;
10526    }
10527    
10528    if (!ast_get_ip(&sin, addr)) {
10529       struct ast_netsock *sock;
10530       int res;
10531 
10532       sin.sin_port = 0;
10533       sin.sin_family = AF_INET;
10534       res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin));
10535       if (res == 0) {
10536          /* ip address valid. */
10537          sin.sin_port = htons(port);
10538          if (!(sock = ast_netsock_find(netsock, &sin)))
10539             sock = ast_netsock_find(outsock, &sin);
10540          if (sock) {
10541             sockfd = ast_netsock_sockfd(sock);
10542             nonlocal = 0;
10543          } else {
10544             unsigned int orig_saddr = sin.sin_addr.s_addr;
10545             /* INADDR_ANY matches anyway! */
10546             sin.sin_addr.s_addr = INADDR_ANY;
10547             if (ast_netsock_find(netsock, &sin)) {
10548                sin.sin_addr.s_addr = orig_saddr;
10549                sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, cos, socket_read, NULL);
10550                if (sock) {
10551                   sockfd = ast_netsock_sockfd(sock);
10552                   ast_netsock_unref(sock);
10553                   nonlocal = 0;
10554                } else {
10555                   nonlocal = 2;
10556                }
10557             }
10558          }
10559       }
10560    }
10561       
10562    peer->sockfd = sockfd;
10563 
10564    if (nonlocal == 1) {
10565       ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n",
10566          srcaddr, peer->name);
10567       return -1;
10568         } else if (nonlocal == 2) {
10569       ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n",
10570          srcaddr, peer->name);
10571          return -1;
10572    } else {
10573       ast_debug(1, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name);
10574       return 0;
10575    }
10576 }

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

peer_status: Report Peer status in character string

Definition at line 2652 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(), handle_cli_iax2_show_peer(), and manager_iax2_show_peer_list().

02653 {
02654    int res = 0;
02655    if (peer->maxms) {
02656       if (peer->lastms < 0) {
02657          ast_copy_string(status, "UNREACHABLE", statuslen);
02658       } else if (peer->lastms > peer->maxms) {
02659          snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms);
02660          res = 1;
02661       } else if (peer->lastms) {
02662          snprintf(status, statuslen, "OK (%d ms)", peer->lastms);
02663          res = 1;
02664       } else {
02665          ast_copy_string(status, "UNKNOWN", statuslen);
02666       }
02667    } else { 
02668       ast_copy_string(status, "Unmonitored", statuslen);
02669       res = -1;
02670    }
02671    return res;
02672 }

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

Definition at line 1343 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(), complete_iax2_unregister(), create_addr(), function_iaxpeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), manager_iax2_show_peer_list(), poke_all_peers(), prune_peers(), reg_source_db(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().

01344 {
01345    ao2_ref(peer, -1);
01346    return NULL;
01347 }

static void poke_all_peers ( void   )  [static]

Definition at line 11556 of file chan_iax2.c.

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

Referenced by reload_config().

11557 {
11558    struct ao2_iterator i;
11559    struct iax2_peer *peer;
11560 
11561    i = ao2_iterator_init(peers, 0);
11562    while ((peer = ao2_iterator_next(&i))) {
11563       iax2_poke_peer(peer, 0);
11564       peer_unref(peer);
11565    }
11566 }

static void prune_peers ( void   )  [static]

Definition at line 11119 of file chan_iax2.c.

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

11120 {
11121    struct iax2_peer *peer;
11122    struct ao2_iterator i;
11123 
11124    i = ao2_iterator_init(peers, 0);
11125    while ((peer = ao2_iterator_next(&i))) {
11126       if (ast_test_flag(peer, IAX_DELME) || ast_test_flag(peer, IAX_RTCACHEFRIENDS)) {
11127          unlink_peer(peer);
11128       }
11129       peer_unref(peer);
11130    }
11131 }

static void prune_users ( void   )  [static]

Definition at line 11104 of file chan_iax2.c.

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

Referenced by handle_cli_iax2_prune_realtime(), and reload_config().

11105 {
11106    struct iax2_user *user;
11107    struct ao2_iterator i;
11108 
11109    i = ao2_iterator_init(users, 0);
11110    while ((user = ao2_iterator_next(&i))) {
11111       if (ast_test_flag(user, IAX_DELME) || ast_test_flag(user, IAX_RTCACHEFRIENDS)) {
11112          ao2_unlink(users, user);
11113       }
11114       user_unref(user);
11115    }
11116 }

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

Definition at line 12369 of file chan_iax2.c.

References CMP_MATCH, chan_iax2_pvt::frames_received, and match().

12370 {
12371    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
12372 
12373    /* The frames_received field is used to hold whether we're matching
12374     * against a full frame or not ... */
12375 
12376    return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 
12377       pvt2->frames_received) ? CMP_MATCH : 0;
12378 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1445 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, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, iax2_trunk_peer::list, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, and chan_iax2_pvt::vars.

01446 {
01447    struct chan_iax2_pvt *pvt = obj;
01448    struct iax_frame *cur = NULL;
01449 
01450    iax2_destroy_helper(pvt);
01451 
01452    /* Already gone */
01453    ast_set_flag(pvt, IAX_ALREADYGONE); 
01454 
01455    AST_LIST_LOCK(&frame_queue);
01456    AST_LIST_TRAVERSE(&frame_queue, cur, list) {
01457       /* Cancel any pending transmissions */
01458       if (cur->callno == pvt->callno) { 
01459          cur->retries = -1;
01460       }
01461    }
01462    AST_LIST_UNLOCK(&frame_queue);
01463 
01464    if (pvt->reg) {
01465       pvt->reg->callno = 0;
01466    }
01467 
01468    if (!pvt->owner) {
01469       jb_frame frame;
01470       if (pvt->vars) {
01471           ast_variables_destroy(pvt->vars);
01472           pvt->vars = NULL;
01473       }
01474 
01475       while (jb_getall(pvt->jb, &frame) == JB_OK) {
01476          iax2_frame_free(frame.data);
01477       }
01478 
01479       jb_destroy(pvt->jb);
01480       ast_string_field_free_memory(pvt);
01481    }
01482 }

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

Definition at line 12362 of file chan_iax2.c.

References chan_iax2_pvt::peercallno.

12363 {
12364    const struct chan_iax2_pvt *pvt = obj;
12365 
12366    return pvt->peercallno;
12367 }

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

Definition at line 6222 of file chan_iax2.c.

References ast_debug, AST_FRAME_IAX, ast_inet_ntoa(), 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().

06223 {
06224    struct ast_iax2_full_hdr fh;
06225    fh.scallno = htons(src | IAX_FLAG_FULL);
06226    fh.dcallno = htons(dst);
06227    fh.ts = 0;
06228    fh.oseqno = 0;
06229    fh.iseqno = 0;
06230    fh.type = AST_FRAME_IAX;
06231    fh.csub = compress_subclass(IAX_COMMAND_INVAL);
06232    if (iaxdebug)
06233        iax_showframe(NULL, &fh, 0, sin, 0);
06234 #if 0
06235    if (option_debug)
06236 #endif   
06237       ast_debug(1, "Raw Hangup %s:%d, src=%d, dst=%d\n",
06238          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst);
06239    return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin));
06240 }

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

03217 {
03218    struct ast_variable *var = NULL;
03219    struct ast_variable *tmp;
03220    struct iax2_peer *peer=NULL;
03221    time_t regseconds = 0, nowtime;
03222    int dynamic=0;
03223 
03224    if (peername) {
03225       var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL);
03226       if (!var && sin)
03227          var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL);
03228    } else if (sin) {
03229       char porta[25];
03230       sprintf(porta, "%d", ntohs(sin->sin_port));
03231       var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
03232       if (var) {
03233          /* We'll need the peer name in order to build the structure! */
03234          for (tmp = var; tmp; tmp = tmp->next) {
03235             if (!strcasecmp(tmp->name, "name"))
03236                peername = tmp->value;
03237          }
03238       }
03239    }
03240    if (!var && peername) { /* Last ditch effort */
03241       var = ast_load_realtime("iaxpeers", "name", peername, NULL);
03242       /*!\note
03243        * If this one loaded something, then we need to ensure that the host
03244        * field matched.  The only reason why we can't have this as a criteria
03245        * is because we only have the IP address and the host field might be
03246        * set as a name (and the reverse PTR might not match).
03247        */
03248       if (var && sin) {
03249          for (tmp = var; tmp; tmp = tmp->next) {
03250             if (!strcasecmp(tmp->name, "host")) {
03251                struct ast_hostent ahp;
03252                struct hostent *hp;
03253                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
03254                   /* No match */
03255                   ast_variables_destroy(var);
03256                   var = NULL;
03257                }
03258                break;
03259             }
03260          }
03261       }
03262    }
03263    if (!var)
03264       return NULL;
03265 
03266    peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1);
03267    
03268    if (!peer) {
03269       ast_variables_destroy(var);
03270       return NULL;
03271    }
03272 
03273    for (tmp = var; tmp; tmp = tmp->next) {
03274       /* Make sure it's not a user only... */
03275       if (!strcasecmp(tmp->name, "type")) {
03276          if (strcasecmp(tmp->value, "friend") &&
03277              strcasecmp(tmp->value, "peer")) {
03278             /* Whoops, we weren't supposed to exist! */
03279             peer = peer_unref(peer);
03280             break;
03281          } 
03282       } else if (!strcasecmp(tmp->name, "regseconds")) {
03283          ast_get_time_t(tmp->value, &regseconds, 0, NULL);
03284       } else if (!strcasecmp(tmp->name, "ipaddr")) {
03285          inet_aton(tmp->value, &(peer->addr.sin_addr));
03286       } else if (!strcasecmp(tmp->name, "port")) {
03287          peer->addr.sin_port = htons(atoi(tmp->value));
03288       } else if (!strcasecmp(tmp->name, "host")) {
03289          if (!strcasecmp(tmp->value, "dynamic"))
03290             dynamic = 1;
03291       }
03292    }
03293 
03294    ast_variables_destroy(var);
03295 
03296    if (!peer)
03297       return NULL;
03298 
03299    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
03300       ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS);
03301       if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) {
03302          if (peer->expire > -1) {
03303             if (!ast_sched_del(sched, peer->expire)) {
03304                peer->expire = -1;
03305                peer_unref(peer);
03306             }
03307          }
03308          peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer));
03309          if (peer->expire == -1)
03310             peer_unref(peer);
03311       }
03312       ao2_link(peers, peer);
03313       if (ast_test_flag(peer, IAX_DYNAMIC))
03314          reg_source_db(peer);
03315    } else {
03316       ast_set_flag(peer, IAX_TEMPONLY);   
03317    }
03318 
03319    if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) {
03320       time(&nowtime);
03321       if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) {
03322          memset(&peer->addr, 0, sizeof(peer->addr));
03323          realtime_update_peer(peer->name, &peer->addr, 0);
03324          ast_debug(1, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n",
03325             peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
03326       }
03327       else {
03328          ast_debug(1, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n",
03329             peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
03330       }
03331    }
03332 
03333    return peer;
03334 }

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

Definition at line 3407 of file chan_iax2.c.

References ast_inet_ntoa(), and ast_update_realtime().

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

03408 {
03409    char port[10];
03410    char regseconds[20];
03411    
03412    snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime);
03413    snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
03414    ast_update_realtime("iaxpeers", "name", peername, 
03415       "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 
03416       "regseconds", regseconds, NULL);
03417 }

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

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

03337 {
03338    struct ast_variable *var;
03339    struct ast_variable *tmp;
03340    struct iax2_user *user=NULL;
03341 
03342    var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL);
03343    if (!var)
03344       var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL);
03345    if (!var && sin) {
03346       char porta[6];
03347       snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port));
03348       var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
03349       if (!var)
03350          var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL);
03351    }
03352    if (!var) { /* Last ditch effort */
03353       var = ast_load_realtime("iaxusers", "name", username, NULL);
03354       /*!\note
03355        * If this one loaded something, then we need to ensure that the host
03356        * field matched.  The only reason why we can't have this as a criteria
03357        * is because we only have the IP address and the host field might be
03358        * set as a name (and the reverse PTR might not match).
03359        */
03360       if (var) {
03361          for (tmp = var; tmp; tmp = tmp->next) {
03362             if (!strcasecmp(tmp->name, "host")) {
03363                struct ast_hostent ahp;
03364                struct hostent *hp;
03365                if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) {
03366                   /* No match */
03367                   ast_variables_destroy(var);
03368                   var = NULL;
03369                }
03370                break;
03371             }
03372          }
03373       }
03374    }
03375    if (!var)
03376       return NULL;
03377 
03378    tmp = var;
03379    while(tmp) {
03380       /* Make sure it's not a peer only... */
03381       if (!strcasecmp(tmp->name, "type")) {
03382          if (strcasecmp(tmp->value, "friend") &&
03383              strcasecmp(tmp->value, "user")) {
03384             return NULL;
03385          } 
03386       }
03387       tmp = tmp->next;
03388    }
03389 
03390    user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS));
03391 
03392    ast_variables_destroy(var);
03393 
03394    if (!user)
03395       return NULL;
03396 
03397    if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
03398       ast_set_flag(user, IAX_RTCACHEFRIENDS);
03399       ao2_link(users, user);
03400    } else {
03401       ast_set_flag(user, IAX_TEMPONLY);   
03402    }
03403 
03404    return user;
03405 }

static void reg_source_db ( struct iax2_peer p  )  [static]

Definition at line 7073 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_verb, iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), IAX_TEMPONLY, inet_aton(), iax2_peer::name, peer_ref(), peer_unref(), register_peer_exten(), and sched.

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

07074 {
07075    char data[80];
07076    struct in_addr in;
07077    char *c, *d;
07078    if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) {
07079       c = strchr(data, ':');
07080       if (c) {
07081          *c = '\0';
07082          c++;
07083          if (inet_aton(data, &in)) {
07084             d = strchr(c, ':');
07085             if (d) {
07086                *d = '\0';
07087                d++;
07088                ast_verb(3, "Seeding '%s' at %s:%d for %d\n", p->name,
07089                   ast_inet_ntoa(in), atoi(c), atoi(d));
07090                iax2_poke_peer(p, 0);
07091                p->expiry = atoi(d);
07092                memset(&p->addr, 0, sizeof(p->addr));
07093                p->addr.sin_family = AF_INET;
07094                p->addr.sin_addr = in;
07095                p->addr.sin_port = htons(atoi(c));
07096                if (p->expire > -1) {
07097                   if (!ast_sched_del(sched, p->expire)) {
07098                      p->expire = -1;
07099                      peer_unref(p);
07100                   }
07101                }
07102                ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
07103                p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
07104                if (p->expire == -1)
07105                   peer_unref(p);
07106                if (iax2_regfunk)
07107                   iax2_regfunk(p->name, 1);
07108                register_peer_exten(p, 1);
07109             }              
07110                
07111          }
07112       }
07113    }
07114 }

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

Definition at line 6994 of file chan_iax2.c.

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

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

06995 {
06996    char multi[256];
06997    char *stringp, *ext;
06998    if (!ast_strlen_zero(regcontext)) {
06999       ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi));
07000       stringp = multi;
07001       while((ext = strsep(&stringp, "&"))) {
07002          if (onoff) {
07003             if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL))
07004                ast_add_extension(regcontext, 1, ext, 1, NULL, NULL,
07005                        "Noop", ast_strdup(peer->name), ast_free_ptr, "IAX2");
07006          } else
07007             ast_context_remove_extension(regcontext, ext, 1, NULL);
07008       }
07009    }
07010 }

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

Verify inbound registration.

Definition at line 6391 of file chan_iax2.c.

References 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, ies, iax2_peer::inkeys, LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), iax2_peer::name, iax2_peer::secret, secret, and strsep().

Referenced by handle_request_register(), and socket_process().

06392 {
06393    char requeststr[256] = "";
06394    char peer[256] = "";
06395    char md5secret[256] = "";
06396    char rsasecret[256] = "";
06397    char secret[256] = "";
06398    struct iax2_peer *p = NULL;
06399    struct ast_key *key;
06400    char *keyn;
06401    int x;
06402    int expire = 0;
06403    int res = -1;
06404 
06405    ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
06406    /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
06407    if (ies->username)
06408       ast_copy_string(peer, ies->username, sizeof(peer));
06409    if (ies->password)
06410       ast_copy_string(secret, ies->password, sizeof(secret));
06411    if (ies->md5_result)
06412       ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret));
06413    if (ies->rsa_result)
06414       ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret));
06415    if (ies->refresh)
06416       expire = ies->refresh;
06417 
06418    if (ast_strlen_zero(peer)) {
06419       ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr));
06420       return -1;
06421    }
06422 
06423    /* SLD: first call to lookup peer during registration */
06424    ast_mutex_unlock(&iaxsl[callno]);
06425    p = find_peer(peer, 1);
06426    ast_mutex_lock(&iaxsl[callno]);
06427    if (!p || !iaxs[callno]) {
06428       if (iaxs[callno]) {
06429          int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT));
06430          /* Anything, as long as it's non-blank */
06431          ast_string_field_set(iaxs[callno], secret, "badsecret");
06432          /* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless
06433           * 1. A challenge already exists indicating a AUTHREQ was already sent out.
06434           * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it.
06435           * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened
06436           *    to be plaintext, indicating it is an authmethod used by other peers on the system. 
06437           *
06438           * If none of these cases exist, res will be returned as 0 without authentication indicating
06439           * an AUTHREQ needs to be sent out. */
06440 
06441          if (ast_strlen_zero(iaxs[callno]->challenge) &&
06442             !(!ast_strlen_zero(secret) && plaintext)) {
06443             /* by setting res to 0, an REGAUTH will be sent */
06444             res = 0;
06445          }
06446       }
06447       if (authdebug && !p)
06448          ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
06449       goto return_unref;
06450    }
06451 
06452    if (!ast_test_flag(p, IAX_DYNAMIC)) {
06453       if (authdebug)
06454          ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
06455       goto return_unref;
06456    }
06457 
06458    if (!ast_apply_ha(p->ha, sin)) {
06459       if (authdebug)
06460          ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
06461       goto return_unref;
06462    }
06463    ast_string_field_set(iaxs[callno], secret, p->secret);
06464    ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
06465    /* Check secret against what we have on file */
06466    if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) {
06467       if (!ast_strlen_zero(p->inkeys)) {
06468          char tmpkeys[256];
06469          char *stringp=NULL;
06470          ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys));
06471          stringp=tmpkeys;
06472          keyn = strsep(&stringp, ":");
06473          while(keyn) {
06474             key = ast_key_get(keyn, AST_KEY_PUBLIC);
06475             if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
06476                ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
06477                break;
06478             } else if (!key)
06479                ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
06480             keyn = strsep(&stringp, ":");
06481          }
06482          if (!keyn) {
06483             if (authdebug)
06484                ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
06485             goto return_unref;
06486          }
06487       } else {
06488          if (authdebug)
06489             ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
06490          goto return_unref;
06491       }
06492    } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) {
06493       struct MD5Context md5;
06494       unsigned char digest[16];
06495       char *tmppw, *stringp;
06496 
06497       tmppw = ast_strdupa(p->secret);
06498       stringp = tmppw;
06499       while((tmppw = strsep(&stringp, ";"))) {
06500          MD5Init(&md5);
06501          MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
06502          MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw));
06503          MD5Final(digest, &md5);
06504          for (x=0;x<16;x++)
06505             sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
06506          if (!strcasecmp(requeststr, md5secret))
06507             break;
06508       }
06509       if (tmppw) {
06510          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
06511       } else {
06512          if (authdebug)
06513             ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret);
06514          goto return_unref;
06515       }
06516    } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
06517       /* They've provided a plain text password and we support that */
06518       if (strcmp(secret, p->secret)) {
06519          if (authdebug)
06520             ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
06521          goto return_unref;
06522       } else
06523          ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
06524    } else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) {
06525       /* if challenge has been sent, but no challenge response if given, reject. */
06526       goto return_unref;
06527    }
06528    ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */
06529 
06530    /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */
06531    res = 0;
06532 
06533 return_unref:
06534    if (iaxs[callno]) {
06535       ast_string_field_set(iaxs[callno], peer, peer);
06536 
06537       /* Choose lowest expiry number */
06538       if (expire && (expire < iaxs[callno]->expiry)) {
06539          iaxs[callno]->expiry = expire;
06540       }
06541    }
06542 
06543    if (p) {
06544       peer_unref(p);
06545    }
06546    return res;
06547 }

static int registry_authrequest ( int  callno  )  [static]

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

Referenced by socket_process().

07271 {
07272    struct iax_ie_data ied;
07273    struct iax2_peer *p;
07274    char challenge[10];
07275    const char *peer_name;
07276    int sentauthmethod;
07277 
07278    peer_name = ast_strdupa(iaxs[callno]->peer);
07279 
07280    /* SLD: third call to find_peer in registration */
07281    ast_mutex_unlock(&iaxsl[callno]);
07282    if ((p = find_peer(peer_name, 1))) {
07283       last_authmethod = p->authmethods;
07284    }
07285 
07286    ast_mutex_lock(&iaxsl[callno]);
07287    if (!iaxs[callno])
07288       goto return_unref;
07289 
07290    memset(&ied, 0, sizeof(ied));
07291    /* The selection of which delayed reject is sent may leak information,
07292     * if it sets a static response.  For example, if a host is known to only
07293     * use MD5 authentication, then an RSA response would indicate that the
07294     * peer does not exist, and vice-versa.
07295     * Therefore, we use whatever the last peer used (which may vary over the
07296     * course of a server, which should leak minimal information). */
07297    sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
07298    if (!p) {
07299       iaxs[callno]->authmethods = sentauthmethod;
07300    }
07301    iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
07302    if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
07303       /* Build the challenge */
07304       snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
07305       ast_string_field_set(iaxs[callno], challenge, challenge);
07306       iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
07307    }
07308    iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
07309 
07310 return_unref:
07311    if (p) {
07312       peer_unref(p);
07313    }
07314 
07315    return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1;
07316 }

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

Definition at line 7318 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, ies, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax2_registry::refresh, REG_STATE_AUTHSENT, iax2_registry::regstate, iax2_registry::secret, send_command(), and iax2_registry::username.

Referenced by socket_process().

07319 {
07320    struct iax2_registry *reg;
07321    /* Start pessimistic */
07322    struct iax_ie_data ied;
07323    char peer[256] = "";
07324    char challenge[256] = "";
07325    int res;
07326    int authmethods = 0;
07327    if (ies->authmethods)
07328       authmethods = ies->authmethods;
07329    if (ies->username)
07330       ast_copy_string(peer, ies->username, sizeof(peer));
07331    if (ies->challenge)
07332       ast_copy_string(challenge, ies->challenge, sizeof(challenge));
07333    memset(&ied, 0, sizeof(ied));
07334    reg = iaxs[callno]->reg;
07335    if (reg) {
07336          if (inaddrcmp(&reg->addr, sin)) {
07337             ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr));
07338             return -1;
07339          }
07340          if (ast_strlen_zero(reg->secret)) {
07341             ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username);
07342             reg->regstate = REG_STATE_NOAUTH;
07343             return -1;
07344          }
07345          iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username);
07346          iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh);
07347          if (reg->secret[0] == '[') {
07348             char tmpkey[256];
07349             ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey));
07350             tmpkey[strlen(tmpkey) - 1] = '\0';
07351             res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL);
07352          } else
07353             res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL);
07354          if (!res) {
07355             reg->regstate = REG_STATE_AUTHSENT;
07356             return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1);
07357          } else
07358             return -1;
07359          ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer);
07360    } else   
07361       ast_log(LOG_NOTICE, "Can't reregister without a reg\n");
07362    return -1;
07363 }

static char* regstate2str ( int  regstate  )  [static]

Definition at line 5516 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_cli_iax2_show_registry(), handle_response_register(), manager_show_registry(), sip_reg_timeout(), and sip_show_registry().

05517 {
05518    switch(regstate) {
05519    case REG_STATE_UNREGISTERED:
05520       return "Unregistered";
05521    case REG_STATE_REGSENT:
05522       return "Request Sent";
05523    case REG_STATE_AUTHSENT:
05524       return "Auth. Sent";
05525    case REG_STATE_REGISTERED:
05526       return "Registered";
05527    case REG_STATE_REJECTED:
05528       return "Rejected";
05529    case REG_STATE_TIMEOUT:
05530       return "Timeout";
05531    case REG_STATE_NOAUTH:
05532       return "No Authentication";
05533    default:
05534       return "Unknown";
05535    }
05536 }

static int reload ( void   )  [static]

Definition at line 11611 of file chan_iax2.c.

References reload_config().

11612 {
11613    return reload_config();
11614 }

static int reload_config ( void   )  [static]

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

11568 {
11569    char *config = "iax.conf";
11570    struct iax2_registry *reg;
11571 
11572    if (set_config(config, 1) > 0) {
11573       prune_peers();
11574       prune_users();
11575       trunk_timed = trunk_untimed = 0; 
11576       trunk_nmaxmtu = trunk_maxmtu = 0; 
11577 
11578       AST_LIST_LOCK(&registrations);
11579       AST_LIST_TRAVERSE(&registrations, reg, entry)
11580          iax2_do_register(reg);
11581       AST_LIST_UNLOCK(&registrations);
11582 
11583       /* Qualify hosts, too */
11584       poke_all_peers();
11585    }
11586    
11587    reload_firmware(0);
11588    iax_provision_reload(1);
11589 
11590    return 0;
11591 }

static void reload_firmware ( int  unload  )  [static]

Definition at line 2162 of file chan_iax2.c.

References ast_config_AST_DATA_DIR, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verb, iax_firmware::dead, destroy_firmware(), dir, errno, iax2_trunk_peer::list, LOG_WARNING, and try_firmware().

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

02163 {
02164    struct iax_firmware *cur = NULL;
02165    DIR *fwd;
02166    struct dirent *de;
02167    char dir[256], fn[256];
02168 
02169    AST_LIST_LOCK(&firmwares);
02170 
02171    /* Mark all as dead */
02172    AST_LIST_TRAVERSE(&firmwares, cur, list)
02173       cur->dead = 1;
02174 
02175    /* Now that we have marked them dead... load new ones */
02176    if (!unload) {
02177       snprintf(dir, sizeof(dir), "%s/firmware/iax", ast_config_AST_DATA_DIR);
02178       fwd = opendir(dir);
02179       if (fwd) {
02180          while((de = readdir(fwd))) {
02181             if (de->d_name[0] != '.') {
02182                snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name);
02183                if (!try_firmware(fn)) {
02184                   ast_verb(2, "Loaded firmware '%s'\n", de->d_name);
02185                }
02186             }
02187          }
02188          closedir(fwd);
02189       } else 
02190          ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
02191    }
02192 
02193    /* Clean up leftovers */
02194    AST_LIST_TRAVERSE_SAFE_BEGIN(&firmwares, cur, list) {
02195       if (!cur->dead)
02196          continue;
02197       AST_LIST_REMOVE_CURRENT(list);
02198       destroy_firmware(cur);
02199    }
02200    AST_LIST_TRAVERSE_SAFE_END;
02201 
02202    AST_LIST_UNLOCK(&firmwares);
02203 }

static void remove_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

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

01673 {
01674    if (!pvt->peercallno) {
01675       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01676       return;
01677    }
01678 
01679    ao2_unlink(iax_peercallno_pvts, pvt);
01680 }

static void remove_by_transfercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1653 of file chan_iax2.c.

References ao2_unlink(), ast_log(), iax_transfercallno_pvts, LOG_ERROR, and chan_iax2_pvt::transfercallno.

Referenced by complete_transfer(), and iax2_destroy().

01654 {
01655    if (!pvt->transfercallno) {
01656       ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n");
01657       return;
01658    }
01659 
01660    ao2_unlink(iax_transfercallno_pvts, pvt);
01661 }

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

Definition at line 7813 of file chan_iax2.c.

References ast_string_field_set, iax_frame::callno, IAX_MAX_OSPBLOCK_NUM, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPBUFF_SIZE, and ies.

Referenced by socket_process().

07814 {
07815    int i;
07816    unsigned int length, offset = 0;
07817    char full_osptoken[IAX_MAX_OSPBUFF_SIZE];
07818 
07819    for (i = 0; i < IAX_MAX_OSPBLOCK_NUM; i++) {
07820       length = ies->ospblocklength[i];
07821       if (length != 0) {
07822          if (length > IAX_MAX_OSPBLOCK_SIZE) {
07823             /* OSP token block length wrong, clear buffer */
07824             offset = 0;
07825             break;
07826          } else {
07827             memcpy(full_osptoken + offset, ies->osptokenblock[i], length);
07828             offset += length;
07829          }
07830       } else {
07831          break;
07832       }
07833    }
07834    *(full_osptoken + offset) = '\0';
07835    if (strlen(full_osptoken) != offset) {
07836       /* OSP token length wrong, clear buffer */
07837       *full_osptoken = '\0';
07838    }
07839 
07840    ast_string_field_set(iaxs[fr->callno], osptoken, full_osptoken);
07841 }

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

Definition at line 7802 of file chan_iax2.c.

References iax_frame::callno, and ies.

Referenced by socket_process().

07803 {
07804    iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter;
07805    iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24;
07806    iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff;
07807    iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts;
07808    iaxs[fr->callno]->remote_rr.delay = ies->rr_delay;
07809    iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped;
07810    iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo;
07811 }

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

Definition at line 10333 of file chan_iax2.c.

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

10334 {
10335    int count;
10336    int res;
10337    struct timeval tv;
10338    struct timespec ts;
10339 
10340    for (;;) {
10341       res = ast_sched_wait(sched);
10342       if ((res > 1000) || (res < 0))
10343          res = 1000;
10344       tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000));
10345       ts.tv_sec = tv.tv_sec;
10346       ts.tv_nsec = tv.tv_usec * 1000;
10347 
10348       pthread_testcancel();
10349       ast_mutex_lock(&sched_lock);
10350       ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
10351       ast_mutex_unlock(&sched_lock);
10352       pthread_testcancel();
10353 
10354       count = ast_sched_runq(sched);
10355       if (count >= 20)
10356          ast_debug(1, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
10357    }
10358 
10359    return NULL;
10360 }

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

References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), ast_debug, AST_FRAME_CNG, AST_FRAME_VOICE, 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, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, ast_channel_tech::properties, sched, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().

Referenced by socket_process(), and socket_process_meta().

03072 {
03073    int type, len;
03074    int ret;
03075    int needfree = 0;
03076    struct ast_channel *owner = NULL;
03077    struct ast_channel *bridge = NULL;
03078    
03079    /* Attempt to recover wrapped timestamps */
03080    unwrap_timestamp(fr);
03081 
03082    /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
03083    if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
03084       fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
03085    else {
03086 #if 0
03087       ast_debug(1, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
03088 #endif
03089       fr->af.delivery = ast_tv(0,0);
03090    }
03091 
03092    type = JB_TYPE_CONTROL;
03093    len = 0;
03094 
03095    if(fr->af.frametype == AST_FRAME_VOICE) {
03096       type = JB_TYPE_VOICE;
03097       len = ast_codec_get_samples(&fr->af) / 8;
03098    } else if(fr->af.frametype == AST_FRAME_CNG) {
03099       type = JB_TYPE_SILENCE;
03100    }
03101 
03102    if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
03103       if (tsout)
03104          *tsout = fr->ts;
03105       __do_deliver(fr);
03106       return -1;
03107    }
03108 
03109    if ((owner = iaxs[fr->callno]->owner))
03110       bridge = ast_bridged_channel(owner);
03111 
03112    /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
03113     * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
03114    if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) {
03115       jb_frame frame;
03116 
03117       /* deliver any frames in the jb */
03118       while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
03119          __do_deliver(frame.data);
03120          /* __do_deliver() can make the call disappear */
03121          if (!iaxs[fr->callno])
03122             return -1;
03123       }
03124 
03125       jb_reset(iaxs[fr->callno]->jb);
03126 
03127       AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
03128 
03129       /* deliver this frame now */
03130       if (tsout)
03131          *tsout = fr->ts;
03132       __do_deliver(fr);
03133       return -1;
03134    }
03135 
03136    /* insert into jitterbuffer */
03137    /* TODO: Perhaps we could act immediately if it's not droppable and late */
03138    ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
03139          calc_rxstamp(iaxs[fr->callno],fr->ts));
03140    if (ret == JB_DROP) {
03141       needfree++;
03142    } else if (ret == JB_SCHED) {
03143       update_jbsched(iaxs[fr->callno]);
03144    }
03145    if (tsout)
03146       *tsout = fr->ts;
03147    if (needfree) {
03148       /* Free our iax frame */
03149       iax2_frame_free(fr);
03150       return -1;
03151    }
03152    return 0;
03153 }

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

Definition at line 1431 of file chan_iax2.c.

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

Referenced by iax2_hangup().

01432 {
01433    short callno = PTR_TO_CALLNO(vid);
01434    ast_mutex_lock(&iaxsl[callno]);
01435    if (iaxs[callno]) {
01436       if (option_debug) {
01437          ast_log(LOG_DEBUG, "Really destroying %d now...\n", callno);
01438       }
01439       iax2_destroy(callno);
01440    }
01441    ast_mutex_unlock(&iaxsl[callno]);
01442    return 0;
01443 }

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

References AST_FRAME_IAX, compress_subclass(), and f.

Referenced by socket_process().

03576 {
03577    struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno),
03578       .ts = htonl(ts), .iseqno = seqno, .oseqno = 0, .type = AST_FRAME_IAX,
03579       .csub = compress_subclass(command) };
03580 
03581    return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin));
03582 }

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

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

05951 {
05952    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
05953 }

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

References __send_command(), chan_iax2_pvt::callno, and iax2_predestroy().

Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_hangup(), socket_process(), and update_registry().

05970 {
05971    int call_num = i->callno;
05972    /* It is assumed that the callno has already been locked */
05973    iax2_predestroy(i->callno);
05974    if (!iaxs[call_num])
05975       return -1;
05976    return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1);
05977 }

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

Definition at line 5979 of file chan_iax2.c.

References __send_command().

Referenced by iax2_vnak(), and socket_process().

05980 {
05981    return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0);
05982 }

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

Definition at line 5955 of file chan_iax2.c.

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

Referenced by iax2_answer(), iax2_digit_begin(), iax2_digit_end(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), and iax2_transfer().

05956 {
05957    int res;
05958    ast_mutex_lock(&iaxsl[callno]);
05959    res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
05960    ast_mutex_unlock(&iaxsl[callno]);
05961    return res;
05962 }

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

Definition at line 5984 of file chan_iax2.c.

References __send_command().

Referenced by socket_process(), and try_transfer().

05985 {
05986    return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0);
05987 }

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

Definition at line 1233 of file chan_iax2.c.

References __send_lagrq(), and schedule_action.

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

01234 {
01235 #ifdef SCHED_MULTITHREADED
01236    if (schedule_action(__send_lagrq, data))
01237 #endif      
01238       __send_lagrq(data);
01239    
01240    return 0;
01241 }

static int send_packet ( struct iax_frame f  )  [static]

Definition at line 2275 of file chan_iax2.c.

References ast_debug, ast_inet_ntoa(), errno, f, handle_error(), iax_showframe(), and iax2_trunk_peer::sockfd.

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

02276 {
02277    int res;
02278    int callno = f->callno;
02279 
02280    /* Don't send if there was an error, but return error instead */
02281    if (!callno || !iaxs[callno] || iaxs[callno]->error)
02282        return -1;
02283    
02284    /* Called with iaxsl held */
02285    if (iaxdebug)
02286       ast_debug(3, "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));
02287    if (f->transfer) {
02288       if (iaxdebug)
02289          iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr));
02290       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer,
02291                sizeof(iaxs[callno]->transfer));
02292    } else {
02293       if (iaxdebug)
02294          iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr));
02295       res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr,
02296                sizeof(iaxs[callno]->addr));
02297    }
02298    if (res < 0) {
02299       if (iaxdebug)
02300          ast_debug(1, "Received error: %s\n", strerror(errno));
02301       handle_error();
02302    } else
02303       res = 0;
02304    return res;
02305 }

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

Definition at line 1188 of file chan_iax2.c.

References __send_ping(), and schedule_action.

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

01189 {
01190 #ifdef SCHED_MULTITHREADED
01191    if (schedule_action(__send_ping, data))
01192 #endif      
01193       __send_ping(data);
01194 
01195    return 0;
01196 }

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

Definition at line 7500 of file chan_iax2.c.

References iax2_trunk_peer::addr, iax_frame::afdata, ast_debug, ast_inet_ntoa(), 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, 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 iax2_trunk_queue(), and timing_read().

07501 {
07502    int res = 0;
07503    struct iax_frame *fr;
07504    struct ast_iax2_meta_hdr *meta;
07505    struct ast_iax2_meta_trunk_hdr *mth;
07506    int calls = 0;
07507    
07508    /* Point to frame */
07509    fr = (struct iax_frame *)tpeer->trunkdata;
07510    /* Point to meta data */
07511    meta = (struct ast_iax2_meta_hdr *)fr->afdata;
07512    mth = (struct ast_iax2_meta_trunk_hdr *)meta->data;
07513    if (tpeer->trunkdatalen) {
07514       /* We're actually sending a frame, so fill the meta trunk header and meta header */
07515       meta->zeros = 0;
07516       meta->metacmd = IAX_META_TRUNK;
07517       if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS))
07518          meta->cmddata = IAX_META_TRUNK_MINI;
07519       else
07520          meta->cmddata = IAX_META_TRUNK_SUPERMINI;
07521       mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now));
07522       /* And the rest of the ast_iax2 header */
07523       fr->direction = DIRECTION_OUTGRESS;
07524       fr->retrans = -1;
07525       fr->transfer = 0;
07526       /* Any appropriate call will do */
07527       fr->data = fr->afdata;
07528       fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr);
07529       res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd);
07530       calls = tpeer->calls;
07531 #if 0
07532       ast_debug(1, "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));
07533 #endif      
07534       /* Reset transmit trunk side data */
07535       tpeer->trunkdatalen = 0;
07536       tpeer->calls = 0;
07537    }
07538    if (res < 0)
07539       return res;
07540    return calls;
07541 }

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

Load configuration.

Definition at line 11165 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_find_or_create(), 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_str2cos(), ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, build_peer(), build_user(), capability, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, 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_TRUNK_MTU, MAX_TRUNKDATA, ast_variable::name, netsock, ast_variable::next, outsock, peer_unref(), prefs, reg_source_db(), secret, set_config_destroy(), set_timing(), socket_read(), user, user_unref(), and ast_variable::value.

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

11166 {
11167    struct ast_config *cfg, *ucfg;
11168    int capability=iax2_capability;
11169    struct ast_variable *v;
11170    char *cat;
11171    const char *utype;
11172    const char *tosval;
11173    int format;
11174    int portno = IAX_DEFAULT_PORTNO;
11175    int  x;
11176    int mtuv; 
11177    struct iax2_user *user;
11178    struct iax2_peer *peer;
11179    struct ast_netsock *ns;
11180    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
11181 #if 0
11182    static unsigned short int last_port=0;
11183 #endif
11184 
11185    cfg = ast_config_load(config_file, config_flags);
11186 
11187    if (!cfg) {
11188       ast_log(LOG_ERROR, "Unable to load config %s\n", config_file);
11189       return -1;
11190    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
11191       ucfg = ast_config_load("users.conf", config_flags);
11192       if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
11193          return 0;
11194       /* Otherwise we need to reread both files */
11195       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11196       cfg = ast_config_load(config_file, config_flags);
11197    } else { /* iax.conf changed, gotta reread users.conf, too */
11198       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
11199       ucfg = ast_config_load("users.conf", config_flags);
11200    }
11201 
11202    if (reload) {
11203       set_config_destroy();
11204    }
11205 
11206    /* Reset global codec prefs */   
11207    memset(&prefs, 0 , sizeof(struct ast_codec_pref));
11208    
11209    /* Reset Global Flags */
11210    memset(&globalflags, 0, sizeof(globalflags));
11211    ast_set_flag(&globalflags, IAX_RTUPDATE);
11212 
11213 #ifdef SO_NO_CHECK
11214    nochecksums = 0;
11215 #endif
11216 
11217    min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
11218    max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
11219    global_max_trunk_mtu = MAX_TRUNK_MTU;
11220 
11221    maxauthreq = 3;
11222 
11223    srvlookup = 0;
11224 
11225    v = ast_variable_browse(cfg, "general");
11226 
11227    /* Seed initial tos value */
11228    tosval = ast_variable_retrieve(cfg, "general", "tos");
11229    if (tosval) {
11230       if (ast_str2tos(tosval, &tos))
11231          ast_log(LOG_WARNING, "Invalid tos value, refer to QoS documentation\n");
11232    }
11233    /* Seed initial cos value */
11234    tosval = ast_variable_retrieve(cfg, "general", "cos");
11235    if (tosval) {
11236       if (ast_str2cos(tosval, &cos))
11237          ast_log(LOG_WARNING, "Invalid cos value, refer to QoS documentation\n");
11238    }
11239    while(v) {
11240       if (!strcasecmp(v->name, "bindport")){ 
11241          if (reload)
11242             ast_log(LOG_NOTICE, "Ignoring bindport on reload\n");
11243          else
11244             portno = atoi(v->value);
11245       } else if (!strcasecmp(v->name, "pingtime")) 
11246          ping_time = atoi(v->value);
11247       else if (!strcasecmp(v->name, "iaxthreadcount")) {
11248          if (reload) {
11249             if (atoi(v->value) != iaxthreadcount)
11250                ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n");
11251          } else {
11252             iaxthreadcount = atoi(v->value);
11253             if (iaxthreadcount < 1) {
11254                ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n");
11255                iaxthreadcount = 1;
11256             } else if (iaxthreadcount > 256) {
11257                ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n");
11258                iaxthreadcount = 256;
11259             }
11260          }
11261       } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) {
11262          if (reload) {
11263             AST_LIST_LOCK(&dynamic_list);
11264             iaxmaxthreadcount = atoi(v->value);
11265             AST_LIST_UNLOCK(&dynamic_list);
11266          } else {
11267             iaxmaxthreadcount = atoi(v->value);
11268             if (iaxmaxthreadcount < 0) {
11269                ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n");
11270                iaxmaxthreadcount = 0;
11271             } else if (iaxmaxthreadcount > 256) {
11272                ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n");
11273                iaxmaxthreadcount = 256;
11274             }
11275          }
11276       } else if (!strcasecmp(v->name, "nochecksums")) {
11277 #ifdef SO_NO_CHECK
11278          if (ast_true(v->value))
11279             nochecksums = 1;
11280          else
11281             nochecksums = 0;
11282 #else
11283          if (ast_true(v->value))
11284             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
11285 #endif
11286       }
11287       else if (!strcasecmp(v->name, "maxjitterbuffer")) 
11288          maxjitterbuffer = atoi(v->value);
11289       else if (!strcasecmp(v->name, "resyncthreshold")) 
11290          resyncthreshold = atoi(v->value);
11291       else if (!strcasecmp(v->name, "maxjitterinterps")) 
11292          maxjitterinterps = atoi(v->value);
11293       else if (!strcasecmp(v->name, "jittertargetextra"))
11294          jittertargetextra = atoi(v->value);
11295       else if (!strcasecmp(v->name, "lagrqtime")) 
11296          lagrq_time = atoi(v->value);
11297       else if (!strcasecmp(v->name, "maxregexpire")) 
11298          max_reg_expire = atoi(v->value);
11299       else if (!strcasecmp(v->name, "minregexpire")) 
11300          min_reg_expire = atoi(v->value);
11301       else if (!strcasecmp(v->name, "bindaddr")) {
11302          if (reload) {
11303             ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n");
11304          } else {
11305             if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, cos, socket_read, NULL))) {
11306                ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno);
11307             } else {
11308                   if (strchr(v->value, ':'))
11309                   ast_verb(2, "Binding IAX2 to '%s'\n", v->value);
11310                   else
11311                   ast_verb(2, "Binding IAX2 to '%s:%d'\n", v->value, portno);
11312                if (defaultsockfd < 0) 
11313                   defaultsockfd = ast_netsock_sockfd(ns);
11314                ast_netsock_unref(ns);
11315             }
11316          }
11317       } else if (!strcasecmp(v->name, "authdebug"))
11318          authdebug = ast_true(v->value);
11319       else if (!strcasecmp(v->name, "encryption"))
11320          iax2_encryption = get_encrypt_methods(v->value);
11321       else if (!strcasecmp(v->name, "transfer")) {
11322          if (!strcasecmp(v->value, "mediaonly")) {
11323             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 
11324          } else if (ast_true(v->value)) {
11325             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0);
11326          } else 
11327             ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
11328       } else if (!strcasecmp(v->name, "codecpriority")) {
11329          if(!strcasecmp(v->value, "caller"))
11330             ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST);
11331          else if(!strcasecmp(v->value, "disabled"))
11332             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
11333          else if(!strcasecmp(v->value, "reqonly")) {
11334             ast_set_flag((&globalflags), IAX_CODEC_NOCAP);
11335             ast_set_flag((&globalflags), IAX_CODEC_NOPREFS);
11336          }
11337       } else if (!strcasecmp(v->name, "jitterbuffer"))
11338          ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 
11339       else if (!strcasecmp(v->name, "forcejitterbuffer"))
11340          ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);  
11341       else if (!strcasecmp(v->name, "delayreject"))
11342          delayreject = ast_true(v->value);
11343       else if (!strcasecmp(v->name, "allowfwdownload"))
11344          ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD);
11345       else if (!strcasecmp(v->name, "rtcachefriends"))
11346          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS);  
11347       else if (!strcasecmp(v->name, "rtignoreregexpire"))
11348          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE);  
11349       else if (!strcasecmp(v->name, "rtupdate"))
11350          ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE);
11351       else if (!strcasecmp(v->name, "trunktimestamps"))
11352          ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS);
11353       else if (!strcasecmp(v->name, "rtautoclear")) {
11354          int i = atoi(v->value);
11355          if(i > 0)
11356             global_rtautoclear = i;
11357          else
11358             i = 0;
11359          ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR);   
11360       } else if (!strcasecmp(v->name, "trunkfreq")) {
11361          trunkfreq = atoi(v->value);
11362          if (trunkfreq < 10)
11363             trunkfreq = 10;
11364       } else if (!strcasecmp(v->name, "trunkmtu")) {
11365          mtuv = atoi(v->value);
11366          if (mtuv  == 0 )  
11367             global_max_trunk_mtu = 0; 
11368          else if (mtuv >= 172 && mtuv < 4000) 
11369             global_max_trunk_mtu = mtuv; 
11370          else 
11371             ast_log(LOG_NOTICE, "trunkmtu value out of bounds (%d) at line %d\n",
11372                mtuv, v->lineno);
11373       } else if (!strcasecmp(v->name, "trunkmaxsize")) {
11374          trunkmaxsize = atoi(v->value);
11375          if (trunkmaxsize == 0)
11376             trunkmaxsize = MAX_TRUNKDATA;
11377       } else if (!strcasecmp(v->name, "autokill")) {
11378          if (sscanf(v->value, "%d", &x) == 1) {
11379             if (x >= 0)
11380                autokill = x;
11381             else
11382                ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno);
11383          } else if (ast_true(v->value)) {
11384             autokill = DEFAULT_MAXMS;
11385          } else {
11386             autokill = 0;
11387          }
11388       } else if (!strcasecmp(v->name, "bandwidth")) {
11389          if (!strcasecmp(v->value, "low")) {
11390             capability = IAX_CAPABILITY_LOWBANDWIDTH;
11391          } else if (!strcasecmp(v->value, "medium")) {
11392             capability = IAX_CAPABILITY_MEDBANDWIDTH;
11393          } else if (!strcasecmp(v->value, "high")) {
11394             capability = IAX_CAPABILITY_FULLBANDWIDTH;
11395          } else
11396             ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n");
11397       } else if (!strcasecmp(v->name, "allow")) {
11398          ast_parse_allow_disallow(&prefs, &capability, v->value, 1);
11399       } else if (!strcasecmp(v->name, "disallow")) {
11400          ast_parse_allow_disallow(&prefs, &capability, v->value, 0);
11401       } else if (!strcasecmp(v->name, "register")) {
11402          iax2_register(v->value, v->lineno);
11403       } else if (!strcasecmp(v->name, "iaxcompat")) {
11404          iaxcompat = ast_true(v->value);
11405       } else if (!strcasecmp(v->name, "regcontext")) {
11406          ast_copy_string(regcontext, v->value, sizeof(regcontext));
11407          /* Create context if it doesn't exist already */
11408          ast_context_find_or_create(NULL, NULL, regcontext, "IAX2");
11409       } else if (!strcasecmp(v->name, "tos")) {
11410          if (ast_str2tos(v->value, &tos))
11411             ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
11412       } else if (!strcasecmp(v->name, "cos")) {
11413          if (ast_str2cos(v->value, &cos))
11414             ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
11415       } else if (!strcasecmp(v->name, "accountcode")) {
11416          ast_copy_string(accountcode, v->value, sizeof(accountcode));
11417       } else if (!strcasecmp(v->name, "mohinterpret")) {
11418          ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
11419       } else if (!strcasecmp(v->name, "mohsuggest")) {
11420          ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest));
11421       } else if (!strcasecmp(v->name, "amaflags")) {
11422          format = ast_cdr_amaflags2int(v->value);
11423          if (format < 0) {
11424             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
11425          } else {
11426             amaflags = format;
11427          }
11428       } else if (!strcasecmp(v->name, "language")) {
11429          ast_copy_string(language, v->value, sizeof(language));
11430       } else if (!strcasecmp(v->name, "maxauthreq")) {
11431          maxauthreq = atoi(v->value);
11432          if (maxauthreq < 0)
11433             maxauthreq = 0;
11434       } else if (!strcasecmp(v->name, "adsi")) {
11435          adsi = ast_true(v->value);
11436       } else if (!strcasecmp(v->name, "srvlookup")) {
11437          srvlookup = ast_true(v->value);
11438       } /*else if (strcasecmp(v->name,"type")) */
11439       /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
11440       v = v->next;
11441    }
11442    
11443    if (defaultsockfd < 0) {
11444       if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, cos, socket_read, NULL))) {
11445          ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
11446       } else {
11447          ast_verb(2, "Binding IAX2 to default address 0.0.0.0:%d\n", portno);
11448          defaultsockfd = ast_netsock_sockfd(ns);
11449          ast_netsock_unref(ns);
11450       }
11451    }
11452    if (reload) {
11453       ast_netsock_release(outsock);
11454       outsock = ast_netsock_list_alloc();
11455       if (!outsock) {
11456          ast_log(LOG_ERROR, "Could not allocate outsock list.\n");
11457          return -1;
11458       }
11459       ast_netsock_init(outsock);
11460    }
11461 
11462    if (min_reg_expire > max_reg_expire) {
11463       ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n",
11464          min_reg_expire, max_reg_expire, max_reg_expire);
11465       min_reg_expire = max_reg_expire;
11466    }
11467    iax2_capability = capability;
11468    
11469    if (ucfg) {
11470       struct ast_variable *gen;
11471       int genhasiax;
11472       int genregisteriax;
11473       const char *hasiax, *registeriax;
11474       
11475       genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax"));
11476       genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax"));
11477       gen = ast_variable_browse(ucfg, "general");
11478       cat = ast_category_browse(ucfg, NULL);
11479       while (cat) {
11480          if (strcasecmp(cat, "general")) {
11481             hasiax = ast_variable_retrieve(ucfg, cat, "hasiax");
11482             registeriax = ast_variable_retrieve(ucfg, cat, "registeriax");
11483             if (ast_true(hasiax) || (!hasiax && genhasiax)) {
11484                /* Start with general parameters, then specific parameters, user and peer */
11485                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
11486                if (user) {
11487                   ao2_link(users, user);
11488                   user = user_unref(user);
11489                }
11490                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
11491                if (peer) {
11492                   if (ast_test_flag(peer, IAX_DYNAMIC))
11493                      reg_source_db(peer);
11494                   ao2_link(peers, peer);
11495                   peer = peer_unref(peer);
11496                }
11497             }
11498             if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
11499                char tmp[256];
11500                const char *host = ast_variable_retrieve(ucfg, cat, "host");
11501                const char *username = ast_variable_retrieve(ucfg, cat, "username");
11502                const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
11503                if (!host)
11504                   host = ast_variable_retrieve(ucfg, "general", "host");
11505                if (!username)
11506                   username = ast_variable_retrieve(ucfg, "general", "username");
11507                if (!secret)
11508                   secret = ast_variable_retrieve(ucfg, "general", "secret");
11509                if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
11510                   if (!ast_strlen_zero(secret))
11511                      snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host);
11512                   else
11513                      snprintf(tmp, sizeof(tmp), "%s@%s", username, host);
11514                   iax2_register(tmp, 0);
11515                }
11516             }
11517          }
11518          cat = ast_category_browse(ucfg, cat);
11519       }
11520       ast_config_destroy(ucfg);
11521    }
11522    
11523    cat = ast_category_browse(cfg, NULL);
11524    while(cat) {
11525       if (strcasecmp(cat, "general")) {
11526          utype = ast_variable_retrieve(cfg, cat, "type");
11527          if (utype) {
11528             if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
11529                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
11530                if (user) {
11531                   ao2_link(users, user);
11532                   user = user_unref(user);
11533                }
11534             }
11535             if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
11536                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
11537                if (peer) {
11538                   if (ast_test_flag(peer, IAX_DYNAMIC))
11539                      reg_source_db(peer);
11540                   ao2_link(peers, peer);
11541                   peer = peer_unref(peer);
11542                }
11543             } else if (strcasecmp(utype, "user")) {
11544                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
11545             }
11546          } else
11547             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
11548       }
11549       cat = ast_category_browse(cfg, cat);
11550    }
11551    ast_config_destroy(cfg);
11552    set_timing();
11553    return 1;
11554 }

static void set_config_destroy ( void   )  [static]

Definition at line 11148 of file chan_iax2.c.

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

Referenced by set_config().

11149 {
11150    strcpy(accountcode, "");
11151    strcpy(language, "");
11152    strcpy(mohinterpret, "default");
11153    strcpy(mohsuggest, "");
11154    trunkmaxsize = MAX_TRUNKDATA;
11155    amaflags = 0;
11156    delayreject = 0;
11157    ast_clear_flag((&globalflags), IAX_NOTRANSFER); 
11158    ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 
11159    ast_clear_flag((&globalflags), IAX_USEJITTERBUF);  
11160    ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF);   
11161    delete_users();
11162 }

static void set_timing ( void   )  [static]

Definition at line 11133 of file chan_iax2.c.

References ast_log(), and LOG_WARNING.

Referenced by set_config().

11134 {
11135 #ifdef HAVE_DAHDI
11136    int bs = trunkfreq * 8;
11137    if (timingfd > -1) {
11138       if (
11139 #ifdef DAHDI_TIMERACK
11140          ioctl(timingfd, DAHDI_TIMERCONFIG, &bs) &&
11141 #endif         
11142          ioctl(timingfd, DAHDI_SET_BLOCKSIZE, &bs))
11143          ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n");
11144    }
11145 #endif
11146 }

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

Definition at line 790 of file chan_iax2.c.

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

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

00791 {
00792    ast_mutex_lock(lock);
00793    ast_cond_signal(cond);
00794    ast_mutex_unlock(lock);
00795 }

static int socket_process ( struct iax2_thread thread  )  [static]

Definition at line 8239 of file chan_iax2.c.

References ast_async_goto(), ast_best_codec(), ast_bridged_channel(), ast_calloc, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_free(), ast_channel_trylock, ast_channel_unlock, 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_debug, 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_free, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), 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_var_assign(), ast_variables_destroy(), ast_verb, 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, check_access(), check_provisioning(), cid_num, complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, DEADLOCK_AVOIDANCE, decrypt_frame(), dp_lookup(), ast_var_t::entries, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), iax2_dpcache::flags, format, ast_frame::frametype, globalflags, 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_variable_datastore_info, 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_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_TRUNK, iaxfrdup2(), ies, inaddrcmp(), ast_datastore::inheritance, iax2_peer::lastms, LOG_ERROR, log_jitterstats(), LOG_NOTICE, LOG_WARNING, make_trunk(), manager_event, iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, iax2_peer::name, ast_channel::name, NEW_ALLOW, NEW_PREVENT, iax_frame::oseqno, pbx_builtin_setvar_helper(), peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, raw_hangup(), REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, S_OR, save_osptoken(), save_rr(), sched, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax2_peer::smoothing, socket_process_meta(), spawn_dp_lookup(), stop_stuff(), store_by_peercallno(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, try_transfer(), iax_frame::ts, uncompress_subclass(), update_registry(), var, VERBOSE_PREFIX_4, vnak_retransmit(), and ast_iax2_meta_hdr::zeros.

Referenced by handle_deferred_full_frames().

08240 {
08241    struct sockaddr_in sin;
08242    int res;
08243    int updatehistory=1;
08244    int new = NEW_PREVENT;
08245    int dcallno = 0;
08246    struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf;
08247    struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf;
08248    struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf;
08249    struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf;
08250    struct iax_frame *fr;
08251    struct iax_frame *cur;
08252    struct ast_frame f = { 0, };
08253    struct ast_channel *c = NULL;
08254    struct iax2_dpcache *dp;
08255    struct iax2_peer *peer;
08256    struct iax_ies ies;
08257    struct iax_ie_data ied0, ied1;
08258    int format;
08259    int fd;
08260    int exists;
08261    int minivid = 0;
08262    char empty[32]="";      /* Safety measure */
08263    struct iax_frame *duped_fr;
08264    char host_pref_buf[128];
08265    char caller_pref_buf[128];
08266    struct ast_codec_pref pref;
08267    char *using_prefs = "mine";
08268 
08269    /* allocate an iax_frame with 4096 bytes of data buffer */
08270    fr = alloca(sizeof(*fr) + 4096);
08271    memset(fr, 0, sizeof(*fr));
08272    fr->afdatalen = 4096; /* From alloca() above */
08273 
08274    /* Copy frequently used parameters to the stack */
08275    res = thread->buf_len;
08276    fd = thread->iofd;
08277    memcpy(&sin, &thread->iosin, sizeof(sin));
08278 
08279    if (res < sizeof(*mh)) {
08280       ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int) sizeof(*mh));
08281       return 1;
08282    }
08283    if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) {
08284       if (res < sizeof(*vh)) {
08285          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));
08286          return 1;
08287       }
08288 
08289       /* This is a video frame, get call number */
08290       fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0);
08291       minivid = 1;
08292    } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000))
08293       return socket_process_meta(res, meta, &sin, fd, fr);
08294 
08295 #ifdef DEBUG_SUPPORT
08296    if (iaxdebug && (res >= sizeof(*fh)))
08297       iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh));
08298 #endif
08299    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
08300       if (res < sizeof(*fh)) {
08301          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));
08302          return 1;
08303       }
08304 
08305       /* Get the destination call number */
08306       dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS;
08307       /* Retrieve the type and subclass */
08308       f.frametype = fh->type;
08309       if (f.frametype == AST_FRAME_VIDEO) {
08310          f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1);
08311       } else {
08312          f.subclass = uncompress_subclass(fh->csub);
08313       }
08314 
08315       /* Deal with POKE/PONG without allocating a callno */
08316       if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) {
08317          /* Reply back with a PONG, but don't care about the result. */
08318          send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohl(fh->ts), fh->iseqno + 1);
08319          return 1;
08320       } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) {
08321          /* Ignore */
08322          return 1;
08323       }
08324 
08325       if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) ||
08326                          (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) ||
08327                          (f.subclass == IAX_COMMAND_REGREL)))
08328          new = NEW_ALLOW;
08329    } else {
08330       /* Don't know anything about it yet */
08331       f.frametype = AST_FRAME_NULL;
08332       f.subclass = 0;
08333    }
08334 
08335    if (!fr->callno) {
08336       int check_dcallno = 0;
08337 
08338       /*
08339        * We enforce accurate destination call numbers for all full frames except
08340        * LAGRQ and PING commands.  This is because older versions of Asterisk
08341        * schedule these commands to get sent very quickly, and they will sometimes
08342        * be sent before they receive the first frame from the other side.  When
08343        * that happens, it doesn't contain the destination call number.  However,
08344        * not checking it for these frames is safe.
08345        * 
08346        * Discussed in the following thread:
08347        *    http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 
08348        */
08349 
08350       if (ntohs(mh->callno) & IAX_FLAG_FULL) {
08351          check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1;
08352       }
08353 
08354       fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno);
08355    }
08356 
08357    if (fr->callno > 0)
08358       ast_mutex_lock(&iaxsl[fr->callno]);
08359 
08360    if (!fr->callno || !iaxs[fr->callno]) {
08361       /* A call arrived for a nonexistent destination.  Unless it's an "inval"
08362          frame, reply with an inval */
08363       if (ntohs(mh->callno) & IAX_FLAG_FULL) {
08364          /* We can only raw hangup control frames */
08365          if (((f.subclass != IAX_COMMAND_INVAL) &&
08366              (f.subclass != IAX_COMMAND_TXCNT) &&
08367              (f.subclass != IAX_COMMAND_TXACC) &&
08368              (f.subclass != IAX_COMMAND_FWDOWNL))||
08369              (f.frametype != AST_FRAME_IAX))
08370             raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL,
08371             fd);
08372       }
08373       if (fr->callno > 0) 
08374          ast_mutex_unlock(&iaxsl[fr->callno]);
08375       return 1;
08376    }
08377    if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) {
08378       if (decrypt_frame(fr->callno, fh, &f, &res)) {
08379          ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n");
08380          ast_mutex_unlock(&iaxsl[fr->callno]);
08381          return 1;
08382       }
08383 #ifdef DEBUG_SUPPORT
08384       else if (iaxdebug)
08385          iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh));
08386 #endif
08387    }
08388 
08389    /* count this frame */
08390    iaxs[fr->callno]->frames_received++;
08391 
08392    if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid &&
08393       f.subclass != IAX_COMMAND_TXCNT &&     /* for attended transfer */
08394       f.subclass != IAX_COMMAND_TXACC) {     /* for attended transfer */
08395       unsigned short new_peercallno;
08396       
08397       new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL);
08398       if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) {
08399          if (iaxs[fr->callno]->peercallno) {
08400             remove_by_peercallno(iaxs[fr->callno]);
08401          }
08402          iaxs[fr->callno]->peercallno = new_peercallno;
08403          store_by_peercallno(iaxs[fr->callno]);
08404       }
08405    }
08406    if (ntohs(mh->callno) & IAX_FLAG_FULL) {
08407       if (iaxdebug)
08408          ast_debug(1, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass);
08409       /* Check if it's out of order (and not an ACK or INVAL) */
08410       fr->oseqno = fh->oseqno;
08411       fr->iseqno = fh->iseqno;
08412       fr->ts = ntohl(fh->ts);
08413 #ifdef IAXTESTS
08414       if (test_resync) {
08415          ast_debug(1, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync);
08416          fr->ts += test_resync;
08417       }
08418 #endif /* IAXTESTS */
08419 #if 0
08420       if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) ||
08421            ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX &&
08422                         (f.subclass == IAX_COMMAND_NEW ||
08423                          f.subclass == IAX_COMMAND_AUTHREQ ||
08424                          f.subclass == IAX_COMMAND_ACCEPT ||
08425                          f.subclass == IAX_COMMAND_REJECT))      ) )
08426 #endif
08427       if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE))
08428          updatehistory = 0;
08429       if ((iaxs[fr->callno]->iseqno != fr->oseqno) &&
08430          (iaxs[fr->callno]->iseqno ||
08431             ((f.subclass != IAX_COMMAND_TXCNT) &&
08432             (f.subclass != IAX_COMMAND_TXREADY) &&    /* for attended transfer */
08433             (f.subclass != IAX_COMMAND_TXREL) &&      /* for attended transfer */
08434             (f.subclass != IAX_COMMAND_UNQUELCH ) &&  /* for attended transfer */
08435             (f.subclass != IAX_COMMAND_TXACC)) ||
08436             (f.frametype != AST_FRAME_IAX))) {
08437          if (
08438           ((f.subclass != IAX_COMMAND_ACK) &&
08439            (f.subclass != IAX_COMMAND_INVAL) &&
08440            (f.subclass != IAX_COMMAND_TXCNT) &&
08441            (f.subclass != IAX_COMMAND_TXREADY) &&     /* for attended transfer */
08442            (f.subclass != IAX_COMMAND_TXREL) &&    /* for attended transfer */
08443            (f.subclass != IAX_COMMAND_UNQUELCH ) &&   /* for attended transfer */
08444            (f.subclass != IAX_COMMAND_TXACC) &&
08445            (f.subclass != IAX_COMMAND_VNAK)) ||
08446            (f.frametype != AST_FRAME_IAX)) {
08447             /* If it's not an ACK packet, it's out of order. */
08448             ast_debug(1, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 
08449                iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass);
08450             /* Check to see if we need to request retransmission,
08451              * and take sequence number wraparound into account */
08452             if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) {
08453                /* If we've already seen it, ack it XXX There's a border condition here XXX */
08454                if ((f.frametype != AST_FRAME_IAX) || 
08455                      ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) {
08456                   ast_debug(1, "Acking anyway\n");
08457                   /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if
08458                      we have anything to send, we'll retransmit and get an ACK back anyway XXX */
08459                   send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08460                }
08461             } else {
08462                /* Send a VNAK requesting retransmission */
08463                iax2_vnak(fr->callno);
08464             }
08465             ast_mutex_unlock(&iaxsl[fr->callno]);
08466             return 1;
08467          }
08468       } else {
08469          /* Increment unless it's an ACK or VNAK */
08470          if (((f.subclass != IAX_COMMAND_ACK) &&
08471              (f.subclass != IAX_COMMAND_INVAL) &&
08472              (f.subclass != IAX_COMMAND_TXCNT) &&
08473              (f.subclass != IAX_COMMAND_TXACC) &&
08474             (f.subclass != IAX_COMMAND_VNAK)) ||
08475              (f.frametype != AST_FRAME_IAX))
08476             iaxs[fr->callno]->iseqno++;
08477       }
08478       /* A full frame */
08479       if (res < sizeof(*fh)) {
08480          ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int) sizeof(*fh));
08481          ast_mutex_unlock(&iaxsl[fr->callno]);
08482          return 1;
08483       }
08484       /* Ensure text frames are NULL-terminated */
08485       if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') {
08486          if (res < thread->buf_size)
08487             thread->buf[res++] = '\0';
08488          else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */
08489             thread->buf[res - 1] = '\0';
08490       }
08491       f.datalen = res - sizeof(*fh);
08492 
08493       /* Handle implicit ACKing unless this is an INVAL, and only if this is 
08494          from the real peer, not the transfer peer */
08495       if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
08496           ((f.subclass != IAX_COMMAND_INVAL) ||
08497            (f.frametype != AST_FRAME_IAX))) {
08498          unsigned char x;
08499          int call_to_destroy;
08500          /* XXX This code is not very efficient.  Surely there is a better way which still
08501                 properly handles boundary conditions? XXX */
08502          /* First we have to qualify that the ACKed value is within our window */
08503          for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++)
08504             if (fr->iseqno == x)
08505                break;
08506          if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) {
08507             /* The acknowledgement is within our window.  Time to acknowledge everything
08508                that it says to */
08509             for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) {
08510                /* Ack the packet with the given timestamp */
08511                if (iaxdebug)
08512                   ast_debug(1, "Cancelling transmission of packet %d\n", x);
08513                call_to_destroy = 0;
08514                AST_LIST_LOCK(&frame_queue);
08515                AST_LIST_TRAVERSE(&frame_queue, cur, list) {
08516                   /* If it's our call, and our timestamp, mark -1 retries */
08517                   if ((fr->callno == cur->callno) && (x == cur->oseqno)) {
08518                      cur->retries = -1;
08519                      /* Destroy call if this is the end */
08520                      if (cur->final)
08521                         call_to_destroy = fr->callno;
08522                   }
08523                }
08524                AST_LIST_UNLOCK(&frame_queue);
08525                if (call_to_destroy) {
08526                   if (iaxdebug)
08527                      ast_debug(1, "Really destroying %d, having been acked on final message\n", call_to_destroy);
08528                   ast_mutex_lock(&iaxsl[call_to_destroy]);
08529                   iax2_destroy(call_to_destroy);
08530                   ast_mutex_unlock(&iaxsl[call_to_destroy]);
08531                }
08532             }
08533             /* Note how much we've received acknowledgement for */
08534             if (iaxs[fr->callno])
08535                iaxs[fr->callno]->rseqno = fr->iseqno;
08536             else {
08537                /* Stop processing now */
08538                ast_mutex_unlock(&iaxsl[fr->callno]);
08539                return 1;
08540             }
08541          } else {
08542             ast_debug(1, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno);
08543          }
08544       }
08545       if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 
08546          ((f.frametype != AST_FRAME_IAX) || 
08547           ((f.subclass != IAX_COMMAND_TXACC) &&
08548            (f.subclass != IAX_COMMAND_TXCNT)))) {
08549          /* Only messages we accept from a transfer host are TXACC and TXCNT */
08550          ast_mutex_unlock(&iaxsl[fr->callno]);
08551          return 1;
08552       }
08553 
08554       if (f.datalen) {
08555          if (f.frametype == AST_FRAME_IAX) {
08556             if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) {
08557                ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr));
08558                ast_mutex_unlock(&iaxsl[fr->callno]);
08559                return 1;
08560             }
08561             f.data = NULL;
08562             f.datalen = 0;
08563          } else {
08564             f.data = thread->buf + sizeof(*fh);
08565             memset(&ies, 0, sizeof(ies));
08566          }
08567       } else {
08568          if (f.frametype == AST_FRAME_IAX)
08569             f.data = NULL;
08570          else
08571             f.data = empty;
08572          memset(&ies, 0, sizeof(ies));
08573       }
08574 
08575       /* when we receive the first full frame for a new incoming channel,
08576          it is safe to start the PBX on the channel because we have now
08577          completed a 3-way handshake with the peer */
08578       if ((f.frametype == AST_FRAME_VOICE) ||
08579           (f.frametype == AST_FRAME_VIDEO) ||
08580           (f.frametype == AST_FRAME_IAX)) {
08581          if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
08582             ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
08583             if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) {
08584                ast_mutex_unlock(&iaxsl[fr->callno]);
08585                return 1;
08586             }
08587          }
08588 
08589          if (ies.vars) {
08590             struct ast_datastore *variablestore;
08591             struct ast_variable *var, *prev = NULL;
08592             AST_LIST_HEAD(, ast_var_t) *varlist;
08593             if ((c = iaxs[fr->callno]->owner)) {
08594                varlist = ast_calloc(1, sizeof(*varlist));
08595                variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL);
08596                if (variablestore && varlist) {
08597                   variablestore->data = varlist;
08598                   variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
08599                   AST_LIST_HEAD_INIT(varlist);
08600                   ast_debug(1, "I can haz IAX vars?\n");
08601                   for (var = ies.vars; var; var = var->next) {
08602                      struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
08603                      if (prev) {
08604                         ast_free(prev);
08605                      }
08606                      prev = var;
08607                      if (!newvar) {
08608                         /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */
08609                         ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
08610                      } else {
08611                         AST_LIST_INSERT_TAIL(varlist, newvar, entries);
08612                      }
08613                   }
08614                   if (prev) {
08615                      ast_free(prev);
08616                   }
08617                   ies.vars = NULL;
08618                   ast_channel_datastore_add(c, variablestore);
08619                } else {
08620                   ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
08621                   if (variablestore) {
08622                      ast_channel_datastore_free(variablestore);
08623                   }
08624                   if (varlist) {
08625                      ast_free(varlist);
08626                   }
08627                }
08628             } else {
08629                /* No channel yet, so transfer the variables directly over to the pvt,
08630                 * for later inheritance. */
08631                ast_debug(1, "No channel, so populating IAXVARs to the pvt, as an intermediate step.\n");
08632                for (var = ies.vars; var && var->next; var = var->next);
08633                if (var) {
08634                   var->next = iaxs[fr->callno]->iaxvars;
08635                   iaxs[fr->callno]->iaxvars = ies.vars;
08636                   ies.vars = NULL;
08637                }
08638             }
08639          }
08640       }
08641 
08642       if (ies.vars) {
08643          ast_debug(1, "I have IAX variables, but they were not processed\n");
08644       }
08645 
08646       if (f.frametype == AST_FRAME_VOICE) {
08647          if (f.subclass != iaxs[fr->callno]->voiceformat) {
08648                iaxs[fr->callno]->voiceformat = f.subclass;
08649                ast_debug(1, "Ooh, voice format changed to %d\n", f.subclass);
08650                if (iaxs[fr->callno]->owner) {
08651                   int orignative;
08652 retryowner:
08653                   if (ast_channel_trylock(iaxs[fr->callno]->owner)) {
08654                      DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
08655                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner;
08656                   }
08657                   if (iaxs[fr->callno]) {
08658                      if (iaxs[fr->callno]->owner) {
08659                         orignative = iaxs[fr->callno]->owner->nativeformats;
08660                         iaxs[fr->callno]->owner->nativeformats = f.subclass;
08661                         if (iaxs[fr->callno]->owner->readformat)
08662                            ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);
08663                         iaxs[fr->callno]->owner->nativeformats = orignative;
08664                         ast_channel_unlock(iaxs[fr->callno]->owner);
08665                      }
08666                   } else {
08667                      ast_debug(1, "Neat, somebody took away the channel at a magical time but i found it!\n");
08668                      /* Free remote variables (if any) */
08669                      if (ies.vars) {
08670                         ast_variables_destroy(ies.vars);
08671                         ast_debug(1, "I can haz iaxvars, but they is no good.  :-(\n");
08672                         ies.vars = NULL;
08673                      }
08674                      ast_mutex_unlock(&iaxsl[fr->callno]);
08675                      return 1;
08676                   }
08677                }
08678          }
08679       }
08680       if (f.frametype == AST_FRAME_VIDEO) {
08681          if (f.subclass != iaxs[fr->callno]->videoformat) {
08682             ast_debug(1, "Ooh, video format changed to %d\n", f.subclass & ~0x1);
08683             iaxs[fr->callno]->videoformat = f.subclass & ~0x1;
08684          }
08685       }
08686       if (f.frametype == AST_FRAME_CONTROL && iaxs[fr->callno]->owner) {
08687          if (f.subclass == AST_CONTROL_BUSY) {
08688             iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_BUSY;
08689          } else if (f.subclass == AST_CONTROL_CONGESTION) {
08690             iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_CONGESTION;
08691          }
08692       }
08693       if (f.frametype == AST_FRAME_IAX) {
08694          AST_SCHED_DEL(sched, iaxs[fr->callno]->initid);
08695          /* Handle the IAX pseudo frame itself */
08696          if (iaxdebug)
08697             ast_debug(1, "IAX subclass %d received\n", f.subclass);
08698 
08699                         /* Update last ts unless the frame's timestamp originated with us. */
08700          if (iaxs[fr->callno]->last < fr->ts &&
08701                             f.subclass != IAX_COMMAND_ACK &&
08702                             f.subclass != IAX_COMMAND_PONG &&
08703                             f.subclass != IAX_COMMAND_LAGRP) {
08704             iaxs[fr->callno]->last = fr->ts;
08705             if (iaxdebug)
08706                ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts);
08707          }
08708          iaxs[fr->callno]->last_iax_message = f.subclass;
08709          if (!iaxs[fr->callno]->first_iax_message) {
08710             iaxs[fr->callno]->first_iax_message = f.subclass;
08711          }
08712          switch(f.subclass) {
08713          case IAX_COMMAND_ACK:
08714             /* Do nothing */
08715             break;
08716          case IAX_COMMAND_QUELCH:
08717             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
08718                     /* Generate Manager Hold event, if necessary*/
08719                if (iaxs[fr->callno]->owner) {
08720                   manager_event(EVENT_FLAG_CALL, "Hold",
08721                      "Status: On\r\n"
08722                      "Channel: %s\r\n"
08723                      "Uniqueid: %s\r\n",
08724                      iaxs[fr->callno]->owner->name, 
08725                      iaxs[fr->callno]->owner->uniqueid);
08726                }
08727 
08728                ast_set_flag(iaxs[fr->callno], IAX_QUELCH);
08729                if (ies.musiconhold) {
08730                   if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
08731                      const char *mohsuggest = iaxs[fr->callno]->mohsuggest;
08732                      iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 
08733                         S_OR(mohsuggest, NULL),
08734                         !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0);
08735                      if (!iaxs[fr->callno]) {
08736                         ast_mutex_unlock(&iaxsl[fr->callno]);
08737                         return 1;
08738                      }
08739                   }
08740                }
08741             }
08742             break;
08743          case IAX_COMMAND_UNQUELCH:
08744             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
08745                     /* Generate Manager Unhold event, if necessary*/
08746                if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) {
08747                   manager_event(EVENT_FLAG_CALL, "Hold",
08748                      "Status: Off\r\n"
08749                      "Channel: %s\r\n"
08750                      "Uniqueid: %s\r\n",
08751                      iaxs[fr->callno]->owner->name, 
08752                      iaxs[fr->callno]->owner->uniqueid);
08753                }
08754 
08755                ast_clear_flag(iaxs[fr->callno], IAX_QUELCH);
08756                if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) {
08757                   iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0);
08758                   if (!iaxs[fr->callno]) {
08759                      ast_mutex_unlock(&iaxsl[fr->callno]);
08760                      return 1;
08761                   }
08762                }
08763             }
08764             break;
08765          case IAX_COMMAND_TXACC:
08766             if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
08767                /* Ack the packet with the given timestamp */
08768                AST_LIST_LOCK(&frame_queue);
08769                AST_LIST_TRAVERSE(&frame_queue, cur, list) {
08770                   /* Cancel any outstanding txcnt's */
08771                   if ((fr->callno == cur->callno) && (cur->transfer))
08772                      cur->retries = -1;
08773                }
08774                AST_LIST_UNLOCK(&frame_queue);
08775                memset(&ied1, 0, sizeof(ied1));
08776                iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno);
08777                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1);
08778                iaxs[fr->callno]->transferring = TRANSFER_READY;
08779             }
08780             break;
08781          case IAX_COMMAND_NEW:
08782             /* Ignore if it's already up */
08783             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD))
08784                break;
08785             if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
08786                ast_mutex_unlock(&iaxsl[fr->callno]);
08787                check_provisioning(&sin, fd, ies.serviceident, ies.provver);
08788                ast_mutex_lock(&iaxsl[fr->callno]);
08789                if (!iaxs[fr->callno]) {
08790                   ast_mutex_unlock(&iaxsl[fr->callno]);
08791                   return 1;
08792                }
08793             }
08794             /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */
08795             if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) {
08796                int new_callno;
08797                if ((new_callno = make_trunk(fr->callno, 1)) != -1)
08798                   fr->callno = new_callno;
08799             }
08800             /* For security, always ack immediately */
08801             if (delayreject)
08802                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
08803             if (check_access(fr->callno, &sin, &ies)) {
08804                /* They're not allowed on */
08805                auth_fail(fr->callno, IAX_COMMAND_REJECT);
08806                if (authdebug)
08807                   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);
08808                break;
08809             }
08810             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
08811                const char *context, *exten, *cid_num;
08812 
08813                context = ast_strdupa(iaxs[fr->callno]->context);
08814                exten = ast_strdupa(iaxs[fr->callno]->exten);
08815                cid_num = ast_strdupa(iaxs[fr->callno]->cid_num);
08816 
08817                /* This might re-enter the IAX code and need the lock */
08818                ast_mutex_unlock(&iaxsl[fr->callno]);
08819                exists = ast_exists_extension(NULL, context, exten, 1, cid_num);
08820                ast_mutex_lock(&iaxsl[fr->callno]);
08821 
08822                if (!iaxs[fr->callno]) {
08823                   ast_mutex_unlock(&iaxsl[fr->callno]);
08824                   return 1;
08825                }
08826             } else
08827                exists = 0;
08828             /* Get OSP token if it does exist */
08829             save_osptoken(fr, &ies);
08830             if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) {
08831                if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
08832                   memset(&ied0, 0, sizeof(ied0));
08833                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
08834                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
08835                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08836                   if (!iaxs[fr->callno]) {
08837                      ast_mutex_unlock(&iaxsl[fr->callno]);
08838                      return 1;
08839                   }
08840                   if (authdebug)
08841                      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);
08842                } else {
08843                   /* Select an appropriate format */
08844 
08845                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
08846                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
08847                         using_prefs = "reqonly";
08848                      } else {
08849                         using_prefs = "disabled";
08850                      }
08851                      format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
08852                      memset(&pref, 0, sizeof(pref));
08853                      strcpy(caller_pref_buf, "disabled");
08854                      strcpy(host_pref_buf, "disabled");
08855                   } else {
08856                      using_prefs = "mine";
08857                      /* If the information elements are in here... use them */
08858                      if (ies.codec_prefs)
08859                         ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
08860                      if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
08861                         /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/
08862                         if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
08863                            pref = iaxs[fr->callno]->rprefs;
08864                            using_prefs = "caller";
08865                         } else {
08866                            pref = iaxs[fr->callno]->prefs;
08867                         }
08868                      } else
08869                         pref = iaxs[fr->callno]->prefs;
08870                      
08871                      format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
08872                      ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
08873                      ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
08874                   }
08875                   if (!format) {
08876                      if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
08877                         format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
08878                      if (!format) {
08879                         memset(&ied0, 0, sizeof(ied0));
08880                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
08881                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
08882                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08883                         if (!iaxs[fr->callno]) {
08884                            ast_mutex_unlock(&iaxsl[fr->callno]);
08885                            return 1;
08886                         }
08887                         if (authdebug) {
08888                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
08889                               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);
08890                            else 
08891                               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);
08892                         }
08893                      } else {
08894                         /* Pick one... */
08895                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
08896                            if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
08897                               format = 0;
08898                         } else {
08899                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
08900                               using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
08901                               memset(&pref, 0, sizeof(pref));
08902                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
08903                               strcpy(caller_pref_buf,"disabled");
08904                               strcpy(host_pref_buf,"disabled");
08905                            } else {
08906                               using_prefs = "mine";
08907                               if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
08908                                  /* Do the opposite of what we tried above. */
08909                                  if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
08910                                     pref = iaxs[fr->callno]->prefs;                       
08911                                  } else {
08912                                     pref = iaxs[fr->callno]->rprefs;
08913                                     using_prefs = "caller";
08914                                  }
08915                                  format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
08916                            
08917                               } else /* if no codec_prefs IE do it the old way */
08918                                  format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
08919                            }
08920                         }
08921 
08922                         if (!format) {
08923                            memset(&ied0, 0, sizeof(ied0));
08924                            iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
08925                            iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
08926                            ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
08927                            send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
08928                            if (!iaxs[fr->callno]) {
08929                               ast_mutex_unlock(&iaxsl[fr->callno]);
08930                               return 1;
08931                            }
08932                            if (authdebug)
08933                               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);
08934                            ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);   
08935                            break;
08936                         }
08937                      }
08938                   }
08939                   if (format) {
08940                      /* No authentication required, let them in */
08941                      memset(&ied1, 0, sizeof(ied1));
08942                      iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
08943                      send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
08944                      if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
08945                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
08946                         ast_verb(3, "Accepting UNAUTHENTICATED call from %s:\n"
08947                                     "%srequested format = %s,\n"
08948                                     "%srequested prefs = %s,\n"
08949                                     "%sactual format = %s,\n"
08950                                     "%shost prefs = %s,\n"
08951                                     "%spriority = %s\n",
08952                                     ast_inet_ntoa(sin.sin_addr), 
08953                                     VERBOSE_PREFIX_4,
08954                                     ast_getformatname(iaxs[fr->callno]->peerformat), 
08955                                     VERBOSE_PREFIX_4,
08956                                     caller_pref_buf,
08957                                     VERBOSE_PREFIX_4,
08958                                     ast_getformatname(format), 
08959                                     VERBOSE_PREFIX_4,
08960                                     host_pref_buf, 
08961                                     VERBOSE_PREFIX_4,
08962                                     using_prefs);
08963                         
08964                         iaxs[fr->callno]->chosenformat = format;
08965                         ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART);
08966                      } else {
08967                         ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
08968                         /* If this is a TBD call, we're ready but now what...  */
08969                         ast_verb(3, "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
08970                      }
08971                   }
08972                }
08973                break;
08974             }
08975             if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5)
08976                merge_encryption(iaxs[fr->callno],ies.encmethods);
08977             else
08978                iaxs[fr->callno]->encmethods = 0;
08979             if (!authenticate_request(fr->callno) && iaxs[fr->callno])
08980                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED);
08981             if (!iaxs[fr->callno]) {
08982                ast_mutex_unlock(&iaxsl[fr->callno]);
08983                return 1;
08984             }
08985             break;
08986          case IAX_COMMAND_DPREQ:
08987             /* Request status in the dialplan */
08988             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) &&
08989                !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) {
08990                if (iaxcompat) {
08991                   /* Spawn a thread for the lookup */
08992                   spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num);
08993                } else {
08994                   /* Just look it up */
08995                   dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1);
08996                }
08997             }
08998             break;
08999          case IAX_COMMAND_HANGUP:
09000             ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
09001             ast_debug(1, "Immediately destroying %d, having received hangup\n", fr->callno);
09002             /* Set hangup cause according to remote */
09003             if (ies.causecode && iaxs[fr->callno]->owner)
09004                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
09005             /* Send ack immediately, before we destroy */
09006             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09007             iax2_destroy(fr->callno);
09008             break;
09009          case IAX_COMMAND_REJECT:
09010             /* Set hangup cause according to remote */
09011             if (ies.causecode && iaxs[fr->callno]->owner)
09012                iaxs[fr->callno]->owner->hangupcause = ies.causecode;
09013 
09014             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
09015                if (iaxs[fr->callno]->owner && authdebug)
09016                   ast_log(LOG_WARNING, "Call rejected by %s: %s\n",
09017                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr),
09018                      ies.cause ? ies.cause : "<Unknown>");
09019                ast_debug(1, "Immediately destroying %d, having received reject\n",
09020                   fr->callno);
09021             }
09022             /* Send ack immediately, before we destroy */
09023             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK,
09024                          fr->ts, NULL, 0, fr->iseqno);
09025             if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION))
09026                iaxs[fr->callno]->error = EPERM;
09027             iax2_destroy(fr->callno);
09028             break;
09029          case IAX_COMMAND_TRANSFER:
09030          {
09031             struct ast_channel *bridged_chan;
09032 
09033             if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) {
09034                /* Set BLINDTRANSFER channel variables */
09035 
09036                ast_mutex_unlock(&iaxsl[fr->callno]);
09037                pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name);
09038                ast_mutex_lock(&iaxsl[fr->callno]);
09039                if (!iaxs[fr->callno]) {
09040                   ast_mutex_unlock(&iaxsl[fr->callno]);
09041                   return 1;
09042                }
09043 
09044                pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name);
09045                if (!strcmp(ies.called_number, ast_parking_ext())) {
09046                   struct ast_channel *saved_channel = iaxs[fr->callno]->owner;
09047                   ast_mutex_unlock(&iaxsl[fr->callno]);
09048                   if (iax_park(bridged_chan, saved_channel)) {
09049                      ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name);
09050                   } else {
09051                      ast_debug(1, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name);
09052                   }
09053                   ast_mutex_lock(&iaxsl[fr->callno]);
09054                } else {
09055                   if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1))
09056                      ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 
09057                         ies.called_number, iaxs[fr->callno]->context);
09058                   else {
09059                      ast_debug(1, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 
09060                         ies.called_number, iaxs[fr->callno]->context);
09061                   }
09062                }
09063             } else {
09064                ast_debug(1, "Async goto not applicable on call %d\n", fr->callno);
09065             }
09066 
09067             break;
09068          }
09069          case IAX_COMMAND_ACCEPT:
09070             /* Ignore if call is already up or needs authentication or is a TBD */
09071             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED))
09072                break;
09073             if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) {
09074                /* Send ack immediately, before we destroy */
09075                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09076                iax2_destroy(fr->callno);
09077                break;
09078             }
09079             if (ies.format) {
09080                iaxs[fr->callno]->peerformat = ies.format;
09081             } else {
09082                if (iaxs[fr->callno]->owner)
09083                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats;
09084                else
09085                   iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability;
09086             }
09087             ast_verb(3, "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat));
09088             if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) {
09089                memset(&ied0, 0, sizeof(ied0));
09090                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
09091                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
09092                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
09093                if (!iaxs[fr->callno]) {
09094                   ast_mutex_unlock(&iaxsl[fr->callno]);
09095                   return 1;
09096                }
09097                if (authdebug)
09098                   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);
09099             } else {
09100                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
09101                if (iaxs[fr->callno]->owner) {
09102                   /* Switch us to use a compatible format */
09103                   iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat;
09104                   ast_verb(3, "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats));
09105 retryowner2:
09106                   if (ast_channel_trylock(iaxs[fr->callno]->owner)) {
09107                      DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
09108                      if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2;
09109                   }
09110                   
09111                   if (iaxs[fr->callno] && iaxs[fr->callno]->owner) {
09112                      /* Setup read/write formats properly. */
09113                      if (iaxs[fr->callno]->owner->writeformat)
09114                         ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat);   
09115                      if (iaxs[fr->callno]->owner->readformat)
09116                         ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat);  
09117                      ast_channel_unlock(iaxs[fr->callno]->owner);
09118                   }
09119                }
09120             }
09121             if (iaxs[fr->callno]) {
09122                AST_LIST_LOCK(&dpcache);
09123                AST_LIST_TRAVERSE(&iaxs[fr->callno]->dpentries, dp, peer_list)
09124                   if (!(dp->flags & CACHE_FLAG_TRANSMITTED))
09125                      iax2_dprequest(dp, fr->callno);
09126                AST_LIST_UNLOCK(&dpcache);
09127             }
09128             break;
09129          case IAX_COMMAND_POKE:
09130             /* Send back a pong packet with the original timestamp */
09131             send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1);
09132             if (!iaxs[fr->callno]) {
09133                ast_mutex_unlock(&iaxsl[fr->callno]);
09134                return 1;
09135             }
09136             break;
09137          case IAX_COMMAND_PING:
09138          {
09139             struct iax_ie_data pingied;
09140             construct_rr(iaxs[fr->callno], &pingied);
09141             /* Send back a pong packet with the original timestamp */
09142             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1);
09143          }
09144             break;
09145          case IAX_COMMAND_PONG:
09146             /* Calculate ping time */
09147             iaxs[fr->callno]->pingtime =  calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts;
09148             /* save RR info */
09149             save_rr(fr, &ies);
09150 
09151             /* Good time to write jb stats for this call */
09152             log_jitterstats(fr->callno);
09153 
09154             if (iaxs[fr->callno]->peerpoke) {
09155                peer = iaxs[fr->callno]->peerpoke;
09156                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) {
09157                   if (iaxs[fr->callno]->pingtime <= peer->maxms) {
09158                      ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime);
09159                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
09160                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
09161                   }
09162                } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) {
09163                   if (iaxs[fr->callno]->pingtime > peer->maxms) {
09164                      ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime);
09165                      manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 
09166                      ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
09167                   }
09168                }
09169                peer->lastms = iaxs[fr->callno]->pingtime;
09170                if (peer->smoothing && (peer->lastms > -1))
09171                   peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2;
09172                else if (peer->smoothing && peer->lastms < 0)
09173                   peer->historicms = (0 + peer->historicms) / 2;
09174                else              
09175                   peer->historicms = iaxs[fr->callno]->pingtime;
09176 
09177                /* Remove scheduled iax2_poke_noanswer */
09178                if (peer->pokeexpire > -1) {
09179                   if (!ast_sched_del(sched, peer->pokeexpire)) {
09180                      peer_unref(peer);
09181                      peer->pokeexpire = -1;
09182                   }
09183                }
09184                /* Schedule the next cycle */
09185                if ((peer->lastms < 0)  || (peer->historicms > peer->maxms)) 
09186                   peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer));
09187                else
09188                   peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer));
09189                if (peer->pokeexpire == -1)
09190                   peer_unref(peer);
09191                /* and finally send the ack */
09192                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09193                /* And wrap up the qualify call */
09194                iax2_destroy(fr->callno);
09195                peer->callno = 0;
09196                ast_debug(1, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms);
09197             }
09198             break;
09199          case IAX_COMMAND_LAGRQ:
09200          case IAX_COMMAND_LAGRP:
09201             f.src = "LAGRQ";
09202             f.mallocd = 0;
09203             f.offset = 0;
09204             f.samples = 0;
09205             iax_frame_wrap(fr, &f);
09206             if(f.subclass == IAX_COMMAND_LAGRQ) {
09207                /* Received a LAGRQ - echo back a LAGRP */
09208                fr->af.subclass = IAX_COMMAND_LAGRP;
09209                iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0);
09210             } else {
09211                /* Received LAGRP in response to our LAGRQ */
09212                unsigned int ts;
09213                /* This is a reply we've been given, actually measure the difference */
09214                ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af);
09215                iaxs[fr->callno]->lag = ts - fr->ts;
09216                if (iaxdebug)
09217                   ast_debug(1, "Peer %s lag measured as %dms\n",
09218                      ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag);
09219             }
09220             break;
09221          case IAX_COMMAND_AUTHREQ:
09222             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
09223                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>");
09224                break;
09225             }
09226             if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) {
09227                struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL,
09228                         .subclass = AST_CONTROL_HANGUP,
09229                };
09230                ast_log(LOG_WARNING, 
09231                   "I don't know how to authenticate %s to %s\n", 
09232                   ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr));
09233                iax2_queue_frame(fr->callno, &hangup_fr);
09234             }
09235             if (!iaxs[fr->callno]) {
09236                ast_mutex_unlock(&iaxsl[fr->callno]);
09237                return 1;
09238             }
09239             break;
09240          case IAX_COMMAND_AUTHREP:
09241             /* For security, always ack immediately */
09242             if (delayreject)
09243                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09244             /* Ignore once we've started */
09245             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) {
09246                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>");
09247                break;
09248             }
09249             if (authenticate_verify(iaxs[fr->callno], &ies)) {
09250                if (authdebug)
09251                   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);
09252                memset(&ied0, 0, sizeof(ied0));
09253                auth_fail(fr->callno, IAX_COMMAND_REJECT);
09254                break;
09255             }
09256             if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) {
09257                /* This might re-enter the IAX code and need the lock */
09258                exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num);
09259             } else
09260                exists = 0;
09261             if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) {
09262                if (authdebug)
09263                   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);
09264                memset(&ied0, 0, sizeof(ied0));
09265                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
09266                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
09267                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
09268                if (!iaxs[fr->callno]) {
09269                   ast_mutex_unlock(&iaxsl[fr->callno]);
09270                   return 1;
09271                }
09272             } else {
09273                /* Select an appropriate format */
09274                if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
09275                   if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
09276                      using_prefs = "reqonly";
09277                   } else {
09278                      using_prefs = "disabled";
09279                   }
09280                   format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability;
09281                   memset(&pref, 0, sizeof(pref));
09282                   strcpy(caller_pref_buf, "disabled");
09283                   strcpy(host_pref_buf, "disabled");
09284                } else {
09285                   using_prefs = "mine";
09286                   if (ies.codec_prefs)
09287                      ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0);
09288                   if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
09289                      if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
09290                         pref = iaxs[fr->callno]->rprefs;
09291                         using_prefs = "caller";
09292                      } else {
09293                         pref = iaxs[fr->callno]->prefs;
09294                      }
09295                   } else /* if no codec_prefs IE do it the old way */
09296                      pref = iaxs[fr->callno]->prefs;
09297                
09298                   format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0);
09299                   ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1);
09300                   ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1);
09301                }
09302                if (!format) {
09303                   if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
09304                      ast_debug(1, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability);
09305                      format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability;
09306                   }
09307                   if (!format) {
09308                      if (authdebug) {
09309                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 
09310                            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);
09311                         else
09312                            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);
09313                      }
09314                      memset(&ied0, 0, sizeof(ied0));
09315                      iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
09316                      iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
09317                      send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
09318                      if (!iaxs[fr->callno]) {
09319                         ast_mutex_unlock(&iaxsl[fr->callno]);
09320                         return 1;
09321                      }
09322                   } else {
09323                      /* Pick one... */
09324                      if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) {
09325                         if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability))
09326                            format = 0;
09327                      } else {
09328                         if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) {
09329                            using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled";
09330                            memset(&pref, 0, sizeof(pref));
09331                            format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ?
09332                               iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
09333                            strcpy(caller_pref_buf,"disabled");
09334                            strcpy(host_pref_buf,"disabled");
09335                         } else {
09336                            using_prefs = "mine";
09337                            if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) {
09338                               /* Do the opposite of what we tried above. */
09339                               if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) {
09340                                  pref = iaxs[fr->callno]->prefs;                 
09341                               } else {
09342                                  pref = iaxs[fr->callno]->rprefs;
09343                                  using_prefs = "caller";
09344                               }
09345                               format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1);
09346                            } else /* if no codec_prefs IE do it the old way */
09347                               format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 
09348                         }
09349                      }
09350                      if (!format) {
09351                         ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability);
09352                         if (authdebug) {
09353                            if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP))
09354                               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);
09355                            else
09356                               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);
09357                         }
09358                         memset(&ied0, 0, sizeof(ied0));
09359                         iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
09360                         iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
09361                         send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
09362                         if (!iaxs[fr->callno]) {
09363                            ast_mutex_unlock(&iaxsl[fr->callno]);
09364                            return 1;
09365                         }
09366                      }
09367                   }
09368                }
09369                if (format) {
09370                   /* Authentication received */
09371                   memset(&ied1, 0, sizeof(ied1));
09372                   iax_ie_append_int(&ied1, IAX_IE_FORMAT, format);
09373                   send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1);
09374                   if (strcmp(iaxs[fr->callno]->exten, "TBD")) {
09375                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
09376                      ast_verb(3, "Accepting AUTHENTICATED call from %s:\n"
09377                                  "%srequested format = %s,\n"
09378                                  "%srequested prefs = %s,\n"
09379                                  "%sactual format = %s,\n"
09380                                  "%shost prefs = %s,\n"
09381                                  "%spriority = %s\n", 
09382                                  ast_inet_ntoa(sin.sin_addr), 
09383                                  VERBOSE_PREFIX_4,
09384                                  ast_getformatname(iaxs[fr->callno]->peerformat),
09385                                  VERBOSE_PREFIX_4,
09386                                  caller_pref_buf,
09387                                  VERBOSE_PREFIX_4,
09388                                  ast_getformatname(format),
09389                                  VERBOSE_PREFIX_4,
09390                                  host_pref_buf,
09391                                  VERBOSE_PREFIX_4,
09392                                  using_prefs);
09393 
09394                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
09395                      if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format)))
09396                         iax2_destroy(fr->callno);
09397                      else if (ies.vars) {
09398                         struct ast_datastore *variablestore;
09399                         struct ast_variable *var, *prev = NULL;
09400                         AST_LIST_HEAD(, ast_var_t) *varlist;
09401                         varlist = ast_calloc(1, sizeof(*varlist));
09402                         variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL);
09403                         if (variablestore && varlist) {
09404                            variablestore->data = varlist;
09405                            variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
09406                            AST_LIST_HEAD_INIT(varlist);
09407                            ast_debug(1, "I can haz IAX vars? w00t\n");
09408                            for (var = ies.vars; var; var = var->next) {
09409                               struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
09410                               if (prev)
09411                                  ast_free(prev);
09412                               prev = var;
09413                               if (!newvar) {
09414                                  /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */
09415                                  ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
09416                               } else {
09417                                  AST_LIST_INSERT_TAIL(varlist, newvar, entries);
09418                               }
09419                            }
09420                            if (prev)
09421                               ast_free(prev);
09422                            ies.vars = NULL;
09423                            ast_channel_datastore_add(c, variablestore);
09424                         } else {
09425                            ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
09426                            if (variablestore)
09427                               ast_channel_datastore_free(variablestore);
09428                            if (varlist)
09429                               ast_free(varlist);
09430                         }
09431                      }
09432                   } else {
09433                      ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
09434                      /* If this is a TBD call, we're ready but now what...  */
09435                      ast_verb(3, "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr));
09436                   }
09437                }
09438             }
09439             break;
09440          case IAX_COMMAND_DIAL:
09441             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) {
09442                ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
09443                ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s");
09444                if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) {
09445                   if (authdebug)
09446                      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);
09447                   memset(&ied0, 0, sizeof(ied0));
09448                   iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
09449                   iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
09450                   send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
09451                   if (!iaxs[fr->callno]) {
09452                      ast_mutex_unlock(&iaxsl[fr->callno]);
09453                      return 1;
09454                   }
09455                } else {
09456                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
09457                   ast_verb(3, "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat);
09458                   ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
09459                   send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
09460                   if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat)))
09461                      iax2_destroy(fr->callno);
09462                   else if (ies.vars) {
09463                      struct ast_datastore *variablestore;
09464                      struct ast_variable *var, *prev = NULL;
09465                      AST_LIST_HEAD(, ast_var_t) *varlist;
09466                      varlist = ast_calloc(1, sizeof(*varlist));
09467                      variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL);
09468                      if (variablestore && varlist) {
09469                         variablestore->data = varlist;
09470                         variablestore->inheritance = DATASTORE_INHERIT_FOREVER;
09471                         AST_LIST_HEAD_INIT(varlist);
09472                         for (var = ies.vars; var; var = var->next) {
09473                            struct ast_var_t *newvar = ast_var_assign(var->name, var->value);
09474                            if (prev)
09475                               ast_free(prev);
09476                            prev = var;
09477                            if (!newvar) {
09478                               /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */
09479                               ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
09480                            } else {
09481                               AST_LIST_INSERT_TAIL(varlist, newvar, entries);
09482                            }
09483                         }
09484                         if (prev)
09485                            ast_free(prev);
09486                         ies.vars = NULL;
09487                         ast_channel_datastore_add(c, variablestore);
09488                      } else {
09489                         ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n");
09490                         if (variablestore)
09491                            ast_channel_datastore_free(variablestore);
09492                         if (varlist)
09493                            ast_free(varlist);
09494                      }
09495                   }
09496                }
09497             }
09498             break;
09499          case IAX_COMMAND_INVAL:
09500             iaxs[fr->callno]->error = ENOTCONN;
09501             ast_debug(1, "Immediately destroying %d, having received INVAL\n", fr->callno);
09502             iax2_destroy(fr->callno);
09503             ast_debug(1, "Destroying call %d\n", fr->callno);
09504             break;
09505          case IAX_COMMAND_VNAK:
09506             ast_debug(1, "Received VNAK: resending outstanding frames\n");
09507             /* Force retransmission */
09508             vnak_retransmit(fr->callno, fr->iseqno);
09509             break;
09510          case IAX_COMMAND_REGREQ:
09511          case IAX_COMMAND_REGREL:
09512             /* For security, always ack immediately */
09513             if (delayreject)
09514                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09515             if (register_verify(fr->callno, &sin, &ies)) {
09516                if (!iaxs[fr->callno]) {
09517                   ast_mutex_unlock(&iaxsl[fr->callno]);
09518                   return 1;
09519                }
09520                /* Send delayed failure */
09521                auth_fail(fr->callno, IAX_COMMAND_REGREJ);
09522                break;
09523             }
09524             if (!iaxs[fr->callno]) {
09525                ast_mutex_unlock(&iaxsl[fr->callno]);
09526                return 1;
09527             }
09528             if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) ||
09529                   ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED)) {
09530 
09531                if (f.subclass == IAX_COMMAND_REGREL)
09532                   memset(&sin, 0, sizeof(sin));
09533                if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh))
09534                   ast_log(LOG_WARNING, "Registry error\n");
09535                if (!iaxs[fr->callno]) {
09536                   ast_mutex_unlock(&iaxsl[fr->callno]);
09537                   return 1;
09538                }
09539                if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) {
09540                   ast_mutex_unlock(&iaxsl[fr->callno]);
09541                   check_provisioning(&sin, fd, ies.serviceident, ies.provver);
09542                   ast_mutex_lock(&iaxsl[fr->callno]);
09543                   if (!iaxs[fr->callno]) {
09544                      ast_mutex_unlock(&iaxsl[fr->callno]);
09545                      return 1;
09546                   }
09547                }
09548                break;
09549             }
09550             registry_authrequest(fr->callno);
09551             if (!iaxs[fr->callno]) {
09552                ast_mutex_unlock(&iaxsl[fr->callno]);
09553                return 1;
09554             }
09555             break;
09556          case IAX_COMMAND_REGACK:
09557             if (iax2_ack_registry(&ies, &sin, fr->callno)) 
09558                ast_log(LOG_WARNING, "Registration failure\n");
09559             /* Send ack immediately, before we destroy */
09560             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09561             iax2_destroy(fr->callno);
09562             break;
09563          case IAX_COMMAND_REGREJ:
09564             if (iaxs[fr->callno]->reg) {
09565                if (authdebug) {
09566                   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));
09567                   manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>");
09568                }
09569                iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED;
09570             }
09571             /* Send ack immediately, before we destroy */
09572             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09573             iax2_destroy(fr->callno);
09574             break;
09575          case IAX_COMMAND_REGAUTH:
09576             /* Authentication request */
09577             if (registry_rerequest(&ies, fr->callno, &sin)) {
09578                memset(&ied0, 0, sizeof(ied0));
09579                iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found");
09580                iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
09581                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
09582                if (!iaxs[fr->callno]) {
09583                   ast_mutex_unlock(&iaxsl[fr->callno]);
09584                   return 1;
09585                }
09586             }
09587             break;
09588          case IAX_COMMAND_TXREJ:
09589             iaxs[fr->callno]->transferring = 0;
09590             ast_verb(3, "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
09591             memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer));
09592             if (iaxs[fr->callno]->bridgecallno) {
09593                if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
09594                   iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0;
09595                   send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
09596                }
09597             }
09598             break;
09599          case IAX_COMMAND_TXREADY:
09600             if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) ||
09601                 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
09602                if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
09603                   iaxs[fr->callno]->transferring = TRANSFER_MREADY;
09604                else
09605                   iaxs[fr->callno]->transferring = TRANSFER_READY;
09606                ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
09607                if (iaxs[fr->callno]->bridgecallno) {
09608                   if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) ||
09609                       (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
09610                      /* They're both ready, now release them. */
09611                      if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
09612                         ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
09613                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
09614 
09615                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
09616                         iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
09617 
09618                         memset(&ied0, 0, sizeof(ied0));
09619                         memset(&ied1, 0, sizeof(ied1));
09620                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
09621                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
09622                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
09623                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
09624                      } else {
09625                         ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
09626                               iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
09627 
09628                         iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
09629                         iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
09630                         ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
09631                         ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
09632 
09633                         /* Stop doing lag & ping requests */
09634                         stop_stuff(fr->callno);
09635                         stop_stuff(iaxs[fr->callno]->bridgecallno);
09636 
09637                         memset(&ied0, 0, sizeof(ied0));
09638                         memset(&ied1, 0, sizeof(ied1));
09639                         iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
09640                         iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
09641                         send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
09642                         send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
09643                      }
09644 
09645                   }
09646                }
09647             }
09648             break;
09649          case IAX_COMMAND_TXREQ:
09650             try_transfer(iaxs[fr->callno], &ies);
09651             break;
09652          case IAX_COMMAND_TXCNT:
09653             if (iaxs[fr->callno]->transferring)
09654                send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0);
09655             break;
09656          case IAX_COMMAND_TXREL:
09657             /* Send ack immediately, rather than waiting until we've changed addresses */
09658             send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09659             complete_transfer(fr->callno, &ies);
09660             stop_stuff(fr->callno); /* for attended transfer to work with libiax */
09661             break;   
09662          case IAX_COMMAND_TXMEDIA:
09663             if (iaxs[fr->callno]->transferring == TRANSFER_READY) {
09664                AST_LIST_LOCK(&frame_queue);
09665                AST_LIST_TRAVERSE(&frame_queue, cur, list) {
09666                   /* Cancel any outstanding frames and start anew */
09667                   if ((fr->callno == cur->callno) && (cur->transfer))
09668                      cur->retries = -1;
09669                }
09670                AST_LIST_UNLOCK(&frame_queue);
09671                /* Start sending our media to the transfer address, but otherwise leave the call as-is */
09672                iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS;
09673             }
09674             break;   
09675          case IAX_COMMAND_DPREP:
09676             complete_dpreply(iaxs[fr->callno], &ies);
09677             break;
09678          case IAX_COMMAND_UNSUPPORT:
09679             ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown);
09680             break;
09681          case IAX_COMMAND_FWDOWNL:
09682             /* Firmware download */
09683             if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) {
09684                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1);
09685                break;
09686             }
09687             memset(&ied0, 0, sizeof(ied0));
09688             res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc);
09689             if (res < 0)
09690                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
09691             else if (res > 0)
09692                send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
09693             else
09694                send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1);
09695             if (!iaxs[fr->callno]) {
09696                ast_mutex_unlock(&iaxsl[fr->callno]);
09697                return 1;
09698             }
09699             break;
09700          default:
09701             ast_debug(1, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno);
09702             memset(&ied0, 0, sizeof(ied0));
09703             iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass);
09704             send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1);
09705          }
09706          /* Free remote variables (if any) */
09707          if (ies.vars) {
09708             ast_variables_destroy(ies.vars);
09709             ast_debug(1, "I can haz IAX vars, but they is no good :-(\n");
09710             ies.vars = NULL;
09711          }
09712 
09713          /* Don't actually pass these frames along */
09714          if ((f.subclass != IAX_COMMAND_ACK) && 
09715            (f.subclass != IAX_COMMAND_TXCNT) && 
09716            (f.subclass != IAX_COMMAND_TXACC) && 
09717            (f.subclass != IAX_COMMAND_INVAL) &&
09718            (f.subclass != IAX_COMMAND_VNAK)) { 
09719             if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
09720                send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09721          }
09722          ast_mutex_unlock(&iaxsl[fr->callno]);
09723          return 1;
09724       }
09725       /* Unless this is an ACK or INVAL frame, ack it */
09726       if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
09727          send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
09728    } else if (minivid) {
09729       f.frametype = AST_FRAME_VIDEO;
09730       if (iaxs[fr->callno]->videoformat > 0) 
09731          f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0);
09732       else {
09733          ast_log(LOG_WARNING, "Received mini frame before first full video frame\n");
09734          iax2_vnak(fr->callno);
09735          ast_mutex_unlock(&iaxsl[fr->callno]);
09736          return 1;
09737       }
09738       f.datalen = res - sizeof(*vh);
09739       if (f.datalen)
09740          f.data = thread->buf + sizeof(*vh);
09741       else
09742          f.data = NULL;
09743 #ifdef IAXTESTS
09744       if (test_resync) {
09745          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff);
09746       } else
09747 #endif /* IAXTESTS */
09748          fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff);
09749    } else {
09750       /* A mini frame */
09751       f.frametype = AST_FRAME_VOICE;
09752       if (iaxs[fr->callno]->voiceformat > 0)
09753          f.subclass = iaxs[fr->callno]->voiceformat;
09754       else {
09755          ast_debug(1, "Received mini frame before first full voice frame\n");
09756          iax2_vnak(fr->callno);
09757          ast_mutex_unlock(&iaxsl[fr->callno]);
09758          return 1;
09759       }
09760       f.datalen = res - sizeof(struct ast_iax2_mini_hdr);
09761       if (f.datalen < 0) {
09762          ast_log(LOG_WARNING, "Datalen < 0?\n");
09763          ast_mutex_unlock(&iaxsl[fr->callno]);
09764          return 1;
09765       }
09766       if (f.datalen)
09767          f.data = thread->buf + sizeof(*mh);
09768       else
09769          f.data = NULL;
09770 #ifdef IAXTESTS
09771       if (test_resync) {
09772          fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff);
09773       } else
09774 #endif /* IAXTESTS */
09775       fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts);
09776       /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */
09777    }
09778    /* Don't pass any packets until we're started */
09779    if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
09780       ast_mutex_unlock(&iaxsl[fr->callno]);
09781       return 1;
09782    }
09783    /* Common things */
09784    f.src = "IAX2";
09785    f.mallocd = 0;
09786    f.offset = 0;
09787    f.len = 0;
09788    if (f.datalen && (f.frametype == AST_FRAME_VOICE)) {
09789       f.samples = ast_codec_get_samples(&f);
09790       /* We need to byteswap incoming slinear samples from network byte order */
09791       if (f.subclass == AST_FORMAT_SLINEAR)
09792          ast_frame_byteswap_be(&f);
09793    } else
09794       f.samples = 0;
09795    iax_frame_wrap(fr, &f);
09796 
09797    /* If this is our most recent packet, use it as our basis for timestamping */
09798    if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
09799       /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/
09800       fr->outoforder = 0;
09801    } else {
09802       if (iaxdebug && iaxs[fr->callno])
09803          ast_debug(1, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr->ts, iaxs[fr->callno]->last);
09804       fr->outoforder = -1;
09805    }
09806    fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO));
09807    duped_fr = iaxfrdup2(fr);
09808    if (duped_fr) {
09809       schedule_delivery(duped_fr, updatehistory, 0, &fr->ts);
09810    }
09811    if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) {
09812       iaxs[fr->callno]->last = fr->ts;
09813 #if 1
09814       if (iaxdebug)
09815          ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts);
09816 #endif
09817    }
09818 
09819    /* Always run again */
09820    ast_mutex_unlock(&iaxsl[fr->callno]);
09821    return 1;
09822 }

static int socket_process_meta ( int  packet_len,
struct ast_iax2_meta_hdr meta,
struct sockaddr_in *  sin,
int  sockfd,
struct iax_frame fr 
) [static]

Definition at line 8039 of file chan_iax2.c.

References ast_codec_get_samples(), AST_FRAME_VOICE, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_test_flag, ast_tvnow(), ast_tvzero(), iax_frame::callno, ast_iax2_mini_hdr::callno, f, find_callno_locked(), find_tpeer(), fix_peerts(), iax2_vnak(), IAX_FLAG_FULL, iax_frame_wrap(), IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_STATE_STARTED, iaxfrdup2(), ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, ast_iax2_meta_trunk_mini::mini, NEW_PREVENT, iax_frame::outoforder, iax2_trunk_peer::rxtrunktime, schedule_delivery(), iax2_trunk_peer::trunkact, iax_frame::ts, and ast_iax2_mini_hdr::ts.

Referenced by socket_process().

08041 {
08042    unsigned char metatype;
08043    struct ast_iax2_meta_trunk_mini *mtm;
08044    struct ast_iax2_meta_trunk_hdr *mth;
08045    struct ast_iax2_meta_trunk_entry *mte;
08046    struct iax2_trunk_peer *tpeer;
08047    unsigned int ts;
08048    void *ptr;
08049    struct timeval rxtrunktime;
08050    struct ast_frame f = { 0, };
08051 
08052    if (packet_len < sizeof(*meta)) {
08053       ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", 
08054          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
08055       return 1;
08056    }
08057 
08058    if (meta->metacmd != IAX_META_TRUNK)
08059       return 1;
08060 
08061    if (packet_len < (sizeof(*meta) + sizeof(*mth))) {
08062       ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %d min)\n", packet_len,
08063          (int) (sizeof(*meta) + sizeof(*mth)));
08064       return 1;
08065    }
08066    mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
08067    ts = ntohl(mth->ts);
08068    metatype = meta->cmddata;
08069    packet_len -= (sizeof(*meta) + sizeof(*mth));
08070    ptr = mth->data;
08071    tpeer = find_tpeer(sin, sockfd);
08072    if (!tpeer) {
08073       ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", 
08074          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
08075       return 1;
08076    }
08077    tpeer->trunkact = ast_tvnow();
08078    if (!ts || ast_tvzero(tpeer->rxtrunktime))
08079       tpeer->rxtrunktime = tpeer->trunkact;
08080    rxtrunktime = tpeer->rxtrunktime;
08081    ast_mutex_unlock(&tpeer->lock);
08082    while (packet_len >= sizeof(*mte)) {
08083       /* Process channels */
08084       unsigned short callno, trunked_ts, len;
08085 
08086       if (metatype == IAX_META_TRUNK_MINI) {
08087          mtm = (struct ast_iax2_meta_trunk_mini *) ptr;
08088          ptr += sizeof(*mtm);
08089          packet_len -= sizeof(*mtm);
08090          len = ntohs(mtm->len);
08091          callno = ntohs(mtm->mini.callno);
08092          trunked_ts = ntohs(mtm->mini.ts);
08093       } else if (metatype == IAX_META_TRUNK_SUPERMINI) {
08094          mte = (struct ast_iax2_meta_trunk_entry *)ptr;
08095          ptr += sizeof(*mte);
08096          packet_len -= sizeof(*mte);
08097          len = ntohs(mte->len);
08098          callno = ntohs(mte->callno);
08099          trunked_ts = 0;
08100       } else {
08101          ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
08102          break;
08103       }
08104       /* Stop if we don't have enough data */
08105       if (len > packet_len)
08106          break;
08107       fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, sin, NEW_PREVENT, sockfd, 0);
08108       if (!fr->callno)
08109          continue;
08110 
08111       /* If it's a valid call, deliver the contents.  If not, we
08112          drop it, since we don't have a scallno to use for an INVAL */
08113       /* Process as a mini frame */
08114       memset(&f, 0, sizeof(f));
08115       f.frametype = AST_FRAME_VOICE;
08116       if (!iaxs[fr->callno]) {
08117          /* drop it */
08118       } else if (iaxs[fr->callno]->voiceformat == 0) {
08119          ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n");
08120          iax2_vnak(fr->callno);
08121       } else {
08122          f.subclass = iaxs[fr->callno]->voiceformat;
08123          f.datalen = len;
08124          if (f.datalen >= 0) {
08125             if (f.datalen)
08126                f.data = ptr;
08127             else
08128                f.data = NULL;
08129             if (trunked_ts)
08130                fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff);
08131             else
08132                fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts);
08133             /* Don't pass any packets until we're started */
08134             if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
08135                struct iax_frame *duped_fr;
08136 
08137                /* Common things */
08138                f.src = "IAX2";
08139                f.mallocd = 0;
08140                f.offset = 0;
08141                if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 
08142                   f.samples = ast_codec_get_samples(&f);
08143                else
08144                   f.samples = 0;
08145                fr->outoforder = 0;
08146                iax_frame_wrap(fr, &f);
08147                duped_fr = iaxfrdup2(fr);
08148                if (duped_fr)
08149                   schedule_delivery(duped_fr, 1, 1, &fr->ts);
08150                if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts)
08151                   iaxs[fr->callno]->last = fr->ts;
08152             }
08153          } else {
08154             ast_log(LOG_WARNING, "Datalen < 0?\n");
08155          }
08156       }
08157       ast_mutex_unlock(&iaxsl[fr->callno]);
08158       ptr += len;
08159       packet_len -= len;
08160    }
08161 
08162    return 1;
08163 }

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

Definition at line 7961 of file chan_iax2.c.

References ast_copy_string(), ast_debug, 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, ast_iax2_full_hdr::scallno, signal_condition(), iax2_thread::sin, thread, and ast_iax2_full_hdr::type.

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

07962 {
07963    struct iax2_thread *thread;
07964    socklen_t len;
07965    time_t t;
07966    static time_t last_errtime = 0;
07967    struct ast_iax2_full_hdr *fh;
07968 
07969    if (!(thread = find_idle_thread())) {
07970       time(&t);
07971       if (t != last_errtime)
07972          ast_debug(1, "Out of idle IAX2 threads for I/O, pausing!\n");
07973       last_errtime = t;
07974       usleep(1);
07975       return 1;
07976    }
07977 
07978    len = sizeof(thread->iosin);
07979    thread->iofd = fd;
07980    thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len);
07981    thread->buf_size = sizeof(thread->readbuf);
07982    thread->buf = thread->readbuf;
07983    if (thread->buf_len < 0) {
07984       if (errno != ECONNREFUSED && errno != EAGAIN)
07985          ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
07986       handle_error();
07987       thread->iostate = IAX_IOSTATE_IDLE;
07988       signal_condition(&thread->lock, &thread->cond);
07989       return 1;
07990    }
07991    if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
07992       thread->iostate = IAX_IOSTATE_IDLE;
07993       signal_condition(&thread->lock, &thread->cond);
07994       return 1;
07995    }
07996    
07997    /* Determine if this frame is a full frame; if so, and any thread is currently
07998       processing a full frame for the same callno from this peer, then drop this
07999       frame (and the peer will retransmit it) */
08000    fh = (struct ast_iax2_full_hdr *) thread->buf;
08001    if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
08002       struct iax2_thread *cur = NULL;
08003       uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL;
08004       
08005       AST_LIST_LOCK(&active_list);
08006       AST_LIST_TRAVERSE(&active_list, cur, list) {
08007          if ((cur->ffinfo.callno == callno) &&
08008              !inaddrcmp(&cur->ffinfo.sin, &thread->iosin))
08009             break;
08010       }
08011       if (cur) {
08012          /* we found another thread processing a full frame for this call,
08013             so queue it up for processing later. */
08014          defer_full_frame(thread, cur);
08015          AST_LIST_UNLOCK(&active_list);
08016          thread->iostate = IAX_IOSTATE_IDLE;
08017          signal_condition(&thread->lock, &thread->cond);
08018          return 1;
08019       } else {
08020          /* this thread is going to process this frame, so mark it */
08021          thread->ffinfo.callno = callno;
08022          memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin));
08023          thread->ffinfo.type = fh->type;
08024          thread->ffinfo.csub = fh->csub;
08025       }
08026       AST_LIST_UNLOCK(&active_list);
08027    }
08028    
08029    /* Mark as ready and send on its way */
08030    thread->iostate = IAX_IOSTATE_READY;
08031 #ifdef DEBUG_SCHED_MULTITHREAD
08032    ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc));
08033 #endif
08034    signal_condition(&thread->lock, &thread->cond);
08035 
08036    return 1;
08037 }

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

Definition at line 7677 of file chan_iax2.c.

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

Referenced by socket_process().

07678 {
07679    pthread_t newthread;
07680    struct dpreq_data *dpr;
07681    
07682    if (!(dpr = ast_calloc(1, sizeof(*dpr))))
07683       return;
07684 
07685    dpr->callno = callno;
07686    ast_copy_string(dpr->context, context, sizeof(dpr->context));
07687    ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum));
07688    if (callerid)
07689       dpr->callerid = ast_strdup(callerid);
07690    if (ast_pthread_create_detached(&newthread, NULL, dp_lookup_thread, dpr)) {
07691       ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
07692    }
07693 }

static int start_network_thread ( void   )  [static]

Definition at line 10427 of file chan_iax2.c.

References ast_calloc, ast_cond_init(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create_detached, iax2_process_thread(), IAX_THREAD_TYPE_POOL, iaxthreadcount, iax2_thread::list, LOG_WARNING, and thread.

Referenced by load_module().

10428 {
10429    struct iax2_thread *thread;
10430    int threadcount = 0;
10431    int x;
10432    for (x = 0; x < iaxthreadcount; x++) {
10433       thread = ast_calloc(1, sizeof(*thread));
10434       if (thread) {
10435          thread->type = IAX_THREAD_TYPE_POOL;
10436          thread->threadnum = ++threadcount;
10437          ast_mutex_init(&thread->lock);
10438          ast_cond_init(&thread->cond, NULL);
10439          if (ast_pthread_create_detached(&thread->threadid, NULL, iax2_process_thread, thread)) {
10440             ast_log(LOG_WARNING, "Failed to create new thread!\n");
10441             ast_free(thread);
10442             thread = NULL;
10443          }
10444          AST_LIST_LOCK(&idle_list);
10445          AST_LIST_INSERT_TAIL(&idle_list, thread, list);
10446          AST_LIST_UNLOCK(&idle_list);
10447       }
10448    }
10449    ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL);
10450    ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
10451    ast_verb(2, "%d helper threads started\n", threadcount);
10452    return 0;
10453 }

static void stop_stuff ( int  callno  )  [static]

Definition at line 7365 of file chan_iax2.c.

References iax2_destroy_helper().

Referenced by socket_process().

07366 {
07367    iax2_destroy_helper(iaxs[callno]);
07368 }

static void store_by_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1662 of file chan_iax2.c.

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

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

01663 {
01664    if (!pvt->peercallno) {
01665       ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
01666       return;
01667    }
01668 
01669    ao2_link(iax_peercallno_pvts, pvt);
01670 }

static void store_by_transfercallno ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 1643 of file chan_iax2.c.

References ao2_link(), ast_log(), iax_transfercallno_pvts, LOG_ERROR, and chan_iax2_pvt::transfercallno.

Referenced by try_transfer().

01644 {
01645    if (!pvt->transfercallno) {
01646       ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n");
01647       return;
01648    }
01649 
01650    ao2_link(iax_transfercallno_pvts, pvt);
01651 }

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

Definition at line 7551 of file chan_iax2.c.

References iax2_trunk_peer::addr, ast_debug, ast_free, ast_inet_ntoa(), AST_IO_PRI, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_tvnow(), ast_verbose(), iax2_trunk_expired(), iax2_trunk_peer::lock, LOG_WARNING, send_trunk(), totalcalls, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.

Referenced by network_thread().

07552 {
07553    char buf[1024];
07554    int res, processed = 0, totalcalls = 0;
07555    struct iax2_trunk_peer *tpeer = NULL, *drop = NULL;
07556 #ifdef DAHDI_TIMERACK
07557    int x = 1;
07558 #endif
07559    struct timeval now = ast_tvnow();
07560    if (iaxtrunkdebug)
07561       ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", trunkmaxsize);
07562    if (events & AST_IO_PRI) {
07563 #ifdef DAHDI_TIMERACK
07564       /* Great, this is a timing interface, just call the ioctl */
07565       if (ioctl(fd, DAHDI_TIMERACK, &x)) {
07566          ast_log(LOG_WARNING, "Unable to acknowledge DAHDI timer. IAX trunking will fail!\n");
07567          usleep(1);
07568          return -1;
07569       }
07570 #endif      
07571    } else {
07572       /* Read and ignore from the pseudo channel for timing */
07573       res = read(fd, buf, sizeof(buf));
07574       if (res < 1) {
07575          ast_log(LOG_WARNING, "Unable to read from timing fd\n");
07576          return 1;
07577       }
07578    }
07579    /* For each peer that supports trunking... */
07580    AST_LIST_LOCK(&tpeers);
07581    AST_LIST_TRAVERSE_SAFE_BEGIN(&tpeers, tpeer, list) {
07582       processed++;
07583       res = 0;
07584       ast_mutex_lock(&tpeer->lock);
07585       /* We can drop a single tpeer per pass.  That makes all this logic
07586          substantially easier */
07587       if (!drop && iax2_trunk_expired(tpeer, &now)) {
07588          /* Take it out of the list, but don't free it yet, because it
07589             could be in use */
07590          AST_LIST_REMOVE_CURRENT(list);
07591          drop = tpeer;
07592       } else {
07593          res = send_trunk(tpeer, &now);
07594          trunk_timed++; 
07595          if (iaxtrunkdebug)
07596             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);
07597       }     
07598       totalcalls += res;   
07599       res = 0;
07600       ast_mutex_unlock(&tpeer->lock);
07601    }
07602    AST_LIST_TRAVERSE_SAFE_END;
07603    AST_LIST_UNLOCK(&tpeers);
07604 
07605    if (drop) {
07606       ast_mutex_lock(&drop->lock);
07607       /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 
07608          because by the time they could get tpeerlock, we've already grabbed it */
07609       ast_debug(1, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port));
07610       if (drop->trunkdata) {
07611          ast_free(drop->trunkdata);
07612          drop->trunkdata = NULL;
07613       }
07614       ast_mutex_unlock(&drop->lock);
07615       ast_mutex_destroy(&drop->lock);
07616       ast_free(drop);
07617       
07618    }
07619 
07620    if (iaxtrunkdebug)
07621       ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls);
07622    iaxtrunkdebug = 0;
07623 
07624    return 1;
07625 }

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

Definition at line 12387 of file chan_iax2.c.

References CMP_MATCH, CMP_STOP, chan_iax2_pvt::frames_received, and match().

Referenced by load_module().

12388 {
12389    struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
12390 
12391    /* The frames_received field is used to hold whether we're matching
12392     * against a full frame or not ... */
12393 
12394    return match(&pvt2->transfer, pvt2->transfercallno, pvt2->callno, pvt,
12395       pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0;
12396 }

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

Definition at line 12380 of file chan_iax2.c.

References chan_iax2_pvt::transfercallno.

Referenced by load_module().

12381 {
12382    const struct chan_iax2_pvt *pvt = obj;
12383 
12384    return pvt->transfercallno;
12385 }

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

Definition at line 2262 of file chan_iax2.c.

References ast_debug, errno, f, and handle_error().

Referenced by send_trunk().

02263 {
02264    int res;
02265    res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin,
02266                sizeof(*sin));
02267    if (res < 0) {
02268       ast_debug(1, "Received error: %s\n", strerror(errno));
02269       handle_error();
02270    } else
02271       res = 0;
02272    return res;
02273 }

static int try_firmware ( char *  s  )  [static]

Definition at line 1964 of file chan_iax2.c.

References ast_calloc, AST_FILE_MODE, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, 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, iax2_trunk_peer::list, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), and ast_iax2_firmware_header::version.

Referenced by reload_firmware().

01965 {
01966    struct stat stbuf;
01967    struct iax_firmware *cur = NULL;
01968    int ifd, fd, res, len, chunk;
01969    struct ast_iax2_firmware_header *fwh, fwh2;
01970    struct MD5Context md5;
01971    unsigned char sum[16], buf[1024];
01972    char *s2, *last;
01973 
01974    if (!(s2 = alloca(strlen(s) + 100))) {
01975       ast_log(LOG_WARNING, "Alloca failed!\n");
01976       return -1;
01977    }
01978 
01979    last = strrchr(s, '/');
01980    if (last)
01981       last++;
01982    else
01983       last = s;
01984 
01985    snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
01986 
01987    if ((res = stat(s, &stbuf) < 0)) {
01988       ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
01989       return -1;
01990    }
01991 
01992    /* Make sure it's not a directory */
01993    if (S_ISDIR(stbuf.st_mode))
01994       return -1;
01995    ifd = open(s, O_RDONLY);
01996    if (ifd < 0) {
01997       ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno));
01998       return -1;
01999    }
02000    fd = open(s2, O_RDWR | O_CREAT | O_EXCL, AST_FILE_MODE);
02001    if (fd < 0) {
02002       ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno));
02003       close(ifd);
02004       return -1;
02005    }
02006    /* Unlink our newly created file */
02007    unlink(s2);
02008    
02009    /* Now copy the firmware into it */
02010    len = stbuf.st_size;
02011    while(len) {
02012       chunk = len;
02013       if (chunk > sizeof(buf))
02014          chunk = sizeof(buf);
02015       res = read(ifd, buf, chunk);
02016       if (res != chunk) {
02017          ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
02018          close(ifd);
02019          close(fd);
02020          return -1;
02021       }
02022       res = write(fd, buf, chunk);
02023       if (res != chunk) {
02024          ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
02025          close(ifd);
02026          close(fd);
02027          return -1;
02028       }
02029       len -= chunk;
02030    }
02031    close(ifd);
02032    /* Return to the beginning */
02033    lseek(fd, 0, SEEK_SET);
02034    if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) {
02035       ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s);
02036       close(fd);
02037       return -1;
02038    }
02039    if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) {
02040       ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s);
02041       close(fd);
02042       return -1;
02043    }
02044    if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) {
02045       ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s);
02046       close(fd);
02047       return -1;
02048    }
02049    if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) {
02050       ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s);
02051       close(fd);
02052       return -1;
02053    }
02054    fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 
02055    if (fwh == MAP_FAILED) {
02056       ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno));
02057       close(fd);
02058       return -1;
02059    }
02060    MD5Init(&md5);
02061    MD5Update(&md5, fwh->data, ntohl(fwh->datalen));
02062    MD5Final(sum, &md5);
02063    if (memcmp(sum, fwh->chksum, sizeof(sum))) {
02064       ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s);
02065       munmap((void*)fwh, stbuf.st_size);
02066       close(fd);
02067       return -1;
02068    }
02069 
02070    AST_LIST_TRAVERSE(&firmwares, cur, list) {
02071       if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
02072          /* Found a candidate */
02073          if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
02074             /* The version we have on loaded is older, load this one instead */
02075             break;
02076          /* This version is no newer than what we have.  Don't worry about it.
02077             We'll consider it a proper load anyhow though */
02078          munmap((void*)fwh, stbuf.st_size);
02079          close(fd);
02080          return 0;
02081       }
02082    }
02083    
02084    if (!cur && ((cur = ast_calloc(1, sizeof(*cur))))) {
02085       cur->fd = -1;
02086       AST_LIST_INSERT_TAIL(&firmwares, cur, list);
02087    }
02088    
02089    if (cur) {
02090       if (cur->fwh)
02091          munmap((void*)cur->fwh, cur->mmaplen);
02092       if (cur->fd > -1)
02093          close(cur->fd);
02094       cur->fwh = fwh;
02095       cur->fd = fd;
02096       cur->mmaplen = stbuf.st_size;
02097       cur->dead = 0;
02098    }
02099    
02100    return 0;
02101 }

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

Definition at line 6733 of file chan_iax2.c.

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

Referenced by socket_process().

06734 {
06735    int newcall = 0;
06736    char newip[256];
06737    struct iax_ie_data ied;
06738    struct sockaddr_in new;
06739    
06740    
06741    memset(&ied, 0, sizeof(ied));
06742    if (ies->apparent_addr)
06743       memmove(&new, ies->apparent_addr, sizeof(new));
06744    if (ies->callno)
06745       newcall = ies->callno;
06746    if (!newcall || !new.sin_addr.s_addr || !new.sin_port) {
06747       ast_log(LOG_WARNING, "Invalid transfer request\n");
06748       return -1;
06749    }
06750    pvt->transfercallno = newcall;
06751    memcpy(&pvt->transfer, &new, sizeof(pvt->transfer));
06752    inet_aton(newip, &pvt->transfer.sin_addr);
06753    pvt->transfer.sin_family = AF_INET;
06754    pvt->transferring = TRANSFER_BEGIN;
06755    pvt->transferid = ies->transferid;
06756    store_by_transfercallno(pvt);
06757    if (ies->transferid)
06758       iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
06759    send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
06760    return 0;
06761 }

static int uncompress_subclass ( unsigned char  csub  )  [static]

Definition at line 1263 of file chan_iax2.c.

References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.

Referenced by decode_frame(), and socket_process().

01264 {
01265    /* If the SC_LOG flag is set, return 2^csub otherwise csub */
01266    if (csub & IAX_FLAG_SC_LOG) {
01267       /* special case for 'compressed' -1 */
01268       if (csub == 0xff)
01269          return -1;
01270       else
01271          return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT);
01272    }
01273    else
01274       return csub;
01275 }

static void unlink_peer ( struct iax2_peer peer  )  [static]

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

07014 {
07015    if (peer->expire > -1) {
07016       if (!ast_sched_del(sched, peer->expire)) {
07017          peer->expire = -1;
07018          peer_unref(peer);
07019       }
07020    }
07021 
07022    if (peer->pokeexpire > -1) {
07023       if (!ast_sched_del(sched, peer->pokeexpire)) {
07024          peer->pokeexpire = -1;
07025          peer_unref(peer);
07026       }
07027    }
07028 
07029    ao2_unlink(peers, peer);
07030 }

static int unload_module ( void   )  [static]

Definition at line 12345 of file chan_iax2.c.

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

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

Definition at line 3983 of file chan_iax2.c.

References ast_mutex_unlock().

Referenced by iax2_bridge().

03984 {
03985    ast_mutex_unlock(&iaxsl[callno1]);
03986    ast_mutex_unlock(&iaxsl[callno0]);
03987 }

static void unwrap_timestamp ( struct iax_frame fr  )  [static]

Definition at line 2928 of file chan_iax2.c.

References iax_frame::af, ast_debug, AST_FRAME_VIDEO, iax_frame::callno, ast_frame::frametype, and iax_frame::ts.

Referenced by schedule_delivery().

02929 {
02930    /* Video mini frames only encode the lower 15 bits of the session
02931     * timestamp, but other frame types (e.g. audio) encode 16 bits. */
02932    const int ts_shift = (fr->af.frametype == AST_FRAME_VIDEO) ? 15 : 16;
02933    const int lower_mask = (1 << ts_shift) - 1;
02934    const int upper_mask = ~lower_mask;
02935    const int last_upper = iaxs[fr->callno]->last & upper_mask;
02936 
02937    if ( (fr->ts & upper_mask) == last_upper ) {
02938       const int x = fr->ts - iaxs[fr->callno]->last;
02939       const int threshold = (ts_shift == 15) ? 25000 : 50000;
02940 
02941       if (x < -threshold) {
02942          /* Sudden big jump backwards in timestamp:
02943             What likely happened here is that miniframe timestamp has circled but we haven't
02944             gotten the update from the main packet.  We'll just pretend that we did, and
02945             update the timestamp appropriately. */
02946          fr->ts = (last_upper + (1 << ts_shift)) | (fr->ts & lower_mask);
02947          if (iaxdebug)
02948             ast_debug(1, "schedule_delivery: pushed forward timestamp\n");
02949       } else if (x > threshold) {
02950          /* Sudden apparent big jump forwards in timestamp:
02951             What's likely happened is this is an old miniframe belonging to the previous
02952             top 15 or 16-bit timestamp that has turned up out of order.
02953             Adjust the timestamp appropriately. */
02954          fr->ts = (last_upper - (1 << ts_shift)) | (fr->ts & lower_mask);
02955          if (iaxdebug)
02956             ast_debug(1, "schedule_delivery: pushed back timestamp\n");
02957       }
02958    }
02959 }

static void update_jbsched ( struct chan_iax2_pvt pvt  )  [static]

Definition at line 2963 of file chan_iax2.c.

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

Referenced by __get_from_jb(), and schedule_delivery().

02964 {
02965    int when;
02966    
02967    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
02968    
02969    when = jb_next(pvt->jb) - when;
02970 
02971    if (when <= 0) {
02972       /* XXX should really just empty until when > 0.. */
02973       when = 1;
02974    }
02975    
02976    pvt->jbid = iax2_sched_replace(pvt->jbid, sched, when, get_from_jb, 
02977       CALLNO_TO_PTR(pvt->callno));
02978 }

static void update_max_nontrunk ( void   )  [static]

Definition at line 1579 of file chan_iax2.c.

References ast_debug, and TRUNK_CALL_START.

Referenced by __find_callno(), and make_trunk().

01580 {
01581    int max = 1;
01582    int x;
01583    /* XXX Prolly don't need locks here XXX */
01584    for (x=1;x<TRUNK_CALL_START - 1; x++) {
01585       if (iaxs[x])
01586          max = x + 1;
01587    }
01588    maxnontrunkcall = max;
01589    if (iaxdebug)
01590       ast_debug(1, "New max nontrunk callno is %d\n", max);
01591 }

static void update_max_trunk ( void   )  [static]

Definition at line 1562 of file chan_iax2.c.

References ARRAY_LEN, ast_debug, and TRUNK_CALL_START.

Referenced by iax2_destroy(), and make_trunk().

01563 {
01564    int max = TRUNK_CALL_START;
01565    int x;
01566 
01567    /* XXX Prolly don't need locks here XXX */
01568    for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
01569       if (iaxs[x]) {
01570          max = x + 1;
01571       }
01572    }
01573 
01574    maxtrunkcall = max;
01575    if (iaxdebug)
01576       ast_debug(1, "New max trunk callno is %d\n", max);
01577 }

static int update_packet ( struct iax_frame f  )  [static]

Definition at line 2392 of file chan_iax2.c.

References build_rand_pad(), ast_iax2_full_hdr::dcallno, decode_frame(), encrypt_frame(), f, IAX_FLAG_RETRANS, and ast_iax2_full_hdr::iseqno.

Referenced by __attempt_transmit().

02393 {
02394    /* Called with iaxsl lock held, and iaxs[callno] non-NULL */
02395    struct ast_iax2_full_hdr *fh = f->data;
02396    struct ast_frame af;
02397 
02398    /* if frame is encrypted. decrypt before updating it. */
02399    if (f->encmethods) {
02400       decode_frame(&f->mydcx, fh, &af, &f->datalen);
02401    }
02402    /* Mark this as a retransmission */
02403    fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno);
02404    /* Update iseqno */
02405    f->iseqno = iaxs[f->callno]->iseqno;
02406    fh->iseqno = f->iseqno;
02407 
02408    /* Now re-encrypt the frame */
02409    if (f->encmethods) {
02410    /* since this is a retransmit frame, create a new random padding
02411     * before re-encrypting. */
02412       build_rand_pad(f->semirand, sizeof(f->semirand));
02413       encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen);
02414    }
02415    return 0;
02416 }

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

References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), ast_device_state_changed(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, 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_verb, 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, inaddrcmp(), LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mailbox, manager_event, iax2_peer::name, peer_ref(), peer_unref(), realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, strsep(), version, and iax2_peer::zonetag.

Referenced by socket_process().

07123 {
07124    /* Called from IAX thread only, with proper iaxsl lock */
07125    struct iax_ie_data ied;
07126    struct iax2_peer *p;
07127    int msgcount;
07128    char data[80];
07129    int version;
07130    const char *peer_name;
07131    int res = -1;
07132 
07133    memset(&ied, 0, sizeof(ied));
07134 
07135    peer_name = ast_strdupa(iaxs[callno]->peer);
07136 
07137    /* SLD: Another find_peer call during registration - this time when we are really updating our registration */
07138    ast_mutex_unlock(&iaxsl[callno]);
07139    if (!(p = find_peer(peer_name, 1))) {
07140       ast_mutex_lock(&iaxsl[callno]);
07141       ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
07142       return -1;
07143    }
07144    ast_mutex_lock(&iaxsl[callno]);
07145    if (!iaxs[callno])
07146       goto return_unref;
07147 
07148    if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) {
07149       if (sin->sin_addr.s_addr) {
07150          time_t nowtime;
07151          time(&nowtime);
07152          realtime_update_peer(peer_name, sin, nowtime);
07153       } else {
07154          realtime_update_peer(peer_name, sin, 0);
07155       }
07156    }
07157    if (inaddrcmp(&p->addr, sin)) {
07158       if (iax2_regfunk)
07159          iax2_regfunk(p->name, 1);
07160       /* Stash the IP address from which they registered */
07161       memcpy(&p->addr, sin, sizeof(p->addr));
07162       snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry);
07163       if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) {
07164          ast_db_put("IAX/Registry", p->name, data);
07165          ast_verb(3, "Registered IAX2 '%s' (%s) at %s:%d\n", p->name,
07166                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
07167          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name);
07168          register_peer_exten(p, 1);
07169          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
07170       } else if (!ast_test_flag(p, IAX_TEMPONLY)) {
07171          ast_verb(3, "Unregistered IAX2 '%s' (%s)\n", p->name,
07172                    ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
07173          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
07174          register_peer_exten(p, 0);
07175          ast_db_del("IAX/Registry", p->name);
07176          ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
07177       }
07178       /* Update the host */
07179       /* Verify that the host is really there */
07180       iax2_poke_peer(p, callno);
07181    }     
07182 
07183    /* Make sure our call still exists, an INVAL at the right point may make it go away */
07184    if (!iaxs[callno]) {
07185       res = -1;
07186       goto return_unref;
07187    }
07188 
07189    /* Store socket fd */
07190    p->sockfd = fd;
07191    /* Setup the expiry */
07192    if (p->expire > -1) {
07193       if (!ast_sched_del(sched, p->expire)) {
07194          p->expire = -1;
07195          peer_unref(p);
07196       }
07197    }
07198    /* treat an unspecified refresh interval as the minimum */
07199    if (!refresh)
07200       refresh = min_reg_expire;
07201    if (refresh > max_reg_expire) {
07202       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
07203          p->name, max_reg_expire, refresh);
07204       p->expiry = max_reg_expire;
07205    } else if (refresh < min_reg_expire) {
07206       ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n",
07207          p->name, min_reg_expire, refresh);
07208       p->expiry = min_reg_expire;
07209    } else {
07210       p->expiry = refresh;
07211    }
07212    if (p->expiry && sin->sin_addr.s_addr) {
07213       p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p));
07214       if (p->expire == -1)
07215          peer_unref(p);
07216    }
07217    iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
07218    iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
07219    if (sin->sin_addr.s_addr) {
07220       iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry);
07221       iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
07222       if (!ast_strlen_zero(p->mailbox)) {
07223          struct ast_event *event;
07224          int new, old;
07225          char *mailbox, *context;
07226 
07227          context = mailbox = ast_strdupa(p->mailbox);
07228          strsep(&context, "@");
07229          if (ast_strlen_zero(context))
07230             context = "default";
07231 
07232          event = ast_event_get_cached(AST_EVENT_MWI,
07233             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
07234             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
07235             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
07236             AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
07237             AST_EVENT_IE_END);
07238          if (event) {
07239             new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
07240             old = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS);
07241             ast_event_destroy(event);
07242          } else /* Fall back on checking the mailbox directly */
07243             ast_app_inboxcount(p->mailbox, &new, &old);
07244 
07245          if (new > 255)
07246             new = 255;
07247          if (old > 255)
07248             old = 255;
07249          msgcount = (old << 8) | new;
07250 
07251          iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
07252       }
07253       if (ast_test_flag(p, IAX_HASCALLERID)) {
07254          iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num);
07255          iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name);
07256       }
07257    }
07258    version = iax_check_version(devtype);
07259    if (version) 
07260       iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version);
07261 
07262    res = 0;
07263 
07264 return_unref:
07265    peer_unref(p);
07266 
07267    return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
07268 }

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

References CMP_MATCH, and user.

Referenced by load_module().

01311 {
01312    struct iax2_user *user = obj, *user2 = arg;
01313 
01314    return !strcmp(user->name, user2->name) ? CMP_MATCH : 0;
01315 }

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

Definition at line 11068 of file chan_iax2.c.

References ast_set_flag, IAX_DELME, and user.

Referenced by delete_users().

11069 {
11070    struct iax2_user *user = obj;
11071 
11072    ast_set_flag(user, IAX_DELME);
11073 
11074    return 0;
11075 }

static void user_destructor ( void *  obj  )  [static]

Definition at line 10833 of file chan_iax2.c.

References ast_free_ha(), ast_string_field_free_memory, ast_variables_destroy(), free_context(), and user.

Referenced by build_user().

10834 {
10835    struct iax2_user *user = obj;
10836 
10837    ast_free_ha(user->ha);
10838    free_context(user->contexts);
10839    if(user->vars) {
10840       ast_variables_destroy(user->vars);
10841       user->vars = NULL;
10842    }
10843    ast_string_field_free_memory(user);
10844 }

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

References ast_str_hash(), and user.

Referenced by load_module().

01301 {
01302    const struct iax2_user *user = obj;
01303 
01304    return ast_str_hash(user->name);
01305 }

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

Definition at line 1357 of file chan_iax2.c.

References ao2_ref(), and user.

01358 {
01359    ao2_ref(user, +1);
01360    return user;
01361 }

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

Definition at line 1363 of file chan_iax2.c.

References ao2_ref(), and user.

Referenced by authenticate_request(), authenticate_verify(), build_user(), check_access(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_users(), iax2_destroy_helper(), prune_users(), and set_config().

01364 {
01365    ao2_ref(user, -1);
01366    return NULL;
01367 }

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

Definition at line 7466 of file chan_iax2.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, f, iax_frame::list, and send_packet().

Referenced by socket_process().

07467 {
07468    struct iax_frame *f;
07469 
07470    AST_LIST_LOCK(&frame_queue);
07471    AST_LIST_TRAVERSE(&frame_queue, f, list) {
07472       /* Send a copy immediately */
07473       if ((f->callno == callno) && iaxs[f->callno] &&
07474          ((unsigned char ) (f->oseqno - last) < 128) &&
07475          (f->retries >= 0)) {
07476          send_packet(f);
07477       }
07478    }
07479    AST_LIST_UNLOCK(&frame_queue);
07480 }

static int wait_for_peercallno ( struct chan_iax2_pvt pvt  )  [static]

Note:
expects the pvt to be locked

Definition at line 3881 of file chan_iax2.c.

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

Referenced by iax2_indicate(), and iax2_setoption().

03882 {
03883    unsigned short callno = pvt->callno;
03884 
03885    if (!pvt->peercallno) {
03886       /* We don't know the remote side's call number, yet.  :( */
03887       int count = 10;
03888       while (count-- && pvt && !pvt->peercallno) {
03889          DEADLOCK_AVOIDANCE(&iaxsl[callno]);
03890          pvt = iaxs[callno];
03891       }
03892       if (!pvt->peercallno) {
03893          return -1;
03894       }
03895    }
03896 
03897    return 0;
03898 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 12524 of file chan_iax2.c.

char accountcode[AST_MAX_ACCOUNT_CODE] [static]

Definition at line 227 of file chan_iax2.c.

Referenced by __ast_channel_alloc_ap(), __oh323_new(), ast_call_forward(), ast_cdr_setaccount(), begin_dial_channel(), build_device(), build_gateway(), dahdi_new(), dial_exec_full(), do_forward(), features_call(), gtalk_new(), jingle_new(), local_call(), mgcp_new(), rpt_call(), skinny_new(), and tds_log().

int adsi = 0 [static]

Definition at line 231 of file chan_iax2.c.

Referenced by build_gateway().

int amaflags = 0 [static]

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

int authdebug = 1 [static]

Definition at line 161 of file chan_iax2.c.

int autokill = 0 [static]

Definition at line 162 of file chan_iax2.c.

struct ast_cli_entry cli_iax2[] [static]

Definition at line 12237 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry cli_iax2_set_debug_deprecated = { .handler = handle_cli_iax2_set_debug_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } [static]

Definition at line 12233 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_set_debug_jb_deprecated = { .handler = handle_cli_iax2_set_debug_jb_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } [static]

Definition at line 12235 of file chan_iax2.c.

struct ast_cli_entry cli_iax2_set_debug_trunk_deprecated = { .handler = handle_cli_iax2_set_debug_trunk_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } [static]

Definition at line 12234 of file chan_iax2.c.

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

Definition at line 142 of file chan_iax2.c.

unsigned int cos = 0 [static]

Definition at line 172 of file chan_iax2.c.

int defaultsockfd = -1 [static]

Definition at line 183 of file chan_iax2.c.

int delayreject = 0 [static]

Definition at line 232 of file chan_iax2.c.

int global_max_trunk_mtu [static]

Maximum MTU, 0 if not used

Definition at line 138 of file chan_iax2.c.

int global_rtautoclear = 120 [static]

Definition at line 285 of file chan_iax2.c.

struct ast_flags globalflags = { 0 } [static]

Definition at line 235 of file chan_iax2.c.

Referenced by __expire_registry(), __find_callno(), aji_create_client(), aji_load_config(), apply_general_options(), build_peer(), build_user(), find_or_create(), find_user(), find_user_realtime(), forward_message(), handle_minivm_show_settings(), 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 213 of file chan_iax2.c.

int iax2_encryption = 0 [static]

Definition at line 233 of file chan_iax2.c.

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

Definition at line 185 of file chan_iax2.c.

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

struct ast_switch iax2_switch [static]

Definition at line 12119 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

struct ast_channel_tech iax2_tech [static]

Definition at line 952 of file chan_iax2.c.

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

struct ast_datastore_info iax2_variable_datastore_info [static]

Initial value:

 {
   .type = "IAX2_VARIABLE",
   .duplicate = iax2_dup_variable_datastore,
   .destroy = iax2_free_variable_datastore,
}

Definition at line 997 of file chan_iax2.c.

Referenced by acf_iaxvar_read(), acf_iaxvar_write(), ast_iax2_new(), authenticate_reply(), iax2_call(), and socket_process().

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

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

struct ao2_container* iax_transfercallno_pvts [static]

Another container of iax2_pvt structures.

*

Active IAX2 pvt stucts used during transfering a call are stored here.

Definition at line 900 of file chan_iax2.c.

Referenced by __find_callno(), __unload_module(), load_module(), remove_by_transfercallno(), and store_by_transfercallno().

int iaxactivethreadcount = 0 [static]

Definition at line 464 of file chan_iax2.c.

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

int iaxcompat = 0 [static]

Definition at line 163 of file chan_iax2.c.

int iaxdebug = 0 [static]

Definition at line 215 of file chan_iax2.c.

int iaxdefaultdpcache = 10 * 60 [static]

Definition at line 166 of file chan_iax2.c.

int iaxdefaulttimeout = 5 [static]

Definition at line 168 of file chan_iax2.c.

int iaxdynamicthreadcount = 0 [static]

Definition at line 462 of file chan_iax2.c.

Referenced by find_idle_thread(), and iax2_process_thread().

int iaxdynamicthreadnum = 0 [static]

Definition at line 463 of file chan_iax2.c.

Referenced by find_idle_thread().

int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static]

Definition at line 461 of file chan_iax2.c.

Referenced by find_idle_thread(), and set_config().

struct ast_custom_function iaxpeer_function

Definition at line 12002 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static]

an array of iax2 pvt structures

The container for active chan_iax2_pvt structures is implemented as an array for extremely quick direct access to the correct pvt structure based on the local call number. The local call number is used as the index into the array where the associated pvt structure is stored.

Definition at line 852 of file chan_iax2.c.

ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static]

chan_iax2_pvt structure locks

These locks are used when accessing a pvt structure in the iaxs array. The index used here is the same as used in the iaxs array. It is the local call number for the associated pvt struct.

Definition at line 872 of file chan_iax2.c.

int iaxthreadcount = DEFAULT_THREAD_COUNT [static]

Definition at line 460 of file chan_iax2.c.

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

int iaxtrunkdebug = 0 [static]

Definition at line 217 of file chan_iax2.c.

struct ast_custom_function iaxvar_function [static]

Definition at line 8231 of file chan_iax2.c.

Referenced by load_module(), and unload_module().

struct io_context* io [static]

Definition at line 210 of file chan_iax2.c.

int jittertargetextra = 40 [static]

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

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

The last time a call number was used.

It is important to know the last time that a call number was used locally so that it is not used again too soon. The reason for this is the same as the reason that the TCP protocol state machine requires a "TIME WAIT" state.

For example, say that a call is up. Then, the remote side sends a HANGUP, which we respond to with an ACK. However, there is no way to know whether the ACK made it there successfully. If it were to get lost, the remote side may retransmit the HANGUP. If in the meantime, this call number has been reused locally, given the right set of circumstances, this retransmitted HANGUP could potentially improperly hang up the new session. So, to avoid this potential issue, we must wait a specified timeout period before reusing a local call number.

The specified time that we must wait before reusing a local call number is defined as MIN_REUSE_TIME, with a default of 60 seconds.

Definition at line 893 of file chan_iax2.c.

int max_reg_expire [static]

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

int maxtrunkcall = TRUNK_CALL_START [static]

Definition at line 906 of file chan_iax2.c.

int min_reg_expire [static]

Definition at line 174 of file chan_iax2.c.

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 228 of file chan_iax2.c.

char mohsuggest[MAX_MUSICCLASS] [static]

Definition at line 229 of file chan_iax2.c.

Referenced by build_device().

struct ast_netsock_list* netsock [static]

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

struct ast_netsock_list* outsock [static]

used if sourceaddress specified and bindaddr == INADDR_ANY

Definition at line 182 of file chan_iax2.c.

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

char* papp = "IAX2Provision" [static]

Definition at line 10061 of file chan_iax2.c.

Referenced by __unload_module(), and load_module().

char* pdescrip [static]

Initial value:

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

Definition at line 10063 of file chan_iax2.c.

Referenced by load_module().

struct ao2_container* peers [static]

Definition at line 677 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 129 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(), jingle_create_member(), jingle_load_config(), new_iax(), set_config(), set_local_capabilities(), and set_peer_capabilities().

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

Definition at line 10062 of file chan_iax2.c.

Referenced by load_module().

char regcontext[AST_MAX_CONTEXT] = "" [static]

Definition at line 145 of file chan_iax2.c.

Referenced by handle_skinny_show_settings(), register_exten(), reload_config(), and unregister_exten().

int resyncthreshold = 1000 [static]

Definition at line 152 of file chan_iax2.c.

struct sched_context* sched [static]

Definition at line 211 of file chan_iax2.c.

ast_cond_t sched_cond [static]

Definition at line 240 of file chan_iax2.c.

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

Definition at line 239 of file chan_iax2.c.

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

pthread_t schedthreadid = AST_PTHREADT_NULL [static]

Definition at line 238 of file chan_iax2.c.

int srvlookup = 0 [static]

Definition at line 177 of file chan_iax2.c.

Referenced by build_peer().

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

Definition at line 131 of file chan_iax2.c.

int test_losspct = 0 [static]

Definition at line 219 of file chan_iax2.c.

int timingfd = -1 [static]

Definition at line 179 of file chan_iax2.c.

unsigned int tos = 0 [static]

Definition at line 170 of file chan_iax2.c.

int trunk_maxmtu [static]

Definition at line 139 of file chan_iax2.c.

int trunk_nmaxmtu [static]

Trunk MTU statistics

Definition at line 139 of file chan_iax2.c.

int trunk_timed [static]

Definition at line 139 of file chan_iax2.c.

int trunk_untimed [static]

Definition at line 139 of file chan_iax2.c.

int trunkfreq = 20 [static]

Definition at line 158 of file chan_iax2.c.

int trunkmaxsize = MAX_TRUNKDATA [static]

Definition at line 159 of file chan_iax2.c.

struct ao2_container* users [static]

Definition at line 680 of file chan_iax2.c.


Generated on Thu Jul 9 13:41:00 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7