#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/md5.h"
#include "asterisk/cdr.h"
#include "asterisk/crypto.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/app.h"
#include "asterisk/astdb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/localtime.h"
#include "asterisk/aes.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/netsock.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/astobj2.h"
#include "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
#include "jitterbuf.h"
Go to the source code of this file.
Data Structures | |
struct | ast_firmware_list |
struct | ast_iax2_queue |
struct | chan_iax2_pvt |
struct | create_addr_info |
struct | dpreq_data |
struct | iax2_context |
struct | iax2_dpcache |
struct | iax2_peer |
struct | iax2_pkt_buf |
struct | iax2_registry |
struct | iax2_thread |
struct | iax2_trunk_peer |
struct | iax2_user |
struct | iax_dual |
struct | iax_firmware |
struct | iax_rr |
struct | parsed_dial_string |
Defines | |
#define | CACHE_FLAG_CANEXIST (1 << 2) |
#define | CACHE_FLAG_EXISTS (1 << 0) |
#define | CACHE_FLAG_MATCHMORE (1 << 7) |
#define | CACHE_FLAG_NONEXISTENT (1 << 1) |
#define | CACHE_FLAG_PENDING (1 << 3) |
#define | CACHE_FLAG_TIMEOUT (1 << 4) |
#define | CACHE_FLAG_TRANSMITTED (1 << 5) |
#define | CACHE_FLAG_UNKNOWN (1 << 6) |
#define | CALLNO_TO_PTR(a) ((void *)(unsigned long)(a)) |
#define | DEBUG_SCHED_MULTITHREAD |
#define | DEBUG_SUPPORT |
#define | DEFAULT_DROP 3 |
#define | DEFAULT_FREQ_NOTOK 10 * 1000 |
#define | DEFAULT_FREQ_OK 60 * 1000 |
#define | DEFAULT_MAX_THREAD_COUNT 100 |
#define | DEFAULT_MAXMS 2000 |
#define | DEFAULT_RETRY_TIME 1000 |
#define | DEFAULT_THREAD_COUNT 10 |
#define | DEFAULT_TRUNKDATA 640 * 10 |
#define | FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" |
#define | FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
#define | FORMAT "%-15.15s %-15d %-15d\n" |
#define | FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
#define | FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
#define | FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" |
#define | FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
#define | FORMAT2 "%-15.15s %-15.15s %-15.15s\n" |
#define | FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
#define | FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
#define | FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
#define | GAMMA (0.01) |
#define | IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
#define | IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF |
#define | IAX_CAPABILITY_LOWBANDWIDTH |
#define | IAX_CAPABILITY_LOWFREE |
#define | IAX_CAPABILITY_MEDBANDWIDTH |
#define | IAX_IOSTATE_IDLE 0 |
#define | IAX_IOSTATE_PROCESSING 2 |
#define | IAX_IOSTATE_READY 1 |
#define | IAX_IOSTATE_SCHEDREADY 3 |
#define | IAX_TYPE_DYNAMIC 2 |
#define | IAX_TYPE_POOL 1 |
#define | IPTOS_MINCOST 0x02 |
#define | MAX_JITTER_BUFFER 50 |
#define | MAX_PEER_BUCKETS 1 |
#define | MAX_RETRY_TIME 10000 |
#define | MAX_TIMESTAMP_SKEW 160 |
#define | MAX_TRUNKDATA 640 * 200 |
#define | MAX_USER_BUCKETS MAX_PEER_BUCKETS |
#define | MEMORY_SIZE 100 |
#define | MIN_JITTER_BUFFER 10 |
#define | MIN_RETRY_TIME 100 |
#define | MIN_REUSE_TIME 60 |
#define | NEW_ALLOW 1 |
#define | NEW_FORCE 2 |
#define | NEW_PREVENT 0 |
#define | PTR_TO_CALLNO(a) ((unsigned short)(unsigned long)(a)) |
#define | SCHED_MULTITHREADED |
#define | schedule_action(func, data) __schedule_action(func, data, __PRETTY_FUNCTION__) |
#define | TRUNK_CALL_START ARRAY_LEN(iaxs) / 2 |
#define | TS_GAP_FOR_JB_RESYNC 5000 |
Enumerations | |
enum | { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2), IAX_STATE_UNCHANGED = (1 << 3) } |
enum | { IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3), IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7), IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12), IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16), IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20), IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24), IAX_DELAYPBXSTART = (1 << 25), IAX_ALLOWFWDOWNLOAD = (1 << 26) } |
enum | iax_reg_state { REG_STATE_UNREGISTERED = 0, REG_STATE_REGSENT, REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_TIMEOUT, REG_STATE_NOAUTH } |
enum | iax_transfer_state { TRANSFER_NONE = 0, TRANSFER_BEGIN, TRANSFER_READY, TRANSFER_RELEASED, TRANSFER_PASSTHROUGH, TRANSFER_MBEGIN, TRANSFER_MREADY, TRANSFER_MRELEASED, TRANSFER_MPASSTHROUGH, TRANSFER_MEDIA, TRANSFER_MEDIAPASS } |
Functions | |
static void | __attempt_transmit (const void *data) |
static void | __auth_reject (const void *nothing) |
static void | __auto_congest (const void *nothing) |
static void | __auto_hangup (const void *nothing) |
static int | __do_deliver (void *data) |
static void | __expire_registry (const void *data) |
static int | __find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int return_locked, int check_dcallno) |
static void | __get_from_jb (const void *p) |
static void | __iax2_do_register_s (const void *data) |
static void | __iax2_poke_noanswer (const void *data) |
static void | __iax2_poke_peer_s (const void *data) |
static int | __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[]) |
static int | __schedule_action (void(*func)(const void *data), const void *data, const char *funcname) |
static int | __send_command (struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const unsigned char *data, int datalen, int seqno, int now, int transfer, int final) |
static void | __send_lagrq (const void *data) |
static void | __send_ping (const void *data) |
static int | __unload_module (void) |
static int | apply_context (struct iax2_context *con, const char *context) |
static int | ast_cli_netstats (struct mansession *s, int fd, int limit_fmt) |
static struct ast_channel * | ast_iax2_new (int callno, int state, int capability) |
Create new call, interface with the PBX core. | |
static | AST_LIST_HEAD_STATIC (dynamic_list, iax2_thread) |
static | AST_LIST_HEAD_STATIC (active_list, iax2_thread) |
static | AST_LIST_HEAD_STATIC (idle_list, iax2_thread) |
static | AST_LIST_HEAD_STATIC (registrations, iax2_registry) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Inter Asterisk eXchange (Ver 2)",.load=load_module,.unload=unload_module,.reload=reload,) | |
AST_MUTEX_DEFINE_STATIC (dpcache_lock) | |
AST_MUTEX_DEFINE_STATIC (tpeerlock) | |
AST_MUTEX_DEFINE_STATIC (sched_lock) | |
static int | attempt_transmit (const void *data) |
static int | auth_fail (int callno, int failcode) |
static int | auth_reject (const void *data) |
static int | authenticate (const char *challenge, const char *secret, const char *keyn, int authmethods, struct iax_ie_data *ied, struct sockaddr_in *sin, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx) |
static int | authenticate_reply (struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey) |
static int | authenticate_request (int call_num) |
static int | authenticate_verify (struct chan_iax2_pvt *p, struct iax_ies *ies) |
static int | auto_congest (const void *data) |
static int | auto_hangup (const void *data) |
static struct iax2_context * | build_context (char *context) |
static void | build_enc_keys (const unsigned char *digest, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx) |
static struct iax2_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) |
Create peer structure based on configuration. | |
static struct iax2_user * | build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) |
Create in-memory user structure from configuration. | |
static int | cache_get_callno_locked (const char *data) |
static unsigned int | calc_rxstamp (struct chan_iax2_pvt *p, unsigned int offset) |
static unsigned int | calc_timestamp (struct chan_iax2_pvt *p, unsigned int ts, struct ast_frame *f) |
static unsigned int | calc_txpeerstamp (struct iax2_trunk_peer *tpeer, int sampms, struct timeval *tv) |
static int | check_access (int callno, struct sockaddr_in *sin, struct iax_ies *ies) |
static int | check_provisioning (struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver) |
static int | check_srcaddr (struct sockaddr *sa, socklen_t salen) |
Check if address can be used as packet source. | |
static int | complete_dpreply (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
static char * | complete_iax2_show_peer (const char *line, const char *word, int pos, int state) |
static int | complete_transfer (int callno, struct iax_ies *ies) |
static unsigned char | compress_subclass (int subclass) |
static void | construct_rr (struct chan_iax2_pvt *pvt, struct iax_ie_data *iep) |
static int | create_addr (const char *peername, struct ast_channel *c, struct sockaddr_in *sin, struct create_addr_info *cai) |
static int | decode_frame (aes_decrypt_ctx *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static int | decrypt_frame (int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static void | defer_full_frame (struct iax2_thread *from_here, struct iax2_thread *to_here) |
Queue the last read full frame for processing by a certain thread. | |
static void | delete_users (void) |
static void | destroy_firmware (struct iax_firmware *cur) |
static void | dp_lookup (int callno, const char *context, const char *callednum, const char *callerid, int skiplock) |
static void * | dp_lookup_thread (void *data) |
static int | encrypt_frame (aes_encrypt_ctx *ecx, struct ast_iax2_full_hdr *fh, unsigned char *poo, int *datalen) |
static int | expire_registry (const void *data) |
static struct iax2_dpcache * | find_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_thread * | find_idle_thread (void) |
static struct iax2_peer * | find_peer (const char *name, int realtime) |
static struct iax2_trunk_peer * | find_tpeer (struct sockaddr_in *sin, int fd) |
static unsigned int | fix_peerts (struct timeval *tv, int callno, unsigned int ts) |
static void | free_context (struct iax2_context *con) |
static int | function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
static int | get_auth_methods (char *value) |
static int | get_encrypt_methods (const char *s) |
static int | get_from_jb (const void *p) |
static void | handle_deferred_full_frames (struct iax2_thread *thread) |
Handle any deferred full frames for this thread. | |
static int | handle_error (void) |
static int | iax2_ack_registry (struct iax_ies *ies, struct sockaddr_in *sin, int callno) |
Acknowledgment received for OUR registration. | |
static int | iax2_answer (struct ast_channel *c) |
static enum ast_bridge_result | iax2_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
static int | iax2_call (struct ast_channel *c, char *dest, int timeout) |
static int | iax2_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
part of the IAX2 dial plan switch interface | |
static unsigned int | iax2_datetime (const char *tz) |
static void | iax2_destroy (int callno) |
static void | iax2_destroy_helper (struct chan_iax2_pvt *pvt) |
static int | iax2_devicestate (void *data) |
Part of the device state notification system ---. | |
static int | iax2_digit_begin (struct ast_channel *c, char digit) |
static int | iax2_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
static int | iax2_do_debug (int fd, int argc, char *argv[]) |
static int | iax2_do_jb_debug (int fd, int argc, char *argv[]) |
static int | iax2_do_register (struct iax2_registry *reg) |
static int | iax2_do_register_s (const void *data) |
static int | iax2_do_trunk_debug (int fd, int argc, char *argv[]) |
static void | iax2_dprequest (struct iax2_dpcache *dp, int callno) |
static int | iax2_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Execute IAX2 dialplan switch. | |
static int | iax2_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 switch interface. | |
static int | iax2_fixup (struct ast_channel *oldchannel, struct ast_channel *newchan) |
static void | iax2_frame_free (struct iax_frame *fr) |
static int | iax2_getpeername (struct sockaddr_in sin, char *host, int len) |
static int | iax2_getpeertrunk (struct sockaddr_in sin) |
static int | iax2_hangup (struct ast_channel *c) |
static int | iax2_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen) |
static int | iax2_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 Switch interface. | |
static int | iax2_no_debug (int fd, int argc, char *argv[]) |
static int | iax2_no_jb_debug (int fd, int argc, char *argv[]) |
static int | iax2_no_trunk_debug (int fd, int argc, char *argv[]) |
static int | iax2_poke_noanswer (const void *data) |
static int | iax2_poke_peer (struct iax2_peer *peer, int heldcall) |
static int | iax2_poke_peer_cb (void *obj, void *arg, int flags) |
static int | iax2_poke_peer_s (const void *data) |
static int | iax2_predestroy (int callno) |
static void * | iax2_process_thread (void *data) |
static void | iax2_process_thread_cleanup (void *data) |
static int | iax2_prov_app (struct ast_channel *chan, void *data) |
static int | iax2_prov_cmd (int fd, int argc, char *argv[]) |
static char * | iax2_prov_complete_template_3rd (const char *line, const char *word, int pos, int state) |
static int | iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force) |
static int | iax2_prune_realtime (int fd, int argc, char *argv[]) |
static int | iax2_queue_control_data (int callno, enum ast_control_frame_type control, const void *data, size_t datalen) |
Queue a control frame on the ast_channel owner. | |
static int | iax2_queue_frame (int callno, struct ast_frame *f) |
Queue a frame to a call's owning asterisk channel. | |
static int | iax2_queue_hangup (int callno) |
Queue a hangup frame on the ast_channel owner. | |
static struct ast_frame * | iax2_read (struct ast_channel *c) |
static int | iax2_register (char *value, int lineno) |
static int | iax2_reload (int fd, int argc, char *argv[]) |
static struct ast_channel * | iax2_request (const char *type, int format, void *data, int *cause) |
static int | iax2_sched_add (struct sched_context *con, int when, ast_sched_cb callback, const void *data) |
static int | iax2_send (struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final) |
static int | iax2_sendhtml (struct ast_channel *c, int subclass, const char *data, int datalen) |
static int | iax2_sendimage (struct ast_channel *c, struct ast_frame *img) |
static int | iax2_sendtext (struct ast_channel *c, const char *text) |
static int | iax2_setoption (struct ast_channel *c, int option, void *data, int datalen) |
static int | iax2_show_cache (int fd, int argc, char *argv[]) |
static int | iax2_show_channels (int fd, int argc, char *argv[]) |
static int | iax2_show_firmware (int fd, int argc, char *argv[]) |
static int | iax2_show_netstats (int fd, int argc, char *argv[]) |
static int | iax2_show_peer (int fd, int argc, char *argv[]) |
Show one peer in detail. | |
static int | iax2_show_peers (int fd, int argc, char *argv[]) |
static int | iax2_show_registry (int fd, int argc, char *argv[]) |
static int | iax2_show_stats (int fd, int argc, char *argv[]) |
static int | iax2_show_threads (int fd, int argc, char *argv[]) |
static int | iax2_show_users (int fd, int argc, char *argv[]) |
static int | iax2_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly) |
static int | iax2_test_losspct (int fd, int argc, char *argv[]) |
static int | iax2_transfer (struct ast_channel *c, const char *dest) |
static int | iax2_transmit (struct iax_frame *fr) |
static int | iax2_trunk_expired (struct iax2_trunk_peer *tpeer, struct timeval *now) |
static int | iax2_trunk_queue (struct chan_iax2_pvt *pvt, struct iax_frame *fr) |
static int | iax2_vnak (int callno) |
static int | iax2_write (struct ast_channel *c, struct ast_frame *f) |
static int | iax_check_version (char *dev) |
static void | iax_debug_output (const char *data) |
static void | iax_error_output (const char *data) |
static int | iax_firmware_append (struct iax_ie_data *ied, const unsigned char *dev, unsigned int desc) |
static int | iax_park (struct ast_channel *chan1, struct ast_channel *chan2) |
static void * | iax_park_thread (void *stuff) |
static struct iax_frame * | iaxfrdup2 (struct iax_frame *fr) |
static void | insert_idle_thread (struct iax2_thread *thread) |
static void | jb_debug_output (const char *fmt,...) |
static void | jb_error_output (const char *fmt,...) |
static void | jb_warning_output (const char *fmt,...) |
static int | load_module (void) |
Load IAX2 module, load configuraiton ---. | |
static void | lock_both (unsigned short callno0, unsigned short callno1) |
static int | make_trunk (unsigned short callno, int locked) |
static int | manager_iax2_show_netstats (struct mansession *s, const struct message *m) |
static int | manager_iax2_show_peers (struct mansession *s, const struct message *m) |
static int | match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, struct chan_iax2_pvt *cur, int check_dcallno) |
static void | memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, aes_decrypt_ctx *dcx) |
static void | memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, aes_encrypt_ctx *ecx) |
static void | merge_encryption (struct chan_iax2_pvt *p, unsigned int enc) |
static void * | network_thread (void *ignore) |
static struct chan_iax2_pvt * | new_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_peer * | peer_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_peer * | peer_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_peer * | realtime_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_user * | realtime_user (const char *username, struct sockaddr_in *sin) |
static void | reg_source_db (struct iax2_peer *p) |
static void | register_peer_exten (struct iax2_peer *peer, int onoff) |
static int | register_verify (int callno, struct sockaddr_in *sin, struct iax_ies *ies) |
Verify inbound registration. | |
static int | registry_authrequest (int callno) |
static int | registry_rerequest (struct iax_ies *ies, int callno, struct sockaddr_in *sin) |
static char * | regstate2str (int regstate) |
static int | reload (void) |
static int | reload_config (void) |
static void | reload_firmware (int unload) |
static void | remove_by_peercallno (struct chan_iax2_pvt *pvt) |
static void | save_rr (struct iax_frame *fr, struct iax_ies *ies) |
static void * | sched_thread (void *ignore) |
static int | schedule_delivery (struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout) |
static int | send_apathetic_reply (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int command, int ts, unsigned char seqno) |
static int | send_command (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_final (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_immediate (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_locked (unsigned short callno, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_transfer (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int) |
static int | send_lagrq (const void *data) |
static int | send_packet (struct iax_frame *f) |
static int | send_ping (const void *data) |
static int | send_trunk (struct iax2_trunk_peer *tpeer, struct timeval *now) |
static int | set_config (char *config_file, int reload) |
Load configuration. | |
static void | set_config_destroy (void) |
static void | set_timing (void) |
static void | signal_condition (ast_mutex_t *lock, ast_cond_t *cond) |
static int | socket_process (struct iax2_thread *thread) |
static int | socket_read (int *id, int fd, short events, void *cbdata) |
static void | spawn_dp_lookup (int callno, const char *context, const char *callednum, const char *callerid) |
static int | start_network_thread (void) |
static void | stop_stuff (int callno) |
static void | store_by_peercallno (struct chan_iax2_pvt *pvt) |
static int | timing_read (int *id, int fd, short events, void *cbdata) |
static int | transmit_trunk (struct iax_frame *f, struct sockaddr_in *sin, int sockfd) |
static int | try_firmware (char *s) |
static int | try_transfer (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
static int | uncompress_subclass (unsigned char csub) |
static void | unlink_peer (struct iax2_peer *peer) |
static int | unload_module (void) |
static void | unlock_both (unsigned short callno0, unsigned short callno1) |
static void | unwrap_timestamp (struct iax_frame *fr) |
static void | update_jbsched (struct chan_iax2_pvt *pvt) |
static void | update_max_nontrunk (void) |
static void | update_max_trunk (void) |
static int | update_packet (struct iax_frame *f) |
static int | update_registry (struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) |
static int | user_cmp_cb (void *obj, void *arg, int flags) |
static int | user_delme_cb (void *obj, void *arg, int flags) |
static void | user_destructor (void *obj) |
static int | user_hash_cb (const void *obj, const int flags) |
static struct iax2_user * | user_ref (struct iax2_user *user) |
static struct iax2_user * | user_unref (struct iax2_user *user) |
static void | vnak_retransmit (int callno, int last) |
Variables | |
static char | accountcode [AST_MAX_ACCOUNT_CODE] |
static int | adsi = 0 |
static int | amaflags = 0 |
static int | authdebug = 1 |
static int | autokill = 0 |
static struct ast_cli_entry | cli_iax2 [] |
static struct ast_cli_entry | cli_iax2_jb_debug_deprecated |
static struct ast_cli_entry | cli_iax2_no_debug_deprecated |
static struct ast_cli_entry | cli_iax2_no_jb_debug_deprecated |
static struct ast_cli_entry | cli_iax2_no_trunk_debug_deprecated |
static struct ast_cli_entry | cli_iax2_trunk_debug_deprecated |
static char | context [80] = "default" |
static char | debug_jb_usage [] |
static char | debug_trunk_usage [] |
static char | debug_usage [] |
static int | defaultsockfd = -1 |
static int | delayreject = 0 |
static struct iax2_dpcache * | dpcache |
static int | global_rtautoclear = 120 |
static struct ast_flags | globalflags = { 0 } |
static int | iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH |
static int | iax2_encryption = 0 |
enum { ... } | iax2_flags |
int(* | iax2_regfunk )(const char *username, int onoff) = NULL |
static char | iax2_reload_usage [] |
enum { ... } | iax2_state |
static struct ast_switch | iax2_switch |
static struct ast_channel_tech | iax2_tech |
static char | iax2_test_losspct_usage [] |
static struct ao2_container * | iax_peercallno_pvts |
Another container of iax2_pvt structures. | |
static int | iaxactivethreadcount = 0 |
static int | iaxcompat = 0 |
static int | iaxdebug = 0 |
static int | iaxdefaultdpcache = 10 * 60 |
static int | iaxdefaulttimeout = 5 |
static int | iaxdynamicthreadcount = 0 |
static int | iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT |
struct ast_custom_function | iaxpeer_function |
static struct ast_iax2_queue | iaxq |
static struct chan_iax2_pvt * | iaxs [IAX_MAX_CALLS] |
static ast_mutex_t | iaxsl [ARRAY_LEN(iaxs)] |
static int | iaxthreadcount = DEFAULT_THREAD_COUNT |
static int | iaxtrunkdebug = 0 |
static struct io_context * | io |
static int | lagrq_time = 10 |
static char | language [MAX_LANGUAGE] = "" |
static struct timeval | lastused [ARRAY_LEN(iaxs)] |
static int | max_reg_expire |
static int | max_retries = 4 |
static int | maxauthreq = 3 |
static int | maxjitterbuffer = 1000 |
static int | maxjitterinterps = 10 |
static int | maxnontrunkcall = 1 |
static int | maxtrunkcall = TRUNK_CALL_START |
static int | min_reg_expire |
static char | mohinterpret [MAX_MUSICCLASS] |
static char | mohsuggest [MAX_MUSICCLASS] |
static struct ast_netsock_list * | netsock |
static pthread_t | netthreadid = AST_PTHREADT_NULL |
static char | no_debug_jb_usage [] |
static char | no_debug_trunk_usage [] |
static char | no_debug_usage [] |
static struct ast_netsock_list * | outsock |
static char * | papp = "IAX2Provision" |
static char * | pdescrip |
static struct ao2_container * | peers |
static int | ping_time = 21 |
static struct ast_codec_pref | prefs |
static char | prune_realtime_usage [] |
static char * | psyn = "Provision a calling IAXy with a given template" |
static char | regcontext [AST_MAX_CONTEXT] = "" |
static int | resyncthreshold = 1000 |
static struct sched_context * | sched |
static ast_cond_t | sched_cond |
static pthread_t | schedthreadid = AST_PTHREADT_NULL |
static char | show_cache_usage [] |
static char | show_channels_usage [] |
static char | show_firmware_usage [] |
static char | show_netstats_usage [] |
static char | show_peer_usage [] |
static char | show_peers_usage [] |
static char | show_prov_usage [] |
static char | show_reg_usage [] |
static char | show_stats_usage [] |
static char | show_threads_usage [] |
static char | show_users_usage [] |
static const char | tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)" |
static int | test_losspct = 0 |
static int | timingfd = -1 |
static unsigned int | tos = 0 |
static struct iax2_trunk_peer * | tpeers |
static int | trunkfreq = 20 |
static struct ao2_container * | users |
static struct ast_firmware_list | waresl |
Definition in file chan_iax2.c.
#define CACHE_FLAG_CANEXIST (1 << 2) |
Extension can exist
Definition at line 665 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_canmatch(), and iax2_show_cache().
#define CACHE_FLAG_EXISTS (1 << 0) |
Extension exists
Definition at line 661 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_exec(), iax2_exists(), and iax2_show_cache().
#define CACHE_FLAG_MATCHMORE (1 << 7) |
Matchmore
Definition at line 675 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_matchmore(), and iax2_show_cache().
#define CACHE_FLAG_NONEXISTENT (1 << 1) |
Extension is nonexistent
Definition at line 663 of file chan_iax2.c.
Referenced by complete_dpreply(), and iax2_show_cache().
#define CACHE_FLAG_PENDING (1 << 3) |
Waiting to hear back response
Definition at line 667 of file chan_iax2.c.
Referenced by complete_dpreply(), find_cache(), and iax2_show_cache().
#define CACHE_FLAG_TIMEOUT (1 << 4) |
Timed out
Definition at line 669 of file chan_iax2.c.
Referenced by find_cache(), and iax2_show_cache().
#define CACHE_FLAG_TRANSMITTED (1 << 5) |
Request transmitted
Definition at line 671 of file chan_iax2.c.
Referenced by iax2_dprequest(), iax2_show_cache(), and socket_process().
#define CACHE_FLAG_UNKNOWN (1 << 6) |
Timeout
Definition at line 673 of file chan_iax2.c.
Referenced by complete_dpreply(), and iax2_show_cache().
#define CALLNO_TO_PTR | ( | a | ) | ((void *)(unsigned long)(a)) |
Definition at line 126 of file chan_iax2.c.
Referenced by ast_iax2_new(), iax2_call(), and update_jbsched().
#define DEBUG_SCHED_MULTITHREAD |
Definition at line 114 of file chan_iax2.c.
#define DEBUG_SUPPORT |
Definition at line 134 of file chan_iax2.c.
#define DEFAULT_DROP 3 |
Definition at line 132 of file chan_iax2.c.
#define DEFAULT_FREQ_NOTOK 10 * 1000 |
Definition at line 199 of file chan_iax2.c.
Referenced by build_peer(), handle_response_peerpoke(), and sip_poke_noanswer().
#define DEFAULT_FREQ_OK 60 * 1000 |
Definition at line 198 of file chan_iax2.c.
Referenced by build_peer(), and handle_response_peerpoke().
#define DEFAULT_MAX_THREAD_COUNT 100 |
Definition at line 129 of file chan_iax2.c.
#define DEFAULT_MAXMS 2000 |
Definition at line 197 of file chan_iax2.c.
#define DEFAULT_RETRY_TIME 1000 |
#define DEFAULT_THREAD_COUNT 10 |
Definition at line 128 of file chan_iax2.c.
#define DEFAULT_TRUNKDATA 640 * 10 |
40ms, uncompressed linear * 10 channels
Definition at line 442 of file chan_iax2.c.
Referenced by iax2_trunk_queue().
#define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" |
#define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
#define FORMAT "%-15.15s %-15d %-15d\n" |
#define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
#define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
#define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" |
#define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
#define FORMAT2 "%-15.15s %-15.15s %-15.15s\n" |
#define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
#define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
#define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
#define GAMMA (0.01) |
Definition at line 139 of file chan_iax2.c.
#define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF |
Definition at line 180 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), and set_config().
#define IAX_CAPABILITY_LOWBANDWIDTH |
Value:
(IAX_CAPABILITY_MEDBANDWIDTH & \ ~AST_FORMAT_G726 & \ ~AST_FORMAT_G726_AAL2 & \ ~AST_FORMAT_ADPCM)
Definition at line 188 of file chan_iax2.c.
Referenced by set_config().
#define IAX_CAPABILITY_LOWFREE |
Value:
Definition at line 193 of file chan_iax2.c.
#define IAX_CAPABILITY_MEDBANDWIDTH |
Value:
(IAX_CAPABILITY_FULLBANDWIDTH & \ ~AST_FORMAT_SLINEAR & \ ~AST_FORMAT_ULAW & \ ~AST_FORMAT_ALAW & \ ~AST_FORMAT_G722)
Definition at line 182 of file chan_iax2.c.
Referenced by set_config().
#define IAX_IOSTATE_IDLE 0 |
#define IAX_IOSTATE_PROCESSING 2 |
#define IAX_IOSTATE_READY 1 |
#define IAX_IOSTATE_SCHEDREADY 3 |
Definition at line 699 of file chan_iax2.c.
Referenced by __schedule_action(), and iax2_process_thread().
#define IAX_TYPE_DYNAMIC 2 |
Definition at line 702 of file chan_iax2.c.
Referenced by find_idle_thread(), iax2_process_thread(), iax2_show_threads(), and insert_idle_thread().
#define IAX_TYPE_POOL 1 |
#define IPTOS_MINCOST 0x02 |
Definition at line 117 of file chan_iax2.c.
#define MAX_JITTER_BUFFER 50 |
Definition at line 439 of file chan_iax2.c.
#define MAX_PEER_BUCKETS 1 |
This module will get much higher performance when doing a lot of user and peer lookups if the number of buckets is increased from 1. However, to maintain old behavior for Asterisk 1.4, these are set to 1 by default. When using multiple buckets, search order through these containers is considered random, so you will not be able to depend on the order the entires are specified in iax.conf for matching order.
Definition at line 647 of file chan_iax2.c.
Referenced by load_module(), and set_config().
#define MAX_RETRY_TIME 10000 |
#define MAX_TIMESTAMP_SKEW 160 |
maximum difference between actual and predicted ts for sending
Definition at line 445 of file chan_iax2.c.
#define MAX_TRUNKDATA 640 * 200 |
40ms, uncompressed linear * 200 channels
Definition at line 443 of file chan_iax2.c.
Referenced by iax2_trunk_queue(), and timing_read().
#define MAX_USER_BUCKETS MAX_PEER_BUCKETS |
#define MEMORY_SIZE 100 |
Definition at line 131 of file chan_iax2.c.
#define MIN_JITTER_BUFFER 10 |
Definition at line 440 of file chan_iax2.c.
#define MIN_RETRY_TIME 100 |
#define MIN_REUSE_TIME 60 |
#define NEW_ALLOW 1 |
#define NEW_FORCE 2 |
Definition at line 1430 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 |
#define PTR_TO_CALLNO | ( | a | ) | ((unsigned short)(unsigned long)(a)) |
Definition at line 125 of file chan_iax2.c.
Referenced by __auto_congest(), __get_from_jb(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), and iax2_write().
#define SCHED_MULTITHREADED |
Definition at line 110 of file chan_iax2.c.
Definition at line 983 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 829 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 448 of file chan_iax2.c.
anonymous enum |
Definition at line 233 of file chan_iax2.c.
00233 { 00234 IAX_STATE_STARTED = (1 << 0), 00235 IAX_STATE_AUTHENTICATED = (1 << 1), 00236 IAX_STATE_TBD = (1 << 2), 00237 IAX_STATE_UNCHANGED = (1 << 3), 00238 } iax2_state;
anonymous enum |
Definition at line 245 of file chan_iax2.c.
00245 { 00246 IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ 00247 IAX_DELME = (1 << 1), /*!< Needs to be deleted */ 00248 IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ 00249 IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ 00250 IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ 00251 IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ 00252 IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ 00253 IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ 00254 /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ 00255 IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ 00256 IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ 00257 IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ 00258 IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ 00259 IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ 00260 IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ 00261 IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ 00262 IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ 00263 IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ 00264 IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ 00265 IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ 00266 IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 00267 IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ 00268 IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ 00269 IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ 00270 IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ 00271 IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a 00272 response, so that we've achieved a three-way handshake with 00273 them before sending voice or anything else*/ 00274 IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */ 00275 } iax2_flags;
enum iax_reg_state |
REG_STATE_UNREGISTERED | |
REG_STATE_REGSENT | |
REG_STATE_AUTHSENT | |
REG_STATE_REGISTERED | |
REG_STATE_REJECTED | |
REG_STATE_TIMEOUT | |
REG_STATE_NOAUTH |
Definition at line 394 of file chan_iax2.c.
00394 { 00395 REG_STATE_UNREGISTERED = 0, 00396 REG_STATE_REGSENT, 00397 REG_STATE_AUTHSENT, 00398 REG_STATE_REGISTERED, 00399 REG_STATE_REJECTED, 00400 REG_STATE_TIMEOUT, 00401 REG_STATE_NOAUTH 00402 };
enum iax_transfer_state |
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 404 of file chan_iax2.c.
00404 { 00405 TRANSFER_NONE = 0, 00406 TRANSFER_BEGIN, 00407 TRANSFER_READY, 00408 TRANSFER_RELEASED, 00409 TRANSFER_PASSTHROUGH, 00410 TRANSFER_MBEGIN, 00411 TRANSFER_MREADY, 00412 TRANSFER_MRELEASED, 00413 TRANSFER_MPASSTHROUGH, 00414 TRANSFER_MEDIA, 00415 TRANSFER_MEDIAPASS 00416 };
static void __attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2149 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, iax2_registry::callno, chan_iax2_pvt::error, f, iax_frame::final, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, iax_frame::oseqno, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_command(), send_packet(), ast_frame::subclass, iax_frame::transfer, iax_frame::ts, update_packet(), and iax2_registry::us.
Referenced by attempt_transmit().
02150 { 02151 /* Attempt to transmit the frame to the remote peer... 02152 Called without iaxsl held. */ 02153 struct iax_frame *f = (struct iax_frame *)data; 02154 int freeme=0; 02155 int callno = f->callno; 02156 /* Make sure this call is still active */ 02157 if (callno) 02158 ast_mutex_lock(&iaxsl[callno]); 02159 if (callno && iaxs[callno]) { 02160 if ((f->retries < 0) /* Already ACK'd */ || 02161 (f->retries >= max_retries) /* Too many attempts */) { 02162 /* Record an error if we've transmitted too many times */ 02163 if (f->retries >= max_retries) { 02164 if (f->transfer) { 02165 /* Transfer timeout */ 02166 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 02167 } else if (f->final) { 02168 if (f->final) 02169 iax2_destroy(callno); 02170 } else { 02171 if (iaxs[callno]->owner) 02172 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); 02173 iaxs[callno]->error = ETIMEDOUT; 02174 if (iaxs[callno]->owner) { 02175 struct ast_frame fr = { 0, }; 02176 /* Hangup the fd */ 02177 fr.frametype = AST_FRAME_CONTROL; 02178 fr.subclass = AST_CONTROL_HANGUP; 02179 iax2_queue_frame(callno, &fr); // XXX 02180 /* Remember, owner could disappear */ 02181 if (iaxs[callno] && iaxs[callno]->owner) 02182 iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 02183 } else { 02184 if (iaxs[callno]->reg) { 02185 memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us)); 02186 iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT; 02187 iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; 02188 } 02189 iax2_destroy(callno); 02190 } 02191 } 02192 02193 } 02194 freeme++; 02195 } else { 02196 /* Update it if it needs it */ 02197 update_packet(f); 02198 /* Attempt transmission */ 02199 send_packet(f); 02200 f->retries++; 02201 /* Try again later after 10 times as long */ 02202 f->retrytime *= 10; 02203 if (f->retrytime > MAX_RETRY_TIME) 02204 f->retrytime = MAX_RETRY_TIME; 02205 /* Transfer messages max out at one second */ 02206 if (f->transfer && (f->retrytime > 1000)) 02207 f->retrytime = 1000; 02208 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 02209 } 02210 } else { 02211 /* Make sure it gets freed */ 02212 f->retries = -1; 02213 freeme++; 02214 } 02215 if (callno) 02216 ast_mutex_unlock(&iaxsl[callno]); 02217 /* Do not try again */ 02218 if (freeme) { 02219 /* Don't attempt delivery, just remove it from the queue */ 02220 AST_LIST_LOCK(&iaxq.queue); 02221 AST_LIST_REMOVE(&iaxq.queue, f, list); 02222 iaxq.count--; 02223 AST_LIST_UNLOCK(&iaxq.queue); 02224 f->retrans = -1; 02225 /* Free the IAX frame */ 02226 iax2_frame_free(f); 02227 } 02228 }
static void __auth_reject | ( | const void * | nothing | ) | [static] |
Definition at line 6348 of file chan_iax2.c.
References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().
Referenced by auth_reject().
06349 { 06350 /* Called from IAX thread only, without iaxs lock */ 06351 int callno = (int)(long)(nothing); 06352 struct iax_ie_data ied; 06353 ast_mutex_lock(&iaxsl[callno]); 06354 if (iaxs[callno]) { 06355 memset(&ied, 0, sizeof(ied)); 06356 if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { 06357 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); 06358 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); 06359 } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { 06360 iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); 06361 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 06362 } 06363 send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); 06364 } 06365 ast_mutex_unlock(&iaxsl[callno]); 06366 }
static void __auto_congest | ( | const void * | nothing | ) | [static] |
Definition at line 3104 of file chan_iax2.c.
References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_queue_frame(), iaxs, iaxsl, chan_iax2_pvt::initid, LOG_NOTICE, and PTR_TO_CALLNO.
Referenced by auto_congest().
03105 { 03106 int callno = PTR_TO_CALLNO(nothing); 03107 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; 03108 ast_mutex_lock(&iaxsl[callno]); 03109 if (iaxs[callno]) { 03110 iaxs[callno]->initid = -1; 03111 iax2_queue_frame(callno, &f); 03112 ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n"); 03113 } 03114 ast_mutex_unlock(&iaxsl[callno]); 03115 }
static void __auto_hangup | ( | const void * | nothing | ) | [static] |
Definition at line 6397 of file chan_iax2.c.
References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().
Referenced by auto_hangup().
06398 { 06399 /* Called from IAX thread only, without iaxs lock */ 06400 int callno = (int)(long)(nothing); 06401 struct iax_ie_data ied; 06402 ast_mutex_lock(&iaxsl[callno]); 06403 if (iaxs[callno]) { 06404 memset(&ied, 0, sizeof(ied)); 06405 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); 06406 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); 06407 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 06408 } 06409 ast_mutex_unlock(&iaxsl[callno]); 06410 }
static int __do_deliver | ( | void * | data | ) | [static] |
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 2016 of file chan_iax2.c.
References iax_frame::af, ast_clear_flag, AST_FRFLAG_HAS_TIMING_INFO, ast_test_flag, iax_frame::callno, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, and iax_frame::retrans.
Referenced by __get_from_jb(), and schedule_delivery().
02017 { 02018 /* Just deliver the packet by using queueing. This is called by 02019 the IAX thread with the iaxsl lock held. */ 02020 struct iax_frame *fr = data; 02021 fr->retrans = -1; 02022 ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO); 02023 if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) 02024 iax2_queue_frame(fr->callno, &fr->af); 02025 /* Free our iax frame */ 02026 iax2_frame_free(fr); 02027 /* And don't run again */ 02028 return 0; 02029 }
static void __expire_registry | ( | const void * | data | ) | [static] |
Definition at line 6036 of file chan_iax2.c.
References iax2_peer::addr, ast_db_del(), ast_device_state_changed(), ast_log(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, LOG_DEBUG, manager_event(), option_debug, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().
Referenced by expire_registry().
06037 { 06038 struct iax2_peer *peer = (struct iax2_peer *) data; 06039 06040 if (!peer) 06041 return; 06042 06043 peer->expire = -1; 06044 06045 if (option_debug) 06046 ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name); 06047 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) 06048 realtime_update_peer(peer->name, &peer->addr, 0); 06049 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 06050 /* Reset the address */ 06051 memset(&peer->addr, 0, sizeof(peer->addr)); 06052 /* Reset expiry value */ 06053 peer->expiry = min_reg_expire; 06054 if (!ast_test_flag(peer, IAX_TEMPONLY)) 06055 ast_db_del("IAX/Registry", peer->name); 06056 register_peer_exten(peer, 0); 06057 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 06058 if (iax2_regfunk) 06059 iax2_regfunk(peer->name, 0); 06060 06061 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) 06062 unlink_peer(peer); 06063 06064 peer_unref(peer); 06065 }
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 1515 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, ao2_find(), ao2_ref(), ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, match(), maxnontrunkcall, maxtrunkcall, MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, store_by_peercallno(), TRUNK_CALL_START, and update_max_nontrunk().
Referenced by find_callno(), and find_callno_locked().
01516 { 01517 int res = 0; 01518 int x; 01519 struct timeval now; 01520 char host[80]; 01521 01522 if (new <= NEW_ALLOW) { 01523 if (callno) { 01524 struct chan_iax2_pvt *pvt; 01525 struct chan_iax2_pvt tmp_pvt = { 01526 .callno = dcallno, 01527 .peercallno = callno, 01528 /* hack!! */ 01529 .frames_received = check_dcallno, 01530 }; 01531 01532 memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr)); 01533 01534 if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 01535 if (return_locked) { 01536 ast_mutex_lock(&iaxsl[pvt->callno]); 01537 } 01538 res = pvt->callno; 01539 ao2_ref(pvt, -1); 01540 pvt = NULL; 01541 return res; 01542 } 01543 } 01544 01545 /* Look for an existing connection first */ 01546 for (x = 1; !res && x < maxnontrunkcall; x++) { 01547 ast_mutex_lock(&iaxsl[x]); 01548 if (iaxs[x]) { 01549 /* Look for an exact match */ 01550 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01551 res = x; 01552 } 01553 } 01554 if (!res || !return_locked) 01555 ast_mutex_unlock(&iaxsl[x]); 01556 } 01557 for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) { 01558 ast_mutex_lock(&iaxsl[x]); 01559 if (iaxs[x]) { 01560 /* Look for an exact match */ 01561 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01562 res = x; 01563 } 01564 } 01565 if (!res || !return_locked) 01566 ast_mutex_unlock(&iaxsl[x]); 01567 } 01568 } 01569 if (!res && (new >= NEW_ALLOW)) { 01570 int start, found = 0; 01571 01572 /* It may seem odd that we look through the peer list for a name for 01573 * this *incoming* call. Well, it is weird. However, users don't 01574 * have an IP address/port number that we can match against. So, 01575 * this is just checking for a peer that has that IP/port and 01576 * assuming that we have a user of the same name. This isn't always 01577 * correct, but it will be changed if needed after authentication. */ 01578 if (!iax2_getpeername(*sin, host, sizeof(host))) 01579 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 01580 01581 now = ast_tvnow(); 01582 start = 2 + (ast_random() % (TRUNK_CALL_START - 1)); 01583 for (x = start; 1; x++) { 01584 if (x == TRUNK_CALL_START) { 01585 x = 1; 01586 continue; 01587 } 01588 01589 /* Find first unused call number that hasn't been used in a while */ 01590 ast_mutex_lock(&iaxsl[x]); 01591 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01592 found = 1; 01593 break; 01594 } 01595 ast_mutex_unlock(&iaxsl[x]); 01596 01597 if (x == start - 1) { 01598 break; 01599 } 01600 } 01601 /* We've still got lock held if we found a spot */ 01602 if (x == start - 1 && !found) { 01603 ast_log(LOG_WARNING, "No more space\n"); 01604 return 0; 01605 } 01606 iaxs[x] = new_iax(sin, host); 01607 update_max_nontrunk(); 01608 if (iaxs[x]) { 01609 if (option_debug && iaxdebug) 01610 ast_log(LOG_DEBUG, "Creating new call structure %d\n", x); 01611 iaxs[x]->sockfd = sockfd; 01612 iaxs[x]->addr.sin_port = sin->sin_port; 01613 iaxs[x]->addr.sin_family = sin->sin_family; 01614 iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr; 01615 iaxs[x]->peercallno = callno; 01616 iaxs[x]->callno = x; 01617 iaxs[x]->pingtime = DEFAULT_RETRY_TIME; 01618 iaxs[x]->expiry = min_reg_expire; 01619 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01620 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01621 iaxs[x]->amaflags = amaflags; 01622 ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 01623 01624 ast_string_field_set(iaxs[x], accountcode, accountcode); 01625 ast_string_field_set(iaxs[x], mohinterpret, mohinterpret); 01626 ast_string_field_set(iaxs[x], mohsuggest, mohsuggest); 01627 01628 if (iaxs[x]->peercallno) { 01629 store_by_peercallno(iaxs[x]); 01630 } 01631 } else { 01632 ast_log(LOG_WARNING, "Out of resources\n"); 01633 ast_mutex_unlock(&iaxsl[x]); 01634 return 0; 01635 } 01636 if (!return_locked) 01637 ast_mutex_unlock(&iaxsl[x]); 01638 res = x; 01639 } 01640 return res; 01641 }
static void __get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 2546 of file chan_iax2.c.
References __do_deliver(), ast_codec_interp_len(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_tvadd(), iax2_registry::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, iaxsl, chan_iax2_pvt::jb, JB_DROP, JB_EMPTY, jb_get(), JB_INTERP, jb_next(), JB_NOFRAME, JB_OK, chan_iax2_pvt::jbid, jb_frame::ms, ast_frame::offset, PTR_TO_CALLNO, chan_iax2_pvt::rxcore, ast_frame::samples, ast_frame::src, ast_frame::subclass, update_jbsched(), and chan_iax2_pvt::voiceformat.
Referenced by get_from_jb().
02547 { 02548 int callno = PTR_TO_CALLNO(p); 02549 struct chan_iax2_pvt *pvt = NULL; 02550 struct iax_frame *fr; 02551 jb_frame frame; 02552 int ret; 02553 long now; 02554 long next; 02555 struct timeval tv; 02556 02557 /* Make sure we have a valid private structure before going on */ 02558 ast_mutex_lock(&iaxsl[callno]); 02559 pvt = iaxs[callno]; 02560 if (!pvt) { 02561 /* No go! */ 02562 ast_mutex_unlock(&iaxsl[callno]); 02563 return; 02564 } 02565 02566 pvt->jbid = -1; 02567 02568 gettimeofday(&tv,NULL); 02569 /* round up a millisecond since ast_sched_runq does; */ 02570 /* prevents us from spinning while waiting for our now */ 02571 /* to catch up with runq's now */ 02572 tv.tv_usec += 1000; 02573 02574 now = ast_tvdiff_ms(tv, pvt->rxcore); 02575 02576 if(now >= (next = jb_next(pvt->jb))) { 02577 ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat)); 02578 switch(ret) { 02579 case JB_OK: 02580 fr = frame.data; 02581 __do_deliver(fr); 02582 /* __do_deliver() can cause the call to disappear */ 02583 pvt = iaxs[callno]; 02584 break; 02585 case JB_INTERP: 02586 { 02587 struct ast_frame af = { 0, }; 02588 02589 /* create an interpolation frame */ 02590 af.frametype = AST_FRAME_VOICE; 02591 af.subclass = pvt->voiceformat; 02592 af.samples = frame.ms * 8; 02593 af.src = "IAX2 JB interpolation"; 02594 af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); 02595 af.offset = AST_FRIENDLY_OFFSET; 02596 02597 /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame, 02598 * which we'd need to malloc, and then it would free it. That seems like a drag */ 02599 if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 02600 iax2_queue_frame(callno, &af); 02601 /* iax2_queue_frame() could cause the call to disappear */ 02602 pvt = iaxs[callno]; 02603 } 02604 } 02605 break; 02606 case JB_DROP: 02607 iax2_frame_free(frame.data); 02608 break; 02609 case JB_NOFRAME: 02610 case JB_EMPTY: 02611 /* do nothing */ 02612 break; 02613 default: 02614 /* shouldn't happen */ 02615 break; 02616 } 02617 } 02618 if (pvt) 02619 update_jbsched(pvt); 02620 ast_mutex_unlock(&iaxsl[callno]); 02621 }
static void __iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 5729 of file chan_iax2.c.
References iax2_registry::expire, and iax2_do_register().
Referenced by iax2_do_register_s().
05730 { 05731 struct iax2_registry *reg = (struct iax2_registry *)data; 05732 reg->expire = -1; 05733 iax2_do_register(reg); 05734 }
static void __iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 8830 of file chan_iax2.c.
References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, iax2_registry::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iax2_sched_add(), iaxsl, iax2_peer::lastms, LOG_NOTICE, manager_event(), peer_ref(), peer_unref(), iax2_peer::pokeexpire, and iax2_peer::pokefreqnotok.
Referenced by iax2_poke_noanswer().
08831 { 08832 struct iax2_peer *peer = (struct iax2_peer *)data; 08833 int callno; 08834 08835 if (peer->lastms > -1) { 08836 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); 08837 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); 08838 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 08839 } 08840 if ((callno = peer->callno) > 0) { 08841 ast_mutex_lock(&iaxsl[callno]); 08842 iax2_destroy(callno); 08843 ast_mutex_unlock(&iaxsl[callno]); 08844 } 08845 peer->callno = 0; 08846 peer->lastms = -1; 08847 /* Try again quickly */ 08848 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 08849 if (peer->pokeexpire == -1) 08850 peer_unref(peer); 08851 }
static void __iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 6460 of file chan_iax2.c.
References iax2_poke_peer(), and peer_unref().
Referenced by iax2_poke_peer_s().
06461 { 06462 struct iax2_peer *peer = (struct iax2_peer *)data; 06463 iax2_poke_peer(peer, 0); 06464 peer_unref(peer); 06465 }
static int __iax2_show_peers | ( | int | manager, | |
int | fd, | |||
struct mansession * | s, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4519 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, name, peer_status(), peer_unref(), peers, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by iax2_show_peers(), and manager_iax2_show_peers().
04520 { 04521 regex_t regexbuf; 04522 int havepattern = 0; 04523 int total_peers = 0; 04524 int online_peers = 0; 04525 int offline_peers = 0; 04526 int unmonitored_peers = 0; 04527 struct ao2_iterator i; 04528 04529 #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" 04530 #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" 04531 04532 struct iax2_peer *peer = NULL; 04533 char name[256]; 04534 int registeredonly=0; 04535 char *term = manager ? "\r\n" : "\n"; 04536 04537 switch (argc) { 04538 case 6: 04539 if (!strcasecmp(argv[3], "registered")) 04540 registeredonly = 1; 04541 else 04542 return RESULT_SHOWUSAGE; 04543 if (!strcasecmp(argv[4], "like")) { 04544 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB)) 04545 return RESULT_SHOWUSAGE; 04546 havepattern = 1; 04547 } else 04548 return RESULT_SHOWUSAGE; 04549 break; 04550 case 5: 04551 if (!strcasecmp(argv[3], "like")) { 04552 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04553 return RESULT_SHOWUSAGE; 04554 havepattern = 1; 04555 } else 04556 return RESULT_SHOWUSAGE; 04557 break; 04558 case 4: 04559 if (!strcasecmp(argv[3], "registered")) 04560 registeredonly = 1; 04561 else 04562 return RESULT_SHOWUSAGE; 04563 break; 04564 case 3: 04565 break; 04566 default: 04567 return RESULT_SHOWUSAGE; 04568 } 04569 04570 04571 if (s) 04572 astman_append(s, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04573 else 04574 ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04575 04576 i = ao2_iterator_init(peers, 0); 04577 for (peer = ao2_iterator_next(&i); peer; 04578 peer_unref(peer), peer = ao2_iterator_next(&i)) { 04579 char nm[20]; 04580 char status[20]; 04581 char srch[2000]; 04582 int retstatus; 04583 04584 if (registeredonly && !peer->addr.sin_addr.s_addr) 04585 continue; 04586 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) 04587 continue; 04588 04589 if (!ast_strlen_zero(peer->username)) 04590 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 04591 else 04592 ast_copy_string(name, peer->name, sizeof(name)); 04593 04594 retstatus = peer_status(peer, status, sizeof(status)); 04595 if (retstatus > 0) 04596 online_peers++; 04597 else if (!retstatus) 04598 offline_peers++; 04599 else 04600 unmonitored_peers++; 04601 04602 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 04603 04604 snprintf(srch, sizeof(srch), FORMAT, name, 04605 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04606 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04607 nm, 04608 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04609 peer->encmethods ? "(E)" : " ", status, term); 04610 04611 if (s) 04612 astman_append(s, FORMAT, name, 04613 peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)", 04614 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04615 nm, 04616 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04617 peer->encmethods ? "(E)" : " ", status, term); 04618 else 04619 ast_cli(fd, FORMAT, name, 04620 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04621 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04622 nm, 04623 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04624 peer->encmethods ? "(E)" : " ", status, term); 04625 total_peers++; 04626 } 04627 04628 if (s) 04629 astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04630 else 04631 ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04632 04633 if (havepattern) 04634 regfree(®exbuf); 04635 04636 return RESULT_SUCCESS; 04637 #undef FORMAT 04638 #undef FORMAT2 04639 }
static int __schedule_action | ( | void(*)(const void *data) | func, | |
const void * | data, | |||
const char * | funcname | |||
) | [static] |
Definition at line 958 of file chan_iax2.c.
References ast_log(), find_idle_thread(), func, IAX_IOSTATE_SCHEDREADY, LOG_DEBUG, option_debug, signal_condition(), t, and thread.
00959 { 00960 struct iax2_thread *thread = NULL; 00961 static time_t lasterror; 00962 static time_t t; 00963 00964 thread = find_idle_thread(); 00965 00966 if (thread != NULL) { 00967 thread->schedfunc = func; 00968 thread->scheddata = data; 00969 thread->iostate = IAX_IOSTATE_SCHEDREADY; 00970 #ifdef DEBUG_SCHED_MULTITHREAD 00971 ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc)); 00972 #endif 00973 signal_condition(&thread->lock, &thread->cond); 00974 return 0; 00975 } 00976 time(&t); 00977 if (t != lasterror && option_debug) 00978 ast_log(LOG_DEBUG, "Out of idle IAX2 threads for scheduling!\n"); 00979 lasterror = t; 00980 00981 return -1; 00982 }
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 5020 of file chan_iax2.c.
References ast_frame::data, ast_frame::datalen, ast_frame::frametype, iax2_send(), ast_frame::src, and ast_frame::subclass.
Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().
05022 { 05023 struct ast_frame f = { 0, }; 05024 05025 f.frametype = type; 05026 f.subclass = command; 05027 f.datalen = datalen; 05028 f.src = __FUNCTION__; 05029 f.data = (void *) data; 05030 05031 return iax2_send(i, &f, ts, seqno, now, transfer, final); 05032 }
static void __send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1038 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, iaxs, iaxsl, chan_iax2_pvt::lagid, send_command(), and send_lagrq().
Referenced by send_lagrq().
01039 { 01040 int callno = (long) data; 01041 01042 ast_mutex_lock(&iaxsl[callno]); 01043 01044 while (iaxs[callno] && iaxs[callno]->lagid > -1) { 01045 if (iaxs[callno]->peercallno) { 01046 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); 01047 } 01048 iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data); 01049 break; 01050 } 01051 01052 ast_mutex_unlock(&iaxsl[callno]); 01053 }
static void __send_ping | ( | const void * | data | ) | [static] |
Definition at line 998 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_PING, iaxs, iaxsl, chan_iax2_pvt::pingid, send_command(), and send_ping().
Referenced by send_ping().
00999 { 01000 int callno = (long) data; 01001 01002 ast_mutex_lock(&iaxsl[callno]); 01003 01004 while (iaxs[callno] && iaxs[callno]->pingid != -1) { 01005 if (iaxs[callno]->peercallno) { 01006 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); 01007 } 01008 iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data); 01009 break; 01010 } 01011 01012 ast_mutex_unlock(&iaxsl[callno]); 01013 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 10957 of file chan_iax2.c.
References ao2_ref(), ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_release(), AST_PTHREADT_NULL, ast_unregister_application(), ast_unregister_switch(), cli_iax2, delete_users(), iax2_destroy(), iax2_switch, iax2_tech, iax_peercallno_pvts, iax_provision_unload(), iaxactivethreadcount, iaxq, iaxs, iaxsl, ast_firmware_list::lock, papp, peers, reload_firmware(), sched_context_destroy(), thread, users, and waresl.
Referenced by load_module(), and unload_module().
10958 { 10959 struct iax2_thread *thread = NULL; 10960 int x; 10961 10962 /* Make sure threads do not hold shared resources when they are canceled */ 10963 10964 /* Grab the sched lock resource to keep it away from threads about to die */ 10965 /* Cancel the network thread, close the net socket */ 10966 if (netthreadid != AST_PTHREADT_NULL) { 10967 AST_LIST_LOCK(&iaxq.queue); 10968 ast_mutex_lock(&sched_lock); 10969 pthread_cancel(netthreadid); 10970 ast_cond_signal(&sched_cond); 10971 ast_mutex_unlock(&sched_lock); /* Release the schedule lock resource */ 10972 AST_LIST_UNLOCK(&iaxq.queue); 10973 pthread_join(netthreadid, NULL); 10974 } 10975 if (schedthreadid != AST_PTHREADT_NULL) { 10976 ast_mutex_lock(&sched_lock); 10977 pthread_cancel(schedthreadid); 10978 ast_cond_signal(&sched_cond); 10979 ast_mutex_unlock(&sched_lock); 10980 pthread_join(schedthreadid, NULL); 10981 } 10982 10983 /* Call for all threads to halt */ 10984 AST_LIST_LOCK(&idle_list); 10985 AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) { 10986 AST_LIST_REMOVE_CURRENT(&idle_list, list); 10987 pthread_cancel(thread->threadid); 10988 } 10989 AST_LIST_TRAVERSE_SAFE_END 10990 AST_LIST_UNLOCK(&idle_list); 10991 10992 AST_LIST_LOCK(&active_list); 10993 AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) { 10994 AST_LIST_REMOVE_CURRENT(&active_list, list); 10995 pthread_cancel(thread->threadid); 10996 } 10997 AST_LIST_TRAVERSE_SAFE_END 10998 AST_LIST_UNLOCK(&active_list); 10999 11000 AST_LIST_LOCK(&dynamic_list); 11001 AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) { 11002 AST_LIST_REMOVE_CURRENT(&dynamic_list, list); 11003 pthread_cancel(thread->threadid); 11004 } 11005 AST_LIST_TRAVERSE_SAFE_END 11006 AST_LIST_UNLOCK(&dynamic_list); 11007 11008 AST_LIST_HEAD_DESTROY(&iaxq.queue); 11009 11010 /* Wait for threads to exit */ 11011 while(0 < iaxactivethreadcount) 11012 usleep(10000); 11013 11014 ast_netsock_release(netsock); 11015 ast_netsock_release(outsock); 11016 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 11017 if (iaxs[x]) { 11018 iax2_destroy(x); 11019 } 11020 } 11021 ast_manager_unregister( "IAXpeers" ); 11022 ast_manager_unregister( "IAXnetstats" ); 11023 ast_unregister_application(papp); 11024 ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 11025 ast_unregister_switch(&iax2_switch); 11026 ast_channel_unregister(&iax2_tech); 11027 delete_users(); 11028 iax_provision_unload(); 11029 sched_context_destroy(sched); 11030 reload_firmware(1); 11031 11032 ast_mutex_destroy(&waresl.lock); 11033 11034 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 11035 ast_mutex_destroy(&iaxsl[x]); 11036 } 11037 11038 ao2_ref(peers, -1); 11039 ao2_ref(users, -1); 11040 ao2_ref(iax_peercallno_pvts, -1); 11041 11042 return 0; 11043 }
static int apply_context | ( | struct iax2_context * | con, | |
const char * | context | |||
) | [static] |
Definition at line 5073 of file chan_iax2.c.
References iax2_context::context, and iax2_context::next.
Referenced by check_access().
05074 { 05075 while(con) { 05076 if (!strcmp(con->context, context) || !strcmp(con->context, "*")) 05077 return -1; 05078 con = con->next; 05079 } 05080 return 0; 05081 }
static int ast_cli_netstats | ( | struct mansession * | s, | |
int | fd, | |||
int | limit_fmt | |||
) | [static] |
Definition at line 4847 of file chan_iax2.c.
References ARRAY_LEN, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, iax_rr::delay, iax_rr::dropped, fmt, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, chan_iax2_pvt::frames_received, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), iax_rr::jitter, jb_info::jitter, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, and chan_iax2_pvt::remote_rr.
Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().
04848 { 04849 int x; 04850 int numchans = 0; 04851 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 04852 ast_mutex_lock(&iaxsl[x]); 04853 if (iaxs[x]) { 04854 int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; 04855 char *fmt; 04856 jb_info jbinfo; 04857 04858 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04859 jb_getinfo(iaxs[x]->jb, &jbinfo); 04860 localjitter = jbinfo.jitter; 04861 localdelay = jbinfo.current - jbinfo.min; 04862 locallost = jbinfo.frames_lost; 04863 locallosspct = jbinfo.losspct/1000; 04864 localdropped = jbinfo.frames_dropped; 04865 localooo = jbinfo.frames_ooo; 04866 } else { 04867 localjitter = -1; 04868 localdelay = 0; 04869 locallost = -1; 04870 locallosspct = -1; 04871 localdropped = 0; 04872 localooo = -1; 04873 } 04874 if (limit_fmt) 04875 fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n"; 04876 else 04877 fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"; 04878 if (s) 04879 04880 astman_append(s, fmt, 04881 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04882 iaxs[x]->pingtime, 04883 localjitter, 04884 localdelay, 04885 locallost, 04886 locallosspct, 04887 localdropped, 04888 localooo, 04889 iaxs[x]->frames_received/1000, 04890 iaxs[x]->remote_rr.jitter, 04891 iaxs[x]->remote_rr.delay, 04892 iaxs[x]->remote_rr.losscnt, 04893 iaxs[x]->remote_rr.losspct, 04894 iaxs[x]->remote_rr.dropped, 04895 iaxs[x]->remote_rr.ooo, 04896 iaxs[x]->remote_rr.packets/1000); 04897 else 04898 ast_cli(fd, fmt, 04899 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04900 iaxs[x]->pingtime, 04901 localjitter, 04902 localdelay, 04903 locallost, 04904 locallosspct, 04905 localdropped, 04906 localooo, 04907 iaxs[x]->frames_received/1000, 04908 iaxs[x]->remote_rr.jitter, 04909 iaxs[x]->remote_rr.delay, 04910 iaxs[x]->remote_rr.losscnt, 04911 iaxs[x]->remote_rr.losspct, 04912 iaxs[x]->remote_rr.dropped, 04913 iaxs[x]->remote_rr.ooo, 04914 iaxs[x]->remote_rr.packets/1000 04915 ); 04916 numchans++; 04917 } 04918 ast_mutex_unlock(&iaxsl[x]); 04919 } 04920 return numchans; 04921 }
static struct ast_channel* ast_iax2_new | ( | int | callno, | |
int | state, | |||
int | capability | |||
) | [static, read] |
Create new call, interface with the PBX core.
Definition at line 3725 of file chan_iax2.c.
References chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_channel_free(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_string_field_set, ast_strlen_zero(), chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, chan_iax2_pvt::callno, CALLNO_TO_PTR, chan_iax2_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, iax2_tech, iaxs, iaxsl, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), chan_iax2_pvt::peeradsicpe, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, chan_iax2_pvt::vars, and ast_channel::writeformat.
Referenced by iax2_request(), and socket_process().
03726 { 03727 struct ast_channel *tmp; 03728 struct chan_iax2_pvt *i; 03729 struct ast_variable *v = NULL; 03730 03731 if (!(i = iaxs[callno])) { 03732 ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); 03733 return NULL; 03734 } 03735 03736 /* Don't hold call lock */ 03737 ast_mutex_unlock(&iaxsl[callno]); 03738 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); 03739 ast_mutex_lock(&iaxsl[callno]); 03740 if (!iaxs[callno]) { 03741 if (tmp) { 03742 ast_channel_free(tmp); 03743 } 03744 ast_mutex_unlock(&iaxsl[callno]); 03745 return NULL; 03746 } 03747 03748 if (!tmp) 03749 return NULL; 03750 tmp->tech = &iax2_tech; 03751 /* We can support any format by default, until we get restricted */ 03752 tmp->nativeformats = capability; 03753 tmp->readformat = ast_best_codec(capability); 03754 tmp->writeformat = ast_best_codec(capability); 03755 tmp->tech_pvt = CALLNO_TO_PTR(i->callno); 03756 03757 /* Don't use ast_set_callerid() here because it will 03758 * generate a NewCallerID event before the NewChannel event */ 03759 if (!ast_strlen_zero(i->ani)) 03760 tmp->cid.cid_ani = ast_strdup(i->ani); 03761 else 03762 tmp->cid.cid_ani = ast_strdup(i->cid_num); 03763 tmp->cid.cid_dnid = ast_strdup(i->dnid); 03764 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 03765 tmp->cid.cid_pres = i->calling_pres; 03766 tmp->cid.cid_ton = i->calling_ton; 03767 tmp->cid.cid_tns = i->calling_tns; 03768 if (!ast_strlen_zero(i->language)) 03769 ast_string_field_set(tmp, language, i->language); 03770 if (!ast_strlen_zero(i->accountcode)) 03771 ast_string_field_set(tmp, accountcode, i->accountcode); 03772 if (i->amaflags) 03773 tmp->amaflags = i->amaflags; 03774 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 03775 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 03776 if (i->adsi) 03777 tmp->adsicpe = i->peeradsicpe; 03778 else 03779 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 03780 i->owner = tmp; 03781 i->capability = capability; 03782 03783 for (v = i->vars ; v ; v = v->next) 03784 pbx_builtin_setvar_helper(tmp, v->name, v->value); 03785 03786 if (state != AST_STATE_DOWN) { 03787 if (ast_pbx_start(tmp)) { 03788 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 03789 ast_hangup(tmp); 03790 i->owner = NULL; 03791 return NULL; 03792 } 03793 } 03794 03795 ast_module_ref(ast_module_info->self); 03796 03797 return tmp; 03798 }
static AST_LIST_HEAD_STATIC | ( | dynamic_list | , | |
iax2_thread | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | active_list | , | |
iax2_thread | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | idle_list | , | |
iax2_thread | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | registrations | , | |
iax2_registry | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"Inter Asterisk eXchange (Ver 2)" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
AST_MUTEX_DEFINE_STATIC | ( | dpcache_lock | ) |
AST_MUTEX_DEFINE_STATIC | ( | tpeerlock | ) |
AST_MUTEX_DEFINE_STATIC | ( | sched_lock | ) |
static int attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2230 of file chan_iax2.c.
References __attempt_transmit(), and schedule_action.
Referenced by __attempt_transmit(), and network_thread().
02231 { 02232 #ifdef SCHED_MULTITHREADED 02233 if (schedule_action(__attempt_transmit, data)) 02234 #endif 02235 __attempt_transmit(data); 02236 return 0; 02237 }
static int auth_fail | ( | int | callno, | |
int | failcode | |||
) | [static] |
Definition at line 6382 of file chan_iax2.c.
References AST_SCHED_DEL, auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, iax2_sched_add(), and iaxs.
Referenced by socket_process().
06383 { 06384 /* Schedule sending the authentication failure in one second, to prevent 06385 guessing */ 06386 if (iaxs[callno]) { 06387 iaxs[callno]->authfail = failcode; 06388 if (delayreject) { 06389 AST_SCHED_DEL(sched, iaxs[callno]->authid); 06390 iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno); 06391 } else 06392 auth_reject((void *)(long)callno); 06393 } 06394 return 0; 06395 }
static int auth_reject | ( | const void * | data | ) | [static] |
Definition at line 6368 of file chan_iax2.c.
References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::authid, iax2_registry::callno, iaxs, iaxsl, and schedule_action.
Referenced by auth_fail().
06369 { 06370 int callno = (int)(long)(data); 06371 ast_mutex_lock(&iaxsl[callno]); 06372 if (iaxs[callno]) 06373 iaxs[callno]->authid = -1; 06374 ast_mutex_unlock(&iaxsl[callno]); 06375 #ifdef SCHED_MULTITHREADED 06376 if (schedule_action(__auth_reject, data)) 06377 #endif 06378 __auth_reject(data); 06379 return 0; 06380 }
static int authenticate | ( | const char * | challenge, | |
const char * | secret, | |||
const char * | keyn, | |||
int | authmethods, | |||
struct iax_ie_data * | ied, | |||
struct sockaddr_in * | sin, | |||
aes_encrypt_ctx * | ecx, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 5598 of file chan_iax2.c.
References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_enc_keys(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, iax_ie_append_str(), IAX_IE_MD5_RESULT, IAX_IE_PASSWORD, IAX_IE_RSA_RESULT, LOG_NOTICE, MD5Final(), MD5Init(), and MD5Update().
05599 { 05600 int res = -1; 05601 int x; 05602 if (!ast_strlen_zero(keyn)) { 05603 if (!(authmethods & IAX_AUTH_RSA)) { 05604 if (ast_strlen_zero(secret)) 05605 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)); 05606 } else if (ast_strlen_zero(challenge)) { 05607 ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr)); 05608 } else { 05609 char sig[256]; 05610 struct ast_key *key; 05611 key = ast_key_get(keyn, AST_KEY_PRIVATE); 05612 if (!key) { 05613 ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); 05614 } else { 05615 if (ast_sign(key, (char*)challenge, sig)) { 05616 ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); 05617 res = -1; 05618 } else { 05619 iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); 05620 res = 0; 05621 } 05622 } 05623 } 05624 } 05625 /* Fall back */ 05626 if (res && !ast_strlen_zero(secret)) { 05627 if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) { 05628 struct MD5Context md5; 05629 unsigned char digest[16]; 05630 char digres[128]; 05631 MD5Init(&md5); 05632 MD5Update(&md5, (unsigned char *)challenge, strlen(challenge)); 05633 MD5Update(&md5, (unsigned char *)secret, strlen(secret)); 05634 MD5Final(digest, &md5); 05635 /* If they support md5, authenticate with it. */ 05636 for (x=0;x<16;x++) 05637 sprintf(digres + (x << 1), "%2.2x", digest[x]); /* safe */ 05638 if (ecx && dcx) 05639 build_enc_keys(digest, ecx, dcx); 05640 iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); 05641 res = 0; 05642 } else if (authmethods & IAX_AUTH_PLAINTEXT) { 05643 iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); 05644 res = 0; 05645 } else 05646 ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods); 05647 } 05648 return res; 05649 }
static int authenticate_reply | ( | struct chan_iax2_pvt * | p, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies, | |||
const char * | override, | |||
const char * | okey | |||
) | [static] |
Definition at line 5655 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax2_peer::authmethods, iax_ie_data::buf, chan_iax2_pvt::callno, iax2_registry::callno, iax_ies::challenge, chan_iax2_pvt::dcx, chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, iax2_peer::mask, merge_encryption(), peer_unref(), peers, iax_ie_data::pos, realtime_peer(), send_command(), and iax_ies::username.
Referenced by socket_process().
05656 { 05657 struct iax2_peer *peer = NULL; 05658 /* Start pessimistic */ 05659 int res = -1; 05660 int authmethods = 0; 05661 struct iax_ie_data ied; 05662 uint16_t callno = p->callno; 05663 05664 memset(&ied, 0, sizeof(ied)); 05665 05666 if (ies->username) 05667 ast_string_field_set(p, username, ies->username); 05668 if (ies->challenge) 05669 ast_string_field_set(p, challenge, ies->challenge); 05670 if (ies->authmethods) 05671 authmethods = ies->authmethods; 05672 if (authmethods & IAX_AUTH_MD5) 05673 merge_encryption(p, ies->encmethods); 05674 else 05675 p->encmethods = 0; 05676 05677 /* Check for override RSA authentication first */ 05678 if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) { 05679 /* Normal password authentication */ 05680 res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05681 } else { 05682 struct ao2_iterator i = ao2_iterator_init(peers, 0); 05683 while ((peer = ao2_iterator_next(&i))) { 05684 if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 05685 /* No peer specified at our end, or this is the peer */ 05686 && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) 05687 /* No username specified in peer rule, or this is the right username */ 05688 && (!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))) 05689 /* No specified host, or this is our host */ 05690 ) { 05691 res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05692 if (!res) { 05693 peer_unref(peer); 05694 break; 05695 } 05696 } 05697 peer_unref(peer); 05698 } 05699 if (!peer) { 05700 /* We checked our list and didn't find one. It's unlikely, but possible, 05701 that we're trying to authenticate *to* a realtime peer */ 05702 const char *peer_name = ast_strdupa(p->peer); 05703 ast_mutex_unlock(&iaxsl[callno]); 05704 if ((peer = realtime_peer(peer_name, NULL))) { 05705 ast_mutex_lock(&iaxsl[callno]); 05706 if (!(p = iaxs[callno])) { 05707 peer_unref(peer); 05708 return -1; 05709 } 05710 res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05711 peer_unref(peer); 05712 } 05713 if (!peer) { 05714 ast_mutex_lock(&iaxsl[callno]); 05715 if (!(p = iaxs[callno])) 05716 return -1; 05717 } 05718 } 05719 } 05720 if (ies->encmethods) 05721 ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); 05722 if (!res) 05723 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); 05724 return res; 05725 }
static int authenticate_request | ( | int | call_num | ) | [static] |
Definition at line 5333 of file chan_iax2.c.
References ao2_find(), AST_CAUSE_CALL_REJECTED, AST_FRAME_IAX, ast_random(), ast_set_flag, ast_string_field_set, ast_test_flag, chan_iax2_pvt::authmethods, iax_ie_data::buf, iax2_user::curauthreq, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, iaxs, iax2_user::maxauthreq, iax_ie_data::pos, send_command(), send_command_final(), user_unref(), and users.
Referenced by socket_process().
05334 { 05335 struct iax_ie_data ied; 05336 int res = -1, authreq_restrict = 0; 05337 char challenge[10]; 05338 struct chan_iax2_pvt *p = iaxs[call_num]; 05339 05340 memset(&ied, 0, sizeof(ied)); 05341 05342 /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */ 05343 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 05344 struct iax2_user *user, tmp_user = { 05345 .name = p->username, 05346 }; 05347 05348 user = ao2_find(users, &tmp_user, OBJ_POINTER); 05349 if (user) { 05350 if (user->curauthreq == user->maxauthreq) 05351 authreq_restrict = 1; 05352 else 05353 user->curauthreq++; 05354 user = user_unref(user); 05355 } 05356 } 05357 05358 /* If the AUTHREQ limit test failed, send back an error */ 05359 if (authreq_restrict) { 05360 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached"); 05361 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED); 05362 send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); 05363 return 0; 05364 } 05365 05366 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 05367 if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) { 05368 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 05369 ast_string_field_set(p, challenge, challenge); 05370 /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */ 05371 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge); 05372 } 05373 if (p->encmethods) 05374 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods); 05375 05376 iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username); 05377 05378 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1); 05379 05380 if (p->encmethods) 05381 ast_set_flag(p, IAX_ENCRYPTED); 05382 05383 return res; 05384 }
static int authenticate_verify | ( | struct chan_iax2_pvt * | p, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5386 of file chan_iax2.c.
References ao2_find(), ast_check_signature, ast_clear_flag, ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::rsa_result, iax2_registry::secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.
Referenced by socket_process().
05387 { 05388 char requeststr[256]; 05389 char md5secret[256] = ""; 05390 char secret[256] = ""; 05391 char rsasecret[256] = ""; 05392 int res = -1; 05393 int x; 05394 struct iax2_user *user, tmp_user = { 05395 .name = p->username, 05396 }; 05397 05398 user = ao2_find(users, &tmp_user, OBJ_POINTER); 05399 if (user) { 05400 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 05401 ast_atomic_fetchadd_int(&user->curauthreq, -1); 05402 ast_clear_flag(p, IAX_MAXAUTHREQ); 05403 } 05404 ast_string_field_set(p, host, user->name); 05405 user = user_unref(user); 05406 } 05407 05408 if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) 05409 return res; 05410 if (ies->password) 05411 ast_copy_string(secret, ies->password, sizeof(secret)); 05412 if (ies->md5_result) 05413 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 05414 if (ies->rsa_result) 05415 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 05416 if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) { 05417 struct ast_key *key; 05418 char *keyn; 05419 char tmpkey[256]; 05420 char *stringp=NULL; 05421 ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey)); 05422 stringp=tmpkey; 05423 keyn = strsep(&stringp, ":"); 05424 while(keyn) { 05425 key = ast_key_get(keyn, AST_KEY_PUBLIC); 05426 if (key && !ast_check_signature(key, p->challenge, rsasecret)) { 05427 res = 0; 05428 break; 05429 } else if (!key) 05430 ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); 05431 keyn = strsep(&stringp, ":"); 05432 } 05433 } else if (p->authmethods & IAX_AUTH_MD5) { 05434 struct MD5Context md5; 05435 unsigned char digest[16]; 05436 char *tmppw, *stringp; 05437 05438 tmppw = ast_strdupa(p->secret); 05439 stringp = tmppw; 05440 while((tmppw = strsep(&stringp, ";"))) { 05441 MD5Init(&md5); 05442 MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge)); 05443 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05444 MD5Final(digest, &md5); 05445 /* If they support md5, authenticate with it. */ 05446 for (x=0;x<16;x++) 05447 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05448 if (!strcasecmp(requeststr, md5secret)) { 05449 res = 0; 05450 break; 05451 } 05452 } 05453 } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { 05454 if (!strcmp(secret, p->secret)) 05455 res = 0; 05456 } 05457 return res; 05458 }
static int auto_congest | ( | const void * | data | ) | [static] |
Definition at line 3117 of file chan_iax2.c.
References __auto_congest(), and schedule_action.
Referenced by iax2_call(), and sip_call().
03118 { 03119 #ifdef SCHED_MULTITHREADED 03120 if (schedule_action(__auto_congest, data)) 03121 #endif 03122 __auto_congest(data); 03123 return 0; 03124 }
static int auto_hangup | ( | const void * | data | ) | [static] |
Definition at line 6412 of file chan_iax2.c.
References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::autoid, iax2_registry::callno, iaxs, iaxsl, and schedule_action.
Referenced by iax2_dprequest(), and iax2_provision().
06413 { 06414 int callno = (int)(long)(data); 06415 ast_mutex_lock(&iaxsl[callno]); 06416 if (iaxs[callno]) { 06417 iaxs[callno]->autoid = -1; 06418 } 06419 ast_mutex_unlock(&iaxsl[callno]); 06420 #ifdef SCHED_MULTITHREADED 06421 if (schedule_action(__auto_hangup, data)) 06422 #endif 06423 __auto_hangup(data); 06424 return 0; 06425 }
static struct iax2_context* build_context | ( | char * | context | ) | [static, read] |
Definition at line 9151 of file chan_iax2.c.
References ast_calloc, and iax2_context::context.
Referenced by build_user().
09152 { 09153 struct iax2_context *con; 09154 09155 if ((con = ast_calloc(1, sizeof(*con)))) 09156 ast_copy_string(con->context, context, sizeof(con->context)); 09157 09158 return con; 09159 }
static void build_enc_keys | ( | const unsigned char * | digest, | |
aes_encrypt_ctx * | ecx, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 4105 of file chan_iax2.c.
References aes_decrypt_key128(), and aes_encrypt_key128().
Referenced by authenticate(), and decrypt_frame().
04106 { 04107 aes_encrypt_key128(digest, ecx); 04108 aes_decrypt_key128(digest, dcx); 04109 }
static struct iax2_peer * build_peer | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static, read] |
Create peer structure based on configuration.
Definition at line 9297 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, ao2_alloc(), ao2_find(), ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), AST_SCHED_DEL, ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), iax2_peer::authmethods, iax2_peer::capability, cid_name, cid_num, iax2_peer::defaddr, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, iax2_peer::dnsmgr, iax2_peer::encmethods, iax2_peer::expire, iax2_peer::expiry, get_auth_methods(), get_encrypt_methods(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, prefs, iax2_peer::prefs, iax2_registry::secret, iax2_peer::smoothing, iax2_peer::sockfd, unlink_peer(), and ast_variable::value.
09298 { 09299 struct iax2_peer *peer = NULL; 09300 struct ast_ha *oldha = NULL; 09301 int maskfound=0; 09302 int found=0; 09303 int firstpass=1; 09304 struct iax2_peer tmp_peer = { 09305 .name = name, 09306 }; 09307 09308 if (!temponly) { 09309 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 09310 if (peer && !ast_test_flag(peer, IAX_DELME)) 09311 firstpass = 0; 09312 } 09313 09314 if (peer) { 09315 found++; 09316 if (firstpass) { 09317 oldha = peer->ha; 09318 peer->ha = NULL; 09319 } 09320 unlink_peer(peer); 09321 } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) { 09322 peer->expire = -1; 09323 peer->pokeexpire = -1; 09324 peer->sockfd = defaultsockfd; 09325 if (ast_string_field_init(peer, 32)) 09326 peer = peer_unref(peer); 09327 } 09328 09329 if (peer) { 09330 if (firstpass) { 09331 ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 09332 peer->encmethods = iax2_encryption; 09333 peer->adsi = adsi; 09334 ast_string_field_set(peer,secret,""); 09335 if (!found) { 09336 ast_string_field_set(peer, name, name); 09337 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 09338 peer->expiry = min_reg_expire; 09339 } 09340 peer->prefs = prefs; 09341 peer->capability = iax2_capability; 09342 peer->smoothing = 0; 09343 peer->pokefreqok = DEFAULT_FREQ_OK; 09344 peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; 09345 ast_string_field_set(peer,context,""); 09346 ast_string_field_set(peer,peercontext,""); 09347 ast_clear_flag(peer, IAX_HASCALLERID); 09348 ast_string_field_set(peer, cid_name, ""); 09349 ast_string_field_set(peer, cid_num, ""); 09350 } 09351 09352 if (!v) { 09353 v = alt; 09354 alt = NULL; 09355 } 09356 while(v) { 09357 if (!strcasecmp(v->name, "secret")) { 09358 ast_string_field_set(peer, secret, v->value); 09359 } else if (!strcasecmp(v->name, "mailbox")) { 09360 ast_string_field_set(peer, mailbox, v->value); 09361 } else if (!strcasecmp(v->name, "mohinterpret")) { 09362 ast_string_field_set(peer, mohinterpret, v->value); 09363 } else if (!strcasecmp(v->name, "mohsuggest")) { 09364 ast_string_field_set(peer, mohsuggest, v->value); 09365 } else if (!strcasecmp(v->name, "dbsecret")) { 09366 ast_string_field_set(peer, dbsecret, v->value); 09367 } else if (!strcasecmp(v->name, "trunk")) { 09368 ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); 09369 if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) { 09370 ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name); 09371 ast_clear_flag(peer, IAX_TRUNK); 09372 } 09373 } else if (!strcasecmp(v->name, "auth")) { 09374 peer->authmethods = get_auth_methods(v->value); 09375 } else if (!strcasecmp(v->name, "encryption")) { 09376 peer->encmethods = get_encrypt_methods(v->value); 09377 } else if (!strcasecmp(v->name, "notransfer")) { 09378 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09379 ast_clear_flag(peer, IAX_TRANSFERMEDIA); 09380 ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 09381 } else if (!strcasecmp(v->name, "transfer")) { 09382 if (!strcasecmp(v->value, "mediaonly")) { 09383 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09384 } else if (ast_true(v->value)) { 09385 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09386 } else 09387 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09388 } else if (!strcasecmp(v->name, "jitterbuffer")) { 09389 ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF); 09390 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 09391 ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF); 09392 } else if (!strcasecmp(v->name, "host")) { 09393 if (!strcasecmp(v->value, "dynamic")) { 09394 /* They'll register with us */ 09395 ast_set_flag(peer, IAX_DYNAMIC); 09396 if (!found) { 09397 /* Initialize stuff iff we're not found, otherwise 09398 we keep going with what we had */ 09399 memset(&peer->addr.sin_addr, 0, 4); 09400 if (peer->addr.sin_port) { 09401 /* If we've already got a port, make it the default rather than absolute */ 09402 peer->defaddr.sin_port = peer->addr.sin_port; 09403 peer->addr.sin_port = 0; 09404 } 09405 } 09406 } else { 09407 /* Non-dynamic. Make sure we become that way if we're not */ 09408 AST_SCHED_DEL(sched, peer->expire); 09409 ast_clear_flag(peer, IAX_DYNAMIC); 09410 if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) 09411 return peer_unref(peer); 09412 if (!peer->addr.sin_port) 09413 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 09414 } 09415 if (!maskfound) 09416 inet_aton("255.255.255.255", &peer->mask); 09417 } else if (!strcasecmp(v->name, "defaultip")) { 09418 if (ast_get_ip(&peer->defaddr, v->value)) 09419 return peer_unref(peer); 09420 } else if (!strcasecmp(v->name, "sourceaddress")) { 09421 peer_set_srcaddr(peer, v->value); 09422 } else if (!strcasecmp(v->name, "permit") || 09423 !strcasecmp(v->name, "deny")) { 09424 peer->ha = ast_append_ha(v->name, v->value, peer->ha); 09425 } else if (!strcasecmp(v->name, "mask")) { 09426 maskfound++; 09427 inet_aton(v->value, &peer->mask); 09428 } else if (!strcasecmp(v->name, "context")) { 09429 ast_string_field_set(peer, context, v->value); 09430 } else if (!strcasecmp(v->name, "regexten")) { 09431 ast_string_field_set(peer, regexten, v->value); 09432 } else if (!strcasecmp(v->name, "peercontext")) { 09433 ast_string_field_set(peer, peercontext, v->value); 09434 } else if (!strcasecmp(v->name, "port")) { 09435 if (ast_test_flag(peer, IAX_DYNAMIC)) 09436 peer->defaddr.sin_port = htons(atoi(v->value)); 09437 else 09438 peer->addr.sin_port = htons(atoi(v->value)); 09439 } else if (!strcasecmp(v->name, "username")) { 09440 ast_string_field_set(peer, username, v->value); 09441 } else if (!strcasecmp(v->name, "allow")) { 09442 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); 09443 } else if (!strcasecmp(v->name, "disallow")) { 09444 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); 09445 } else if (!strcasecmp(v->name, "callerid")) { 09446 if (!ast_strlen_zero(v->value)) { 09447 char name2[80]; 09448 char num2[80]; 09449 ast_callerid_split(v->value, name2, 80, num2, 80); 09450 ast_string_field_set(peer, cid_name, name2); 09451 ast_string_field_set(peer, cid_num, num2); 09452 ast_set_flag(peer, IAX_HASCALLERID); 09453 } else { 09454 ast_clear_flag(peer, IAX_HASCALLERID); 09455 ast_string_field_set(peer, cid_name, ""); 09456 ast_string_field_set(peer, cid_num, ""); 09457 } 09458 } else if (!strcasecmp(v->name, "fullname")) { 09459 if (!ast_strlen_zero(v->value)) { 09460 ast_string_field_set(peer, cid_name, v->value); 09461 ast_set_flag(peer, IAX_HASCALLERID); 09462 } else { 09463 ast_string_field_set(peer, cid_name, ""); 09464 if (ast_strlen_zero(peer->cid_num)) 09465 ast_clear_flag(peer, IAX_HASCALLERID); 09466 } 09467 } else if (!strcasecmp(v->name, "cid_number")) { 09468 if (!ast_strlen_zero(v->value)) { 09469 ast_string_field_set(peer, cid_num, v->value); 09470 ast_set_flag(peer, IAX_HASCALLERID); 09471 } else { 09472 ast_string_field_set(peer, cid_num, ""); 09473 if (ast_strlen_zero(peer->cid_name)) 09474 ast_clear_flag(peer, IAX_HASCALLERID); 09475 } 09476 } else if (!strcasecmp(v->name, "sendani")) { 09477 ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 09478 } else if (!strcasecmp(v->name, "inkeys")) { 09479 ast_string_field_set(peer, inkeys, v->value); 09480 } else if (!strcasecmp(v->name, "outkey")) { 09481 ast_string_field_set(peer, outkey, v->value); 09482 } else if (!strcasecmp(v->name, "qualify")) { 09483 if (!strcasecmp(v->value, "no")) { 09484 peer->maxms = 0; 09485 } else if (!strcasecmp(v->value, "yes")) { 09486 peer->maxms = DEFAULT_MAXMS; 09487 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 09488 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); 09489 peer->maxms = 0; 09490 } 09491 } else if (!strcasecmp(v->name, "qualifysmoothing")) { 09492 peer->smoothing = ast_true(v->value); 09493 } else if (!strcasecmp(v->name, "qualifyfreqok")) { 09494 if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) { 09495 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); 09496 } 09497 } else if (!strcasecmp(v->name, "qualifyfreqnotok")) { 09498 if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) { 09499 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); 09500 } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok); 09501 } else if (!strcasecmp(v->name, "timezone")) { 09502 ast_string_field_set(peer, zonetag, v->value); 09503 } else if (!strcasecmp(v->name, "adsi")) { 09504 peer->adsi = ast_true(v->value); 09505 }/* else if (strcasecmp(v->name,"type")) */ 09506 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09507 v = v->next; 09508 if (!v) { 09509 v = alt; 09510 alt = NULL; 09511 } 09512 } 09513 if (!peer->authmethods) 09514 peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09515 ast_clear_flag(peer, IAX_DELME); 09516 /* Make sure these are IPv4 addresses */ 09517 peer->addr.sin_family = AF_INET; 09518 } 09519 if (oldha) 09520 ast_free_ha(oldha); 09521 return peer; 09522 }
static struct iax2_user * build_user | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static, read] |
Create in-memory user structure from configuration.
Definition at line 9538 of file chan_iax2.c.
References iax2_user::adsi, iax2_user::amaflags, ao2_alloc(), ao2_find(), ao2_unlink(), ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_clear_flag, ast_copy_flags, ast_free_ha(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_build, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_new(), iax2_user::authmethods, build_context(), iax2_user::capability, cid_name, cid_num, cleanup(), iax2_user::contexts, iax2_user::curauthreq, iax2_user::encmethods, format, free_context(), get_auth_methods(), get_encrypt_methods(), iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_context::next, prefs, iax2_user::prefs, iax2_registry::secret, user_destructor(), user_unref(), users, ast_variable::value, and iax2_user::vars.
09539 { 09540 struct iax2_user *user = NULL; 09541 struct iax2_context *con, *conl = NULL; 09542 struct ast_ha *oldha = NULL; 09543 struct iax2_context *oldcon = NULL; 09544 int format; 09545 int firstpass=1; 09546 int oldcurauthreq = 0; 09547 char *varname = NULL, *varval = NULL; 09548 struct ast_variable *tmpvar = NULL; 09549 struct iax2_user tmp_user = { 09550 .name = name, 09551 }; 09552 09553 if (!temponly) { 09554 user = ao2_find(users, &tmp_user, OBJ_POINTER); 09555 if (user && !ast_test_flag(user, IAX_DELME)) 09556 firstpass = 0; 09557 } 09558 09559 if (user) { 09560 if (firstpass) { 09561 oldcurauthreq = user->curauthreq; 09562 oldha = user->ha; 09563 oldcon = user->contexts; 09564 user->ha = NULL; 09565 user->contexts = NULL; 09566 } 09567 /* Already in the list, remove it and it will be added back (or FREE'd) */ 09568 ao2_unlink(users, user); 09569 } else { 09570 user = ao2_alloc(sizeof(*user), user_destructor); 09571 } 09572 09573 if (user) { 09574 if (firstpass) { 09575 ast_string_field_free_memory(user); 09576 memset(user, 0, sizeof(struct iax2_user)); 09577 if (ast_string_field_init(user, 32)) { 09578 user = user_unref(user); 09579 goto cleanup; 09580 } 09581 user->maxauthreq = maxauthreq; 09582 user->curauthreq = oldcurauthreq; 09583 user->prefs = prefs; 09584 user->capability = iax2_capability; 09585 user->encmethods = iax2_encryption; 09586 user->adsi = adsi; 09587 ast_string_field_set(user, name, name); 09588 ast_string_field_set(user, language, language); 09589 ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); 09590 ast_clear_flag(user, IAX_HASCALLERID); 09591 ast_string_field_set(user, cid_name, ""); 09592 ast_string_field_set(user, cid_num, ""); 09593 } 09594 if (!v) { 09595 v = alt; 09596 alt = NULL; 09597 } 09598 while(v) { 09599 if (!strcasecmp(v->name, "context")) { 09600 con = build_context(v->value); 09601 if (con) { 09602 if (conl) 09603 conl->next = con; 09604 else 09605 user->contexts = con; 09606 conl = con; 09607 } 09608 } else if (!strcasecmp(v->name, "permit") || 09609 !strcasecmp(v->name, "deny")) { 09610 user->ha = ast_append_ha(v->name, v->value, user->ha); 09611 } else if (!strcasecmp(v->name, "setvar")) { 09612 varname = ast_strdupa(v->value); 09613 if (varname && (varval = strchr(varname,'='))) { 09614 *varval = '\0'; 09615 varval++; 09616 if((tmpvar = ast_variable_new(varname, varval))) { 09617 tmpvar->next = user->vars; 09618 user->vars = tmpvar; 09619 } 09620 } 09621 } else if (!strcasecmp(v->name, "allow")) { 09622 ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); 09623 } else if (!strcasecmp(v->name, "disallow")) { 09624 ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); 09625 } else if (!strcasecmp(v->name, "trunk")) { 09626 ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); 09627 if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) { 09628 ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name); 09629 ast_clear_flag(user, IAX_TRUNK); 09630 } 09631 } else if (!strcasecmp(v->name, "auth")) { 09632 user->authmethods = get_auth_methods(v->value); 09633 } else if (!strcasecmp(v->name, "encryption")) { 09634 user->encmethods = get_encrypt_methods(v->value); 09635 } else if (!strcasecmp(v->name, "notransfer")) { 09636 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09637 ast_clear_flag(user, IAX_TRANSFERMEDIA); 09638 ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 09639 } else if (!strcasecmp(v->name, "transfer")) { 09640 if (!strcasecmp(v->value, "mediaonly")) { 09641 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09642 } else if (ast_true(v->value)) { 09643 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09644 } else 09645 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09646 } else if (!strcasecmp(v->name, "codecpriority")) { 09647 if(!strcasecmp(v->value, "caller")) 09648 ast_set_flag(user, IAX_CODEC_USER_FIRST); 09649 else if(!strcasecmp(v->value, "disabled")) 09650 ast_set_flag(user, IAX_CODEC_NOPREFS); 09651 else if(!strcasecmp(v->value, "reqonly")) { 09652 ast_set_flag(user, IAX_CODEC_NOCAP); 09653 ast_set_flag(user, IAX_CODEC_NOPREFS); 09654 } 09655 } else if (!strcasecmp(v->name, "jitterbuffer")) { 09656 ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF); 09657 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 09658 ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF); 09659 } else if (!strcasecmp(v->name, "dbsecret")) { 09660 ast_string_field_set(user, dbsecret, v->value); 09661 } else if (!strcasecmp(v->name, "secret")) { 09662 if (!ast_strlen_zero(user->secret)) { 09663 char *old = ast_strdupa(user->secret); 09664 09665 ast_string_field_build(user, secret, "%s;%s", old, v->value); 09666 } else 09667 ast_string_field_set(user, secret, v->value); 09668 } else if (!strcasecmp(v->name, "callerid")) { 09669 if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) { 09670 char name2[80]; 09671 char num2[80]; 09672 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 09673 ast_string_field_set(user, cid_name, name2); 09674 ast_string_field_set(user, cid_num, num2); 09675 ast_set_flag(user, IAX_HASCALLERID); 09676 } else { 09677 ast_clear_flag(user, IAX_HASCALLERID); 09678 ast_string_field_set(user, cid_name, ""); 09679 ast_string_field_set(user, cid_num, ""); 09680 } 09681 } else if (!strcasecmp(v->name, "fullname")) { 09682 if (!ast_strlen_zero(v->value)) { 09683 ast_string_field_set(user, cid_name, v->value); 09684 ast_set_flag(user, IAX_HASCALLERID); 09685 } else { 09686 ast_string_field_set(user, cid_name, ""); 09687 if (ast_strlen_zero(user->cid_num)) 09688 ast_clear_flag(user, IAX_HASCALLERID); 09689 } 09690 } else if (!strcasecmp(v->name, "cid_number")) { 09691 if (!ast_strlen_zero(v->value)) { 09692 ast_string_field_set(user, cid_num, v->value); 09693 ast_set_flag(user, IAX_HASCALLERID); 09694 } else { 09695 ast_string_field_set(user, cid_num, ""); 09696 if (ast_strlen_zero(user->cid_name)) 09697 ast_clear_flag(user, IAX_HASCALLERID); 09698 } 09699 } else if (!strcasecmp(v->name, "accountcode")) { 09700 ast_string_field_set(user, accountcode, v->value); 09701 } else if (!strcasecmp(v->name, "mohinterpret")) { 09702 ast_string_field_set(user, mohinterpret, v->value); 09703 } else if (!strcasecmp(v->name, "mohsuggest")) { 09704 ast_string_field_set(user, mohsuggest, v->value); 09705 } else if (!strcasecmp(v->name, "language")) { 09706 ast_string_field_set(user, language, v->value); 09707 } else if (!strcasecmp(v->name, "amaflags")) { 09708 format = ast_cdr_amaflags2int(v->value); 09709 if (format < 0) { 09710 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 09711 } else { 09712 user->amaflags = format; 09713 } 09714 } else if (!strcasecmp(v->name, "inkeys")) { 09715 ast_string_field_set(user, inkeys, v->value); 09716 } else if (!strcasecmp(v->name, "maxauthreq")) { 09717 user->maxauthreq = atoi(v->value); 09718 if (user->maxauthreq < 0) 09719 user->maxauthreq = 0; 09720 } else if (!strcasecmp(v->name, "adsi")) { 09721 user->adsi = ast_true(v->value); 09722 }/* else if (strcasecmp(v->name,"type")) */ 09723 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09724 v = v->next; 09725 if (!v) { 09726 v = alt; 09727 alt = NULL; 09728 } 09729 } 09730 if (!user->authmethods) { 09731 if (!ast_strlen_zero(user->secret)) { 09732 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09733 if (!ast_strlen_zero(user->inkeys)) 09734 user->authmethods |= IAX_AUTH_RSA; 09735 } else if (!ast_strlen_zero(user->inkeys)) { 09736 user->authmethods = IAX_AUTH_RSA; 09737 } else { 09738 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09739 } 09740 } 09741 ast_clear_flag(user, IAX_DELME); 09742 } 09743 cleanup: 09744 if (oldha) 09745 ast_free_ha(oldha); 09746 if (oldcon) 09747 free_context(oldcon); 09748 return user; 09749 }
static int cache_get_callno_locked | ( | const char * | data | ) | [static] |
Definition at line 10254 of file chan_iax2.c.
References ARRAY_LEN, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), iax_ie_data::buf, iax2_registry::callno, chan_iax2_pvt::capability, parsed_dial_string::context, create_addr(), parsed_dial_string::exten, find_callno_locked(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, iaxs, iaxsl, parsed_dial_string::key, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, iax_ie_data::pos, iax2_registry::secret, send_command(), create_addr_info::sockfd, and parsed_dial_string::username.
Referenced by find_cache().
10255 { 10256 struct sockaddr_in sin; 10257 int x; 10258 int callno; 10259 struct iax_ie_data ied; 10260 struct create_addr_info cai; 10261 struct parsed_dial_string pds; 10262 char *tmpstr; 10263 10264 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 10265 /* Look for an *exact match* call. Once a call is negotiated, it can only 10266 look up entries for a single context */ 10267 if (!ast_mutex_trylock(&iaxsl[x])) { 10268 if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) 10269 return x; 10270 ast_mutex_unlock(&iaxsl[x]); 10271 } 10272 } 10273 10274 /* No match found, we need to create a new one */ 10275 10276 memset(&cai, 0, sizeof(cai)); 10277 memset(&ied, 0, sizeof(ied)); 10278 memset(&pds, 0, sizeof(pds)); 10279 10280 tmpstr = ast_strdupa(data); 10281 parse_dial_string(tmpstr, &pds); 10282 10283 if (ast_strlen_zero(pds.peer)) { 10284 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data); 10285 return -1; 10286 } 10287 10288 /* Populate our address from the given */ 10289 if (create_addr(pds.peer, NULL, &sin, &cai)) 10290 return -1; 10291 10292 if (option_debug) 10293 ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n", 10294 pds.peer, pds.username, pds.password, pds.context); 10295 10296 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 10297 if (callno < 1) { 10298 ast_log(LOG_WARNING, "Unable to create call\n"); 10299 return -1; 10300 } 10301 10302 ast_string_field_set(iaxs[callno], dproot, data); 10303 iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; 10304 10305 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 10306 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); 10307 /* the string format is slightly different from a standard dial string, 10308 because the context appears in the 'exten' position 10309 */ 10310 if (pds.exten) 10311 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); 10312 if (pds.username) 10313 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 10314 iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); 10315 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); 10316 /* Keep password handy */ 10317 if (pds.password) 10318 ast_string_field_set(iaxs[callno], secret, pds.password); 10319 if (pds.key) 10320 ast_string_field_set(iaxs[callno], outkey, pds.key); 10321 /* Start the call going */ 10322 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 10323 10324 return callno; 10325 }
static unsigned int calc_rxstamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | offset | |||
) | [static] |
Definition at line 3973 of file chan_iax2.c.
References ast_log(), ast_random(), ast_tvsub(), chan_iax2_pvt::callno, LOG_DEBUG, option_debug, and chan_iax2_pvt::rxcore.
03974 { 03975 /* Returns where in "receive time" we are. That is, how many ms 03976 since we received (or would have received) the frame with timestamp 0 */ 03977 int ms; 03978 #ifdef IAXTESTS 03979 int jit; 03980 #endif /* IAXTESTS */ 03981 /* Setup rxcore if necessary */ 03982 if (ast_tvzero(p->rxcore)) { 03983 p->rxcore = ast_tvnow(); 03984 if (option_debug && iaxdebug) 03985 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n", 03986 p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset); 03987 p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000)); 03988 #if 1 03989 if (option_debug && iaxdebug) 03990 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n", 03991 p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec)); 03992 #endif 03993 } 03994 03995 ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore); 03996 #ifdef IAXTESTS 03997 if (test_jit) { 03998 if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) { 03999 jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0)); 04000 if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0))) 04001 jit = -jit; 04002 ms += jit; 04003 } 04004 } 04005 if (test_late) { 04006 ms += test_late; 04007 test_late = 0; 04008 } 04009 #endif /* IAXTESTS */ 04010 return ms; 04011 }
static unsigned int calc_timestamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | ts, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 3844 of file chan_iax2.c.
References AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_tvadd(), ast_tvsub(), chan_iax2_pvt::callno, ast_frame::delivery, ast_frame::frametype, iaxs, chan_iax2_pvt::lastsent, LOG_DEBUG, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, option_debug, chan_iax2_pvt::peercallno, and ast_frame::samples.
Referenced by iax2_send(), and socket_process().
03845 { 03846 int ms; 03847 int voice = 0; 03848 int genuine = 0; 03849 int adjust; 03850 struct timeval *delivery = NULL; 03851 03852 03853 /* What sort of frame do we have?: voice is self-explanatory 03854 "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK 03855 non-genuine frames are CONTROL frames [ringing etc], DTMF 03856 The "genuine" distinction is needed because genuine frames must get a clock-based timestamp, 03857 the others need a timestamp slaved to the voice frames so that they go in sequence 03858 */ 03859 if (f) { 03860 if (f->frametype == AST_FRAME_VOICE) { 03861 voice = 1; 03862 delivery = &f->delivery; 03863 } else if (f->frametype == AST_FRAME_IAX) { 03864 genuine = 1; 03865 } else if (f->frametype == AST_FRAME_CNG) { 03866 p->notsilenttx = 0; 03867 } 03868 } 03869 if (ast_tvzero(p->offset)) { 03870 gettimeofday(&p->offset, NULL); 03871 /* Round to nearest 20ms for nice looking traces */ 03872 p->offset.tv_usec -= p->offset.tv_usec % 20000; 03873 } 03874 /* If the timestamp is specified, just send it as is */ 03875 if (ts) 03876 return ts; 03877 /* If we have a time that the frame arrived, always use it to make our timestamp */ 03878 if (delivery && !ast_tvzero(*delivery)) { 03879 ms = ast_tvdiff_ms(*delivery, p->offset); 03880 if (option_debug > 2 && iaxdebug) 03881 ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno); 03882 } else { 03883 ms = ast_tvdiff_ms(ast_tvnow(), p->offset); 03884 if (ms < 0) 03885 ms = 0; 03886 if (voice) { 03887 /* On a voice frame, use predicted values if appropriate */ 03888 if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) { 03889 /* Adjust our txcore, keeping voice and non-voice synchronized */ 03890 /* AN EXPLANATION: 03891 When we send voice, we usually send "calculated" timestamps worked out 03892 on the basis of the number of samples sent. When we send other frames, 03893 we usually send timestamps worked out from the real clock. 03894 The problem is that they can tend to drift out of step because the 03895 source channel's clock and our clock may not be exactly at the same rate. 03896 We fix this by continuously "tweaking" p->offset. p->offset is "time zero" 03897 for this call. Moving it adjusts timestamps for non-voice frames. 03898 We make the adjustment in the style of a moving average. Each time we 03899 adjust p->offset by 10% of the difference between our clock-derived 03900 timestamp and the predicted timestamp. That's why you see "10000" 03901 below even though IAX2 timestamps are in milliseconds. 03902 The use of a moving average avoids offset moving too radically. 03903 Generally, "adjust" roams back and forth around 0, with offset hardly 03904 changing at all. But if a consistent different starts to develop it 03905 will be eliminated over the course of 10 frames (200-300msecs) 03906 */ 03907 adjust = (ms - p->nextpred); 03908 if (adjust < 0) 03909 p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000)); 03910 else if (adjust > 0) 03911 p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000)); 03912 03913 if (!p->nextpred) { 03914 p->nextpred = ms; /*f->samples / 8;*/ 03915 if (p->nextpred <= p->lastsent) 03916 p->nextpred = p->lastsent + 3; 03917 } 03918 ms = p->nextpred; 03919 } else { 03920 /* in this case, just use the actual 03921 * time, since we're either way off 03922 * (shouldn't happen), or we're ending a 03923 * silent period -- and seed the next 03924 * predicted time. Also, round ms to the 03925 * next multiple of frame size (so our 03926 * silent periods are multiples of 03927 * frame size too) */ 03928 03929 if (option_debug && iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW ) 03930 ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n", 03931 abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW); 03932 03933 if (f->samples >= 8) /* check to make sure we dont core dump */ 03934 { 03935 int diff = ms % (f->samples / 8); 03936 if (diff) 03937 ms += f->samples/8 - diff; 03938 } 03939 03940 p->nextpred = ms; 03941 p->notsilenttx = 1; 03942 } 03943 } else if ( f->frametype == AST_FRAME_VIDEO ) { 03944 /* 03945 * IAX2 draft 03 says that timestamps MUST be in order. 03946 * It does not say anything about several frames having the same timestamp 03947 * When transporting video, we can have a frame that spans multiple iax packets 03948 * (so called slices), so it would make sense to use the same timestamp for all of 03949 * them 03950 * We do want to make sure that frames don't go backwards though 03951 */ 03952 if ( (unsigned int)ms < p->lastsent ) 03953 ms = p->lastsent; 03954 } else { 03955 /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless 03956 it's a genuine frame */ 03957 if (genuine) { 03958 /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */ 03959 if (ms <= p->lastsent) 03960 ms = p->lastsent + 3; 03961 } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) { 03962 /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */ 03963 ms = p->lastsent + 3; 03964 } 03965 } 03966 } 03967 p->lastsent = ms; 03968 if (voice) 03969 p->nextpred = p->nextpred + f->samples / 8; 03970 return ms; 03971 }
static unsigned int calc_txpeerstamp | ( | struct iax2_trunk_peer * | tpeer, | |
int | sampms, | |||
struct timeval * | tv | |||
) | [static] |
Definition at line 3800 of file chan_iax2.c.
References iax2_trunk_peer::lastsent, iax2_trunk_peer::lasttxtime, MAX_TIMESTAMP_SKEW, iax2_trunk_peer::trunkact, and iax2_trunk_peer::txtrunktime.
Referenced by send_trunk().
03801 { 03802 unsigned long int mssincetx; /* unsigned to handle overflows */ 03803 long int ms, pred; 03804 03805 tpeer->trunkact = *tv; 03806 mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime); 03807 if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) { 03808 /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */ 03809 tpeer->txtrunktime = *tv; 03810 tpeer->lastsent = 999999; 03811 } 03812 /* Update last transmit time now */ 03813 tpeer->lasttxtime = *tv; 03814 03815 /* Calculate ms offset */ 03816 ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime); 03817 /* Predict from last value */ 03818 pred = tpeer->lastsent + sampms; 03819 if (abs(ms - pred) < MAX_TIMESTAMP_SKEW) 03820 ms = pred; 03821 03822 /* We never send the same timestamp twice, so fudge a little if we must */ 03823 if (ms == tpeer->lastsent) 03824 ms = tpeer->lastsent + 1; 03825 tpeer->lastsent = ms; 03826 return ms; 03827 }
static int check_access | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5084 of file chan_iax2.c.
References iax2_user::adsi, chan_iax2_pvt::adsi, iax_ies::adsicpe, chan_iax2_pvt::amaflags, iax2_user::amaflags, ao2_iterator_init(), ao2_iterator_next(), apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), iax2_user::authmethods, chan_iax2_pvt::authmethods, iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, chan_iax2_pvt::calling_pres, iax_ies::calling_pres, chan_iax2_pvt::calling_tns, iax_ies::calling_tns, chan_iax2_pvt::calling_ton, iax_ies::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, iax_ies::capability, cid_name, cid_num, iax_ies::codec_prefs, iax2_context::context, iax2_user::contexts, iax_ies::dnid, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax_ies::format, iax2_user::ha, iax2_getpeertrunk(), IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iax_ies::language, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, chan_iax2_pvt::peeradsicpe, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_user::prefs, chan_iax2_pvt::prefs, prefs, iax_ies::rdnis, realtime_user(), iax2_registry::secret, user_unref(), iax_ies::username, users, ast_variable::value, chan_iax2_pvt::vars, iax2_user::vars, and iax_ies::version.
Referenced by socket_process().
05085 { 05086 /* Start pessimistic */ 05087 int res = -1; 05088 int version = 2; 05089 struct iax2_user *user = NULL, *best = NULL; 05090 int bestscore = 0; 05091 int gotcapability = 0; 05092 struct ast_variable *v = NULL, *tmpvar = NULL; 05093 struct ao2_iterator i; 05094 05095 if (!iaxs[callno]) 05096 return res; 05097 if (ies->called_number) 05098 ast_string_field_set(iaxs[callno], exten, ies->called_number); 05099 if (ies->calling_number) { 05100 ast_shrink_phone_number(ies->calling_number); 05101 ast_string_field_set(iaxs[callno], cid_num, ies->calling_number); 05102 } 05103 if (ies->calling_name) 05104 ast_string_field_set(iaxs[callno], cid_name, ies->calling_name); 05105 if (ies->calling_ani) 05106 ast_string_field_set(iaxs[callno], ani, ies->calling_ani); 05107 if (ies->dnid) 05108 ast_string_field_set(iaxs[callno], dnid, ies->dnid); 05109 if (ies->rdnis) 05110 ast_string_field_set(iaxs[callno], rdnis, ies->rdnis); 05111 if (ies->called_context) 05112 ast_string_field_set(iaxs[callno], context, ies->called_context); 05113 if (ies->language) 05114 ast_string_field_set(iaxs[callno], language, ies->language); 05115 if (ies->username) 05116 ast_string_field_set(iaxs[callno], username, ies->username); 05117 if (ies->calling_ton > -1) 05118 iaxs[callno]->calling_ton = ies->calling_ton; 05119 if (ies->calling_tns > -1) 05120 iaxs[callno]->calling_tns = ies->calling_tns; 05121 if (ies->calling_pres > -1) 05122 iaxs[callno]->calling_pres = ies->calling_pres; 05123 if (ies->format) 05124 iaxs[callno]->peerformat = ies->format; 05125 if (ies->adsicpe) 05126 iaxs[callno]->peeradsicpe = ies->adsicpe; 05127 if (ies->capability) { 05128 gotcapability = 1; 05129 iaxs[callno]->peercapability = ies->capability; 05130 } 05131 if (ies->version) 05132 version = ies->version; 05133 05134 /* Use provided preferences until told otherwise for actual preferences */ 05135 if(ies->codec_prefs) { 05136 ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); 05137 ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); 05138 } 05139 05140 if (!gotcapability) 05141 iaxs[callno]->peercapability = iaxs[callno]->peerformat; 05142 if (version > IAX_PROTO_VERSION) { 05143 ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 05144 ast_inet_ntoa(sin->sin_addr), version); 05145 return res; 05146 } 05147 /* Search the userlist for a compatible entry, and fill in the rest */ 05148 i = ao2_iterator_init(users, 0); 05149 while ((user = ao2_iterator_next(&i))) { 05150 if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ 05151 !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ 05152 && ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */ 05153 && (ast_strlen_zero(iaxs[callno]->context) || /* No context specified */ 05154 apply_context(user->contexts, iaxs[callno]->context))) { /* Context is permitted */ 05155 if (!ast_strlen_zero(iaxs[callno]->username)) { 05156 /* Exact match, stop right now. */ 05157 if (best) 05158 user_unref(best); 05159 best = user; 05160 break; 05161 } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) { 05162 /* No required authentication */ 05163 if (user->ha) { 05164 /* There was host authentication and we passed, bonus! */ 05165 if (bestscore < 4) { 05166 bestscore = 4; 05167 if (best) 05168 user_unref(best); 05169 best = user; 05170 continue; 05171 } 05172 } else { 05173 /* No host access, but no secret, either, not bad */ 05174 if (bestscore < 3) { 05175 bestscore = 3; 05176 if (best) 05177 user_unref(best); 05178 best = user; 05179 continue; 05180 } 05181 } 05182 } else { 05183 if (user->ha) { 05184 /* Authentication, but host access too, eh, it's something.. */ 05185 if (bestscore < 2) { 05186 bestscore = 2; 05187 if (best) 05188 user_unref(best); 05189 best = user; 05190 continue; 05191 } 05192 } else { 05193 /* Authentication and no host access... This is our baseline */ 05194 if (bestscore < 1) { 05195 bestscore = 1; 05196 if (best) 05197 user_unref(best); 05198 best = user; 05199 continue; 05200 } 05201 } 05202 } 05203 } 05204 user_unref(user); 05205 } 05206 user = best; 05207 if (!user && !ast_strlen_zero(iaxs[callno]->username)) { 05208 user = realtime_user(iaxs[callno]->username, sin); 05209 if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ 05210 !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ 05211 user = user_unref(user); 05212 } 05213 } 05214 if (user) { 05215 /* We found our match (use the first) */ 05216 /* copy vars */ 05217 for (v = user->vars ; v ; v = v->next) { 05218 if((tmpvar = ast_variable_new(v->name, v->value))) { 05219 tmpvar->next = iaxs[callno]->vars; 05220 iaxs[callno]->vars = tmpvar; 05221 } 05222 } 05223 /* If a max AUTHREQ restriction is in place, activate it */ 05224 if (user->maxauthreq > 0) 05225 ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ); 05226 iaxs[callno]->prefs = user->prefs; 05227 ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST); 05228 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS); 05229 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP); 05230 iaxs[callno]->encmethods = user->encmethods; 05231 /* Store the requested username if not specified */ 05232 if (ast_strlen_zero(iaxs[callno]->username)) 05233 ast_string_field_set(iaxs[callno], username, user->name); 05234 /* Store whether this is a trunked call, too, of course, and move if appropriate */ 05235 ast_copy_flags(iaxs[callno], user, IAX_TRUNK); 05236 iaxs[callno]->capability = user->capability; 05237 /* And use the default context */ 05238 if (ast_strlen_zero(iaxs[callno]->context)) { 05239 if (user->contexts) 05240 ast_string_field_set(iaxs[callno], context, user->contexts->context); 05241 else 05242 ast_string_field_set(iaxs[callno], context, context); 05243 } 05244 /* And any input keys */ 05245 ast_string_field_set(iaxs[callno], inkeys, user->inkeys); 05246 /* And the permitted authentication methods */ 05247 iaxs[callno]->authmethods = user->authmethods; 05248 iaxs[callno]->adsi = user->adsi; 05249 /* If they have callerid, override the given caller id. Always store the ANI */ 05250 if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) { 05251 if (ast_test_flag(user, IAX_HASCALLERID)) { 05252 iaxs[callno]->calling_tns = 0; 05253 iaxs[callno]->calling_ton = 0; 05254 ast_string_field_set(iaxs[callno], cid_num, user->cid_num); 05255 ast_string_field_set(iaxs[callno], cid_name, user->cid_name); 05256 iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 05257 } 05258 if (ast_strlen_zero(iaxs[callno]->ani)) 05259 ast_string_field_set(iaxs[callno], ani, user->cid_num); 05260 } else { 05261 iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE; 05262 } 05263 if (!ast_strlen_zero(user->accountcode)) 05264 ast_string_field_set(iaxs[callno], accountcode, user->accountcode); 05265 if (!ast_strlen_zero(user->mohinterpret)) 05266 ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret); 05267 if (!ast_strlen_zero(user->mohsuggest)) 05268 ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest); 05269 if (user->amaflags) 05270 iaxs[callno]->amaflags = user->amaflags; 05271 if (!ast_strlen_zero(user->language)) 05272 ast_string_field_set(iaxs[callno], language, user->language); 05273 ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 05274 /* Keep this check last */ 05275 if (!ast_strlen_zero(user->dbsecret)) { 05276 char *family, *key=NULL; 05277 char buf[80]; 05278 family = ast_strdupa(user->dbsecret); 05279 key = strchr(family, '/'); 05280 if (key) { 05281 *key = '\0'; 05282 key++; 05283 } 05284 if (!key || ast_db_get(family, key, buf, sizeof(buf))) 05285 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); 05286 else 05287 ast_string_field_set(iaxs[callno], secret, buf); 05288 } else 05289 ast_string_field_set(iaxs[callno], secret, user->secret); 05290 res = 0; 05291 user = user_unref(user); 05292 } 05293 ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK); 05294 return res; 05295 }
static int check_provisioning | ( | struct sockaddr_in * | sin, | |
int | sockfd, | |||
char * | si, | |||
unsigned int | ver | |||
) | [static] |
Definition at line 6770 of file chan_iax2.c.
References ast_log(), iax2_provision(), iax_provision_version(), LOG_DEBUG, and option_debug.
Referenced by socket_process().
06771 { 06772 unsigned int ourver; 06773 char rsi[80]; 06774 snprintf(rsi, sizeof(rsi), "si-%s", si); 06775 if (iax_provision_version(&ourver, rsi, 1)) 06776 return 0; 06777 if (option_debug) 06778 ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver); 06779 if (ourver != ver) 06780 iax2_provision(sin, sockfd, NULL, rsi, 1); 06781 return 0; 06782 }
static int check_srcaddr | ( | struct sockaddr * | sa, | |
socklen_t | salen | |||
) | [static] |
Check if address can be used as packet source.
Definition at line 9177 of file chan_iax2.c.
References ast_log(), errno, LOG_DEBUG, LOG_ERROR, and option_debug.
Referenced by peer_set_srcaddr().
09178 { 09179 int sd; 09180 int res; 09181 09182 sd = socket(AF_INET, SOCK_DGRAM, 0); 09183 if (sd < 0) { 09184 ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); 09185 return -1; 09186 } 09187 09188 res = bind(sd, sa, salen); 09189 if (res < 0) { 09190 if (option_debug) 09191 ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno)); 09192 close(sd); 09193 return 1; 09194 } 09195 09196 close(sd); 09197 return 0; 09198 }
static int complete_dpreply | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5774 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_UNKNOWN, iax_ies::called_number, iax2_dpcache::callno, chan_iax2_pvt::dpentries, iax_ies::dpstatus, iax2_dpcache::expiry, expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax2_dpcache::orig, iax2_dpcache::peer, iax_ies::refresh, and iax2_dpcache::waiters.
Referenced by socket_process().
05775 { 05776 char exten[256] = ""; 05777 int status = CACHE_FLAG_UNKNOWN; 05778 int expiry = iaxdefaultdpcache; 05779 int x; 05780 int matchmore = 0; 05781 struct iax2_dpcache *dp, *prev; 05782 05783 if (ies->called_number) 05784 ast_copy_string(exten, ies->called_number, sizeof(exten)); 05785 05786 if (ies->dpstatus & IAX_DPSTATUS_EXISTS) 05787 status = CACHE_FLAG_EXISTS; 05788 else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST) 05789 status = CACHE_FLAG_CANEXIST; 05790 else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT) 05791 status = CACHE_FLAG_NONEXISTENT; 05792 05793 if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) { 05794 /* Don't really do anything with this */ 05795 } 05796 if (ies->refresh) 05797 expiry = ies->refresh; 05798 if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE) 05799 matchmore = CACHE_FLAG_MATCHMORE; 05800 ast_mutex_lock(&dpcache_lock); 05801 prev = NULL; 05802 dp = pvt->dpentries; 05803 while(dp) { 05804 if (!strcmp(dp->exten, exten)) { 05805 /* Let them go */ 05806 if (prev) 05807 prev->peer = dp->peer; 05808 else 05809 pvt->dpentries = dp->peer; 05810 dp->peer = NULL; 05811 dp->callno = 0; 05812 dp->expiry.tv_sec = dp->orig.tv_sec + expiry; 05813 if (dp->flags & CACHE_FLAG_PENDING) { 05814 dp->flags &= ~CACHE_FLAG_PENDING; 05815 dp->flags |= status; 05816 dp->flags |= matchmore; 05817 } 05818 /* Wake up waiters */ 05819 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 05820 if (dp->waiters[x] > -1) 05821 write(dp->waiters[x], "asdf", 4); 05822 } 05823 prev = dp; 05824 dp = dp->peer; 05825 } 05826 ast_mutex_unlock(&dpcache_lock); 05827 return 0; 05828 }
static char* complete_iax2_show_peer | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 2392 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_strdup, peer_unref(), and peers.
02393 { 02394 int which = 0; 02395 struct iax2_peer *peer; 02396 char *res = NULL; 02397 int wordlen = strlen(word); 02398 struct ao2_iterator i; 02399 02400 /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */ 02401 if (pos != 3) 02402 return NULL; 02403 02404 i = ao2_iterator_init(peers, 0); 02405 while ((peer = ao2_iterator_next(&i))) { 02406 if (!strncasecmp(peer->name, word, wordlen) && ++which > state) { 02407 res = ast_strdup(peer->name); 02408 peer_unref(peer); 02409 break; 02410 } 02411 peer_unref(peer); 02412 } 02413 02414 return res; 02415 }
static int complete_transfer | ( | int | callno, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5830 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, iax_ies::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), iaxq, iaxs, chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, store_by_peercallno(), chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, TRANSFER_NONE, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, chan_iax2_pvt::videoformat, and chan_iax2_pvt::voiceformat.
Referenced by socket_process().
05831 { 05832 int peercallno = 0; 05833 struct chan_iax2_pvt *pvt = iaxs[callno]; 05834 struct iax_frame *cur; 05835 jb_frame frame; 05836 05837 if (ies->callno) 05838 peercallno = ies->callno; 05839 05840 if (peercallno < 1) { 05841 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05842 return -1; 05843 } 05844 memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr)); 05845 memset(&pvt->transfer, 0, sizeof(pvt->transfer)); 05846 /* Reset sequence numbers */ 05847 pvt->oseqno = 0; 05848 pvt->rseqno = 0; 05849 pvt->iseqno = 0; 05850 pvt->aseqno = 0; 05851 05852 if (pvt->peercallno) { 05853 remove_by_peercallno(pvt); 05854 } 05855 pvt->peercallno = peercallno; 05856 store_by_peercallno(pvt); 05857 05858 pvt->transferring = TRANSFER_NONE; 05859 pvt->svoiceformat = -1; 05860 pvt->voiceformat = 0; 05861 pvt->svideoformat = -1; 05862 pvt->videoformat = 0; 05863 pvt->transfercallno = -1; 05864 memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); 05865 memset(&pvt->offset, 0, sizeof(pvt->offset)); 05866 /* reset jitterbuffer */ 05867 while(jb_getall(pvt->jb,&frame) == JB_OK) 05868 iax2_frame_free(frame.data); 05869 jb_reset(pvt->jb); 05870 pvt->lag = 0; 05871 pvt->last = 0; 05872 pvt->lastsent = 0; 05873 pvt->nextpred = 0; 05874 pvt->pingtime = DEFAULT_RETRY_TIME; 05875 AST_LIST_LOCK(&iaxq.queue); 05876 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 05877 /* We must cancel any packets that would have been transmitted 05878 because now we're talking to someone new. It's okay, they 05879 were transmitted to someone that didn't care anyway. */ 05880 if (callno == cur->callno) 05881 cur->retries = -1; 05882 } 05883 AST_LIST_UNLOCK(&iaxq.queue); 05884 return 0; 05885 }
static unsigned char compress_subclass | ( | int | subclass | ) | [static] |
Definition at line 1064 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().
01065 { 01066 int x; 01067 int power=-1; 01068 /* If it's 128 or smaller, just return it */ 01069 if (subclass < IAX_FLAG_SC_LOG) 01070 return subclass; 01071 /* Otherwise find its power */ 01072 for (x = 0; x < IAX_MAX_SHIFT; x++) { 01073 if (subclass & (1 << x)) { 01074 if (power > -1) { 01075 ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass); 01076 return 0; 01077 } else 01078 power = x; 01079 } 01080 } 01081 return power | IAX_FLAG_SC_LOG; 01082 }
static void construct_rr | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ie_data * | iep | |||
) | [static] |
Definition at line 6784 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().
06785 { 06786 jb_info stats; 06787 jb_getinfo(pvt->jb, &stats); 06788 06789 memset(iep, 0, sizeof(*iep)); 06790 06791 iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter); 06792 if(stats.frames_in == 0) stats.frames_in = 1; 06793 iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff))); 06794 iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in); 06795 iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min); 06796 iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped); 06797 iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo); 06798 }
static int create_addr | ( | const char * | peername, | |
struct ast_channel * | c, | |||
struct sockaddr_in * | sin, | |||
struct create_addr_info * | cai | |||
) | [static] |
Definition at line 3009 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_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_DEBUG, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, create_addr_info::outkey, peer_unref(), create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.
03010 { 03011 struct ast_hostent ahp; 03012 struct hostent *hp; 03013 struct iax2_peer *peer; 03014 int res = -1; 03015 struct ast_codec_pref ourprefs; 03016 03017 ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); 03018 cai->sockfd = defaultsockfd; 03019 cai->maxtime = 0; 03020 sin->sin_family = AF_INET; 03021 03022 if (!(peer = find_peer(peername, 1))) { 03023 cai->found = 0; 03024 03025 hp = ast_gethostbyname(peername, &ahp); 03026 if (hp) { 03027 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 03028 sin->sin_port = htons(IAX_DEFAULT_PORTNO); 03029 /* use global iax prefs for unknown peer/user */ 03030 /* But move the calling channel's native codec to the top of the preference list */ 03031 memcpy(&ourprefs, &prefs, sizeof(ourprefs)); 03032 if (c) 03033 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03034 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03035 return 0; 03036 } else { 03037 ast_log(LOG_WARNING, "No such host: %s\n", peername); 03038 return -1; 03039 } 03040 } 03041 03042 cai->found = 1; 03043 03044 /* if the peer has no address (current or default), return failure */ 03045 if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) 03046 goto return_unref; 03047 03048 /* if the peer is being monitored and is currently unreachable, return failure */ 03049 if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) 03050 goto return_unref; 03051 03052 ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 03053 cai->maxtime = peer->maxms; 03054 cai->capability = peer->capability; 03055 cai->encmethods = peer->encmethods; 03056 cai->sockfd = peer->sockfd; 03057 cai->adsi = peer->adsi; 03058 memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); 03059 /* Move the calling channel's native codec to the top of the preference list */ 03060 if (c) { 03061 ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats); 03062 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03063 } 03064 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03065 ast_copy_string(cai->context, peer->context, sizeof(cai->context)); 03066 ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); 03067 ast_copy_string(cai->username, peer->username, sizeof(cai->username)); 03068 ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); 03069 ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); 03070 ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret)); 03071 ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest)); 03072 if (ast_strlen_zero(peer->dbsecret)) { 03073 ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); 03074 } else { 03075 char *family; 03076 char *key = NULL; 03077 03078 family = ast_strdupa(peer->dbsecret); 03079 key = strchr(family, '/'); 03080 if (key) 03081 *key++ = '\0'; 03082 if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { 03083 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); 03084 goto return_unref; 03085 } 03086 } 03087 03088 if (peer->addr.sin_addr.s_addr) { 03089 sin->sin_addr = peer->addr.sin_addr; 03090 sin->sin_port = peer->addr.sin_port; 03091 } else { 03092 sin->sin_addr = peer->defaddr.sin_addr; 03093 sin->sin_port = peer->defaddr.sin_port; 03094 } 03095 03096 res = 0; 03097 03098 return_unref: 03099 peer_unref(peer); 03100 03101 return res; 03102 }
static int decode_frame | ( | aes_decrypt_ctx * | dcx, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4159 of file chan_iax2.c.
References AST_FRAME_VIDEO, ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, ast_frame::frametype, IAX_FLAG_FULL, LOG_DEBUG, memcpy_decrypt(), option_debug, ast_iax2_full_hdr::scallno, ast_frame::subclass, ast_iax2_full_hdr::type, and uncompress_subclass().
Referenced by decrypt_frame().
04160 { 04161 int padding; 04162 unsigned char *workspace; 04163 04164 workspace = alloca(*datalen); 04165 memset(f, 0, sizeof(*f)); 04166 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04167 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04168 if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr)) 04169 return -1; 04170 /* Decrypt */ 04171 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx); 04172 04173 padding = 16 + (workspace[15] & 0xf); 04174 if (option_debug && iaxdebug) 04175 ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]); 04176 if (*datalen < padding + sizeof(struct ast_iax2_full_hdr)) 04177 return -1; 04178 04179 *datalen -= padding; 04180 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04181 f->frametype = fh->type; 04182 if (f->frametype == AST_FRAME_VIDEO) { 04183 f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 04184 } else { 04185 f->subclass = uncompress_subclass(fh->csub); 04186 } 04187 } else { 04188 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04189 if (option_debug && iaxdebug) 04190 ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen); 04191 if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr)) 04192 return -1; 04193 /* Decrypt */ 04194 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx); 04195 padding = 16 + (workspace[15] & 0x0f); 04196 if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr)) 04197 return -1; 04198 *datalen -= padding; 04199 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04200 } 04201 return 0; 04202 }
static int decrypt_frame | ( | int | callno, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4245 of file chan_iax2.c.
References ast_set_flag, ast_strdupa, ast_test_flag, build_enc_keys(), decode_frame(), IAX_KEYPOPULATED, iaxs, MD5Final(), MD5Init(), MD5Update(), iax2_registry::secret, and strsep().
Referenced by socket_process().
04246 { 04247 int res=-1; 04248 if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) { 04249 /* Search for possible keys, given secrets */ 04250 struct MD5Context md5; 04251 unsigned char digest[16]; 04252 char *tmppw, *stringp; 04253 04254 tmppw = ast_strdupa(iaxs[callno]->secret); 04255 stringp = tmppw; 04256 while ((tmppw = strsep(&stringp, ";"))) { 04257 MD5Init(&md5); 04258 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 04259 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 04260 MD5Final(digest, &md5); 04261 build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx); 04262 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04263 if (!res) { 04264 ast_set_flag(iaxs[callno], IAX_KEYPOPULATED); 04265 break; 04266 } 04267 } 04268 } else 04269 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04270 return res; 04271 }
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 6846 of file chan_iax2.c.
References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), and ast_iax2_full_hdr::oseqno.
Referenced by socket_read().
06847 { 06848 struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf; 06849 struct ast_iax2_full_hdr *fh, *cur_fh; 06850 06851 if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len))) 06852 return; 06853 06854 pkt_buf->len = from_here->buf_len; 06855 memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len); 06856 06857 fh = (struct ast_iax2_full_hdr *) pkt_buf->buf; 06858 ast_mutex_lock(&to_here->lock); 06859 AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) { 06860 cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf; 06861 if (fh->oseqno < cur_fh->oseqno) { 06862 AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry); 06863 break; 06864 } 06865 } 06866 AST_LIST_TRAVERSE_SAFE_END 06867 06868 if (!cur_pkt_buf) 06869 AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry); 06870 06871 ast_mutex_unlock(&to_here->lock); 06872 }
static void delete_users | ( | void | ) | [static] |
Definition at line 9769 of file chan_iax2.c.
References ao2_callback(), ast_dnsmgr_release(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, free, iax2_destroy(), iaxs, iaxsl, peer_delme_cb(), peers, chan_iax2_pvt::reg, user_delme_cb(), and users.
09770 { 09771 struct iax2_registry *reg; 09772 09773 ao2_callback(users, 0, user_delme_cb, NULL); 09774 09775 AST_LIST_LOCK(®istrations); 09776 while ((reg = AST_LIST_REMOVE_HEAD(®istrations, entry))) { 09777 ast_sched_del(sched, reg->expire); 09778 if (reg->callno) { 09779 ast_mutex_lock(&iaxsl[reg->callno]); 09780 if (iaxs[reg->callno]) { 09781 iaxs[reg->callno]->reg = NULL; 09782 iax2_destroy(reg->callno); 09783 } 09784 ast_mutex_unlock(&iaxsl[reg->callno]); 09785 } 09786 if (reg->dnsmgr) 09787 ast_dnsmgr_release(reg->dnsmgr); 09788 free(reg); 09789 } 09790 AST_LIST_UNLOCK(®istrations); 09791 09792 ao2_callback(peers, 0, peer_delme_cb, NULL); 09793 }
static void destroy_firmware | ( | struct iax_firmware * | cur | ) | [static] |
Definition at line 1743 of file chan_iax2.c.
References ast_iax2_firmware_header::datalen, iax_firmware::fd, free, and iax_firmware::fwh.
Referenced by reload_firmware().
01744 { 01745 /* Close firmware */ 01746 if (cur->fwh) { 01747 munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh))); 01748 } 01749 close(cur->fd); 01750 free(cur); 01751 }
static void dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid, | |||
int | skiplock | |||
) | [static] |
Definition at line 6618 of file chan_iax2.c.
References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_IAX, ast_ignore_pattern(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), iax_ie_data::buf, IAX_COMMAND_DPREP, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_NUMBER, IAX_IE_DPSTATUS, IAX_IE_REFRESH, iaxs, iaxsl, iax_ie_data::pos, and send_command().
Referenced by dp_lookup_thread(), and socket_process().
06619 { 06620 unsigned short dpstatus = 0; 06621 struct iax_ie_data ied1; 06622 int mm; 06623 06624 memset(&ied1, 0, sizeof(ied1)); 06625 mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); 06626 /* Must be started */ 06627 if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) { 06628 dpstatus = IAX_DPSTATUS_EXISTS; 06629 } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { 06630 dpstatus = IAX_DPSTATUS_CANEXIST; 06631 } else { 06632 dpstatus = IAX_DPSTATUS_NONEXISTENT; 06633 } 06634 if (ast_ignore_pattern(context, callednum)) 06635 dpstatus |= IAX_DPSTATUS_IGNOREPAT; 06636 if (mm) 06637 dpstatus |= IAX_DPSTATUS_MATCHMORE; 06638 if (!skiplock) 06639 ast_mutex_lock(&iaxsl[callno]); 06640 if (iaxs[callno]) { 06641 iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); 06642 iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); 06643 iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); 06644 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); 06645 } 06646 if (!skiplock) 06647 ast_mutex_unlock(&iaxsl[callno]); 06648 }
static void* dp_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 6650 of file chan_iax2.c.
References dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup(), and free.
Referenced by spawn_dp_lookup().
06651 { 06652 /* Look up for dpreq */ 06653 struct dpreq_data *dpr = data; 06654 dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0); 06655 if (dpr->callerid) 06656 free(dpr->callerid); 06657 free(dpr); 06658 return NULL; 06659 }
static int encrypt_frame | ( | aes_encrypt_ctx * | ecx, | |
struct ast_iax2_full_hdr * | fh, | |||
unsigned char * | poo, | |||
int * | datalen | |||
) | [static] |
Definition at line 4204 of file chan_iax2.c.
References ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, LOG_DEBUG, memcpy_encrypt(), option_debug, ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.
Referenced by iax2_send().
04205 { 04206 int padding; 04207 unsigned char *workspace; 04208 workspace = alloca(*datalen + 32); 04209 if (!workspace) 04210 return -1; 04211 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04212 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04213 if (option_debug && iaxdebug) 04214 ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen); 04215 padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16); 04216 padding = 16 + (padding & 0xf); 04217 memcpy(workspace, poo, padding); 04218 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04219 workspace[15] &= 0xf0; 04220 workspace[15] |= (padding & 0xf); 04221 if (option_debug && iaxdebug) 04222 ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]); 04223 *datalen += padding; 04224 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx); 04225 if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr)) 04226 memcpy(poo, workspace + *datalen - 32, 32); 04227 } else { 04228 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04229 if (option_debug && iaxdebug) 04230 ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen); 04231 padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16); 04232 padding = 16 + (padding & 0xf); 04233 memcpy(workspace, poo, padding); 04234 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04235 workspace[15] &= 0xf0; 04236 workspace[15] |= (padding & 0x0f); 04237 *datalen += padding; 04238 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx); 04239 if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr)) 04240 memcpy(poo, workspace + *datalen - 32, 32); 04241 } 04242 return 0; 04243 }
static int expire_registry | ( | const void * | data | ) | [static] |
Definition at line 6067 of file chan_iax2.c.
References __expire_registry(), and schedule_action.
Referenced by iax2_prune_realtime(), realtime_peer(), reg_source_db(), and update_registry().
06068 { 06069 #ifdef SCHED_MULTITHREADED 06070 if (schedule_action(__expire_registry, data)) 06071 #endif 06072 __expire_registry(data); 06073 return 0; 06074 }
static struct iax2_dpcache* find_cache | ( | struct ast_channel * | chan, | |
const char * | data, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) | [static, read] |
Definition at line 10327 of file chan_iax2.c.
References ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, iax2_registry::callno, dpcache, chan_iax2_pvt::dpentries, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, free, iax2_dprequest(), IAX_STATE_STARTED, iaxs, iaxsl, LOG_WARNING, iax2_dpcache::next, iax2_dpcache::orig, iax2_dpcache::peer, iax2_dpcache::peercontext, and iax2_dpcache::waiters.
Referenced by iax2_canmatch(), iax2_exec(), iax2_exists(), and iax2_matchmore().
10328 { 10329 struct iax2_dpcache *dp, *prev = NULL, *next; 10330 struct timeval tv; 10331 int x; 10332 int com[2]; 10333 int timeout; 10334 int old=0; 10335 int outfd; 10336 int abort; 10337 int callno; 10338 struct ast_channel *c; 10339 struct ast_frame *f; 10340 gettimeofday(&tv, NULL); 10341 dp = dpcache; 10342 while(dp) { 10343 next = dp->next; 10344 /* Expire old caches */ 10345 if (ast_tvcmp(tv, dp->expiry) > 0) { 10346 /* It's expired, let it disappear */ 10347 if (prev) 10348 prev->next = dp->next; 10349 else 10350 dpcache = dp->next; 10351 if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) { 10352 /* Free memory and go again */ 10353 free(dp); 10354 } else { 10355 ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = %p callno = %d)\n", dp->flags, dp->peer, dp->callno); 10356 } 10357 dp = next; 10358 continue; 10359 } 10360 /* We found an entry that matches us! */ 10361 if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 10362 break; 10363 prev = dp; 10364 dp = next; 10365 } 10366 if (!dp) { 10367 /* No matching entry. Create a new one. */ 10368 /* First, can we make a callno? */ 10369 callno = cache_get_callno_locked(data); 10370 if (callno < 0) { 10371 ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data); 10372 return NULL; 10373 } 10374 if (!(dp = ast_calloc(1, sizeof(*dp)))) { 10375 ast_mutex_unlock(&iaxsl[callno]); 10376 return NULL; 10377 } 10378 ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext)); 10379 ast_copy_string(dp->exten, exten, sizeof(dp->exten)); 10380 gettimeofday(&dp->expiry, NULL); 10381 dp->orig = dp->expiry; 10382 /* Expires in 30 mins by default */ 10383 dp->expiry.tv_sec += iaxdefaultdpcache; 10384 dp->next = dpcache; 10385 dp->flags = CACHE_FLAG_PENDING; 10386 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 10387 dp->waiters[x] = -1; 10388 dpcache = dp; 10389 dp->peer = iaxs[callno]->dpentries; 10390 iaxs[callno]->dpentries = dp; 10391 /* Send the request if we're already up */ 10392 if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 10393 iax2_dprequest(dp, callno); 10394 ast_mutex_unlock(&iaxsl[callno]); 10395 } 10396 /* By here we must have a dp */ 10397 if (dp->flags & CACHE_FLAG_PENDING) { 10398 /* Okay, here it starts to get nasty. We need a pipe now to wait 10399 for a reply to come back so long as it's pending */ 10400 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) { 10401 /* Find an empty slot */ 10402 if (dp->waiters[x] < 0) 10403 break; 10404 } 10405 if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) { 10406 ast_log(LOG_WARNING, "No more waiter positions available\n"); 10407 return NULL; 10408 } 10409 if (pipe(com)) { 10410 ast_log(LOG_WARNING, "Unable to create pipe for comm\n"); 10411 return NULL; 10412 } 10413 dp->waiters[x] = com[1]; 10414 /* Okay, now we wait */ 10415 timeout = iaxdefaulttimeout * 1000; 10416 /* Temporarily unlock */ 10417 ast_mutex_unlock(&dpcache_lock); 10418 /* Defer any dtmf */ 10419 if (chan) 10420 old = ast_channel_defer_dtmf(chan); 10421 abort = 0; 10422 while(timeout) { 10423 c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout); 10424 if (outfd > -1) { 10425 break; 10426 } 10427 if (c) { 10428 f = ast_read(c); 10429 if (f) 10430 ast_frfree(f); 10431 else { 10432 /* Got hung up on, abort! */ 10433 break; 10434 abort = 1; 10435 } 10436 } 10437 } 10438 if (!timeout) { 10439 ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten); 10440 } 10441 ast_mutex_lock(&dpcache_lock); 10442 dp->waiters[x] = -1; 10443 close(com[1]); 10444 close(com[0]); 10445 if (abort) { 10446 /* Don't interpret anything, just abort. Not sure what th epoint 10447 of undeferring dtmf on a hung up channel is but hey whatever */ 10448 if (!old && chan) 10449 ast_channel_undefer_dtmf(chan); 10450 return NULL; 10451 } 10452 if (!(dp->flags & CACHE_FLAG_TIMEOUT)) { 10453 /* Now to do non-independent analysis the results of our wait */ 10454 if (dp->flags & CACHE_FLAG_PENDING) { 10455 /* Still pending... It's a timeout. Wake everybody up. Consider it no longer 10456 pending. Don't let it take as long to timeout. */ 10457 dp->flags &= ~CACHE_FLAG_PENDING; 10458 dp->flags |= CACHE_FLAG_TIMEOUT; 10459 /* Expire after only 60 seconds now. This is designed to help reduce backlog in heavily loaded 10460 systems without leaving it unavailable once the server comes back online */ 10461 dp->expiry.tv_sec = dp->orig.tv_sec + 60; 10462 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 10463 if (dp->waiters[x] > -1) 10464 write(dp->waiters[x], "asdf", 4); 10465 } 10466 } 10467 /* Our caller will obtain the rest */ 10468 if (!old && chan) 10469 ast_channel_undefer_dtmf(chan); 10470 } 10471 return dp; 10472 }
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 1643 of file chan_iax2.c.
References __find_callno().
Referenced by iax2_poke_peer(), and socket_process().
01643 { 01644 01645 return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame); 01646 }
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 1648 of file chan_iax2.c.
References __find_callno().
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_provision(), iax2_request(), and socket_process().
01648 { 01649 01650 return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame); 01651 }
static struct iax2_thread* find_idle_thread | ( | void | ) | [static, read] |
Definition at line 909 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_init(), ast_pthread_create, iax2_thread::ffinfo, free, iax2_process_thread(), IAX_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxmaxthreadcount, and thread.
Referenced by __schedule_action(), and socket_read().
00910 { 00911 pthread_attr_t attr; 00912 struct iax2_thread *thread = NULL; 00913 00914 /* Pop the head of the list off */ 00915 AST_LIST_LOCK(&idle_list); 00916 thread = AST_LIST_REMOVE_HEAD(&idle_list, list); 00917 AST_LIST_UNLOCK(&idle_list); 00918 00919 /* If no idle thread is available from the regular list, try dynamic */ 00920 if (thread == NULL) { 00921 AST_LIST_LOCK(&dynamic_list); 00922 thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list); 00923 /* Make sure we absolutely have a thread... if not, try to make one if allowed */ 00924 if (thread == NULL && iaxmaxthreadcount > iaxdynamicthreadcount) { 00925 /* We need to MAKE a thread! */ 00926 if ((thread = ast_calloc(1, sizeof(*thread)))) { 00927 thread->threadnum = iaxdynamicthreadcount; 00928 thread->type = IAX_TYPE_DYNAMIC; 00929 ast_mutex_init(&thread->lock); 00930 ast_cond_init(&thread->cond, NULL); 00931 pthread_attr_init(&attr); 00932 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00933 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 00934 free(thread); 00935 thread = NULL; 00936 } else { 00937 /* All went well and the thread is up, so increment our count */ 00938 iaxdynamicthreadcount++; 00939 00940 /* Wait for the thread to be ready before returning it to the caller */ 00941 while (!thread->ready_for_signal) 00942 usleep(1); 00943 } 00944 } 00945 } 00946 AST_LIST_UNLOCK(&dynamic_list); 00947 } 00948 00949 /* this thread is not processing a full frame (since it is idle), 00950 so ensure that the field for the full frame call number is empty */ 00951 if (thread) 00952 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 00953 00954 return thread; 00955 }
static struct iax2_peer* find_peer | ( | const char * | name, | |
int | realtime | |||
) | [static, read] |
Definition at line 1142 of file chan_iax2.c.
References ao2_find(), peers, and realtime_peer().
01143 { 01144 struct iax2_peer *peer = NULL; 01145 struct iax2_peer tmp_peer = { 01146 .name = name, 01147 }; 01148 01149 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 01150 01151 /* Now go for realtime if applicable */ 01152 if(!peer && realtime) 01153 peer = realtime_peer(name, NULL); 01154 01155 return peer; 01156 }
static struct iax2_trunk_peer* find_tpeer | ( | struct sockaddr_in * | sin, | |
int | fd | |||
) | [static, read] |
Definition at line 4013 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_calloc, ast_inet_ntoa(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), inaddrcmp(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lock, LOG_DEBUG, iax2_trunk_peer::next, option_debug, iax2_trunk_peer::sockfd, tpeers, and iax2_trunk_peer::trunkact.
Referenced by iax2_trunk_queue(), and socket_process().
04014 { 04015 struct iax2_trunk_peer *tpeer; 04016 04017 /* Finds and locks trunk peer */ 04018 ast_mutex_lock(&tpeerlock); 04019 for (tpeer = tpeers; tpeer; tpeer = tpeer->next) { 04020 /* We don't lock here because tpeer->addr *never* changes */ 04021 if (!inaddrcmp(&tpeer->addr, sin)) { 04022 ast_mutex_lock(&tpeer->lock); 04023 break; 04024 } 04025 } 04026 if (!tpeer) { 04027 if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) { 04028 ast_mutex_init(&tpeer->lock); 04029 tpeer->lastsent = 9999; 04030 memcpy(&tpeer->addr, sin, sizeof(tpeer->addr)); 04031 tpeer->trunkact = ast_tvnow(); 04032 ast_mutex_lock(&tpeer->lock); 04033 tpeer->next = tpeers; 04034 tpeer->sockfd = fd; 04035 tpeers = tpeer; 04036 #ifdef SO_NO_CHECK 04037 setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 04038 #endif 04039 if (option_debug) 04040 ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 04041 } 04042 } 04043 ast_mutex_unlock(&tpeerlock); 04044 return tpeer; 04045 }
static unsigned int fix_peerts | ( | struct timeval * | tv, | |
int | callno, | |||
unsigned int | ts | |||
) | [static] |
Definition at line 3829 of file chan_iax2.c.
References iaxs, and chan_iax2_pvt::rxcore.
Referenced by socket_process().
03830 { 03831 long ms; /* NOT unsigned */ 03832 if (ast_tvzero(iaxs[callno]->rxcore)) { 03833 /* Initialize rxcore time if appropriate */ 03834 gettimeofday(&iaxs[callno]->rxcore, NULL); 03835 /* Round to nearest 20ms so traces look pretty */ 03836 iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000; 03837 } 03838 /* Calculate difference between trunk and channel */ 03839 ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore); 03840 /* Return as the sum of trunk time and the difference between trunk and real time */ 03841 return ms + ts; 03842 }
static void free_context | ( | struct iax2_context * | con | ) | [static] |
Definition at line 8936 of file chan_iax2.c.
References free, and iax2_context::next.
Referenced by build_user(), and user_destructor().
08937 { 08938 struct iax2_context *conl; 08939 while(con) { 08940 conl = con; 08941 con = con->next; 08942 free(conl); 08943 } 08944 }
static int function_iaxpeer | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 10596 of file chan_iax2.c.
References iax2_peer::addr, iax2_registry::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_registry::callno, iax2_peer::capability, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iaxs, peer_status(), peer_unref(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
10597 { 10598 struct iax2_peer *peer; 10599 char *peername, *colname; 10600 10601 peername = ast_strdupa(data); 10602 10603 /* if our channel, return the IP address of the endpoint of current channel */ 10604 if (!strcmp(peername,"CURRENTCHANNEL")) { 10605 unsigned short callno; 10606 if (chan->tech != &iax2_tech) 10607 return -1; 10608 callno = PTR_TO_CALLNO(chan->tech_pvt); 10609 ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len); 10610 return 0; 10611 } 10612 10613 if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */ 10614 *colname++ = '\0'; 10615 else if ((colname = strchr(peername, '|'))) 10616 *colname++ = '\0'; 10617 else 10618 colname = "ip"; 10619 10620 if (!(peer = find_peer(peername, 1))) 10621 return -1; 10622 10623 if (!strcasecmp(colname, "ip")) { 10624 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 10625 } else if (!strcasecmp(colname, "status")) { 10626 peer_status(peer, buf, len); 10627 } else if (!strcasecmp(colname, "mailbox")) { 10628 ast_copy_string(buf, peer->mailbox, len); 10629 } else if (!strcasecmp(colname, "context")) { 10630 ast_copy_string(buf, peer->context, len); 10631 } else if (!strcasecmp(colname, "expire")) { 10632 snprintf(buf, len, "%d", peer->expire); 10633 } else if (!strcasecmp(colname, "dynamic")) { 10634 ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len); 10635 } else if (!strcasecmp(colname, "callerid_name")) { 10636 ast_copy_string(buf, peer->cid_name, len); 10637 } else if (!strcasecmp(colname, "callerid_num")) { 10638 ast_copy_string(buf, peer->cid_num, len); 10639 } else if (!strcasecmp(colname, "codecs")) { 10640 ast_getformatname_multiple(buf, len -1, peer->capability); 10641 } else if (!strncasecmp(colname, "codec[", 6)) { 10642 char *codecnum, *ptr; 10643 int index = 0, codec = 0; 10644 10645 codecnum = strchr(colname, '['); 10646 *codecnum = '\0'; 10647 codecnum++; 10648 if ((ptr = strchr(codecnum, ']'))) { 10649 *ptr = '\0'; 10650 } 10651 index = atoi(codecnum); 10652 if((codec = ast_codec_pref_index(&peer->prefs, index))) { 10653 ast_copy_string(buf, ast_getformatname(codec), len); 10654 } 10655 } 10656 10657 peer_unref(peer); 10658 10659 return 0; 10660 }
static int get_auth_methods | ( | char * | value | ) | [static] |
Definition at line 9161 of file chan_iax2.c.
References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.
Referenced by build_peer(), and build_user().
09162 { 09163 int methods = 0; 09164 if (strstr(value, "rsa")) 09165 methods |= IAX_AUTH_RSA; 09166 if (strstr(value, "md5")) 09167 methods |= IAX_AUTH_MD5; 09168 if (strstr(value, "plaintext")) 09169 methods |= IAX_AUTH_PLAINTEXT; 09170 return methods; 09171 }
static int get_encrypt_methods | ( | const char * | s | ) | [static] |
Definition at line 1024 of file chan_iax2.c.
References ast_true(), and IAX_ENCRYPT_AES128.
Referenced by build_peer(), build_user(), and set_config().
01025 { 01026 int e; 01027 if (!strcasecmp(s, "aes128")) 01028 e = IAX_ENCRYPT_AES128; 01029 else if (ast_true(s)) 01030 e = IAX_ENCRYPT_AES128; 01031 else 01032 e = 0; 01033 return e; 01034 }
static int get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 2623 of file chan_iax2.c.
References __get_from_jb(), and schedule_action.
Referenced by update_jbsched().
02624 { 02625 #ifdef SCHED_MULTITHREADED 02626 if (schedule_action(__get_from_jb, data)) 02627 #endif 02628 __get_from_jb(data); 02629 return 0; 02630 }
static void handle_deferred_full_frames | ( | struct iax2_thread * | thread | ) | [static] |
Handle any deferred full frames for this thread.
Definition at line 6816 of file chan_iax2.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), and socket_process().
Referenced by iax2_process_thread().
06817 { 06818 struct iax2_pkt_buf *pkt_buf; 06819 06820 ast_mutex_lock(&thread->lock); 06821 06822 while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) { 06823 ast_mutex_unlock(&thread->lock); 06824 06825 thread->buf = pkt_buf->buf; 06826 thread->buf_len = pkt_buf->len; 06827 thread->buf_size = pkt_buf->len + 1; 06828 06829 socket_process(thread); 06830 06831 thread->buf = NULL; 06832 ast_free(pkt_buf); 06833 06834 ast_mutex_lock(&thread->lock); 06835 } 06836 06837 ast_mutex_unlock(&thread->lock); 06838 }
static int handle_error | ( | void | ) | [static] |
Definition at line 2031 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().
02032 { 02033 /* XXX Ideally we should figure out why an error occured and then abort those 02034 rather than continuing to try. Unfortunately, the published interface does 02035 not seem to work XXX */ 02036 #if 0 02037 struct sockaddr_in *sin; 02038 int res; 02039 struct msghdr m; 02040 struct sock_extended_err e; 02041 m.msg_name = NULL; 02042 m.msg_namelen = 0; 02043 m.msg_iov = NULL; 02044 m.msg_control = &e; 02045 m.msg_controllen = sizeof(e); 02046 m.msg_flags = 0; 02047 res = recvmsg(netsocket, &m, MSG_ERRQUEUE); 02048 if (res < 0) 02049 ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno)); 02050 else { 02051 if (m.msg_controllen) { 02052 sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e); 02053 if (sin) 02054 ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr)); 02055 else 02056 ast_log(LOG_WARNING, "No address detected??\n"); 02057 } else { 02058 ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno)); 02059 } 02060 } 02061 #endif 02062 return 0; 02063 }
static int iax2_ack_registry | ( | struct iax_ies * | ies, | |
struct sockaddr_in * | sin, | |||
int | callno | |||
) | [static] |
Acknowledgment received for OUR registration.
Definition at line 5888 of file chan_iax2.c.
References iax2_registry::addr, iax_ies::apparent_addr, ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), iax_ies::calling_number, EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_add(), iaxs, inaddrcmp(), LOG_WARNING, manager_event(), iax2_registry::messages, iax_ies::msgcount, option_verbose, iax_ies::refresh, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGISTERED, iax2_registry::regstate, iax2_registry::us, iax_ies::username, and VERBOSE_PREFIX_3.
Referenced by socket_process().
05889 { 05890 struct iax2_registry *reg; 05891 /* Start pessimistic */ 05892 char peer[256] = ""; 05893 char msgstatus[60]; 05894 int refresh = 60; 05895 char ourip[256] = "<Unspecified>"; 05896 struct sockaddr_in oldus; 05897 struct sockaddr_in us; 05898 int oldmsgs; 05899 05900 memset(&us, 0, sizeof(us)); 05901 if (ies->apparent_addr) 05902 bcopy(ies->apparent_addr, &us, sizeof(us)); 05903 if (ies->username) 05904 ast_copy_string(peer, ies->username, sizeof(peer)); 05905 if (ies->refresh) 05906 refresh = ies->refresh; 05907 if (ies->calling_number) { 05908 /* We don't do anything with it really, but maybe we should */ 05909 } 05910 reg = iaxs[callno]->reg; 05911 if (!reg) { 05912 ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer); 05913 return -1; 05914 } 05915 memcpy(&oldus, ®->us, sizeof(oldus)); 05916 oldmsgs = reg->messages; 05917 if (inaddrcmp(®->addr, sin)) { 05918 ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 05919 return -1; 05920 } 05921 memcpy(®->us, &us, sizeof(reg->us)); 05922 if (ies->msgcount >= 0) 05923 reg->messages = ies->msgcount & 0xffff; /* only low 16 bits are used in the transmission of the IE */ 05924 /* always refresh the registration at the interval requested by the server 05925 we are registering to 05926 */ 05927 reg->refresh = refresh; 05928 AST_SCHED_DEL(sched, reg->expire); 05929 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 05930 if (inaddrcmp(&oldus, ®->us) || (reg->messages != oldmsgs)) { 05931 if (option_verbose > 2) { 05932 if (reg->messages > 255) 05933 snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8); 05934 else if (reg->messages > 1) 05935 snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages); 05936 else if (reg->messages > 0) 05937 snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n"); 05938 else 05939 snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n"); 05940 snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 05941 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); 05942 } 05943 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); 05944 } 05945 reg->regstate = REG_STATE_REGISTERED; 05946 return 0; 05947 }
static int iax2_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3629 of file chan_iax2.c.
References AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_log(), iax2_registry::callno, LOG_DEBUG, option_debug, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03630 { 03631 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03632 if (option_debug) 03633 ast_log(LOG_DEBUG, "Answering IAX2 call\n"); 03634 return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); 03635 }
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 3479 of file chan_iax2.c.
References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_getformatname_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), AST_SOFTHANGUP_DEV, ast_test_flag, ast_verbose(), ast_waitfor_n(), ast_write(), chan_iax2_pvt::bridgecallno, f, ast_frame::frametype, iax2_start_transfer(), iax2_tech, IAX_LINGER_TIMEOUT, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, iaxs, iaxsl, lock_both(), LOG_WARNING, ast_channel::nativeformats, option_verbose, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, TRANSFER_RELEASED, tv, unlock_both(), and VERBOSE_PREFIX_3.
03480 { 03481 struct ast_channel *cs[3]; 03482 struct ast_channel *who, *other; 03483 int to = -1; 03484 int res = -1; 03485 int transferstarted=0; 03486 struct ast_frame *f; 03487 unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt); 03488 unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt); 03489 struct timeval waittimer = {0, 0}, tv; 03490 03491 lock_both(callno0, callno1); 03492 if (!iaxs[callno0] || !iaxs[callno1]) { 03493 unlock_both(callno0, callno1); 03494 return AST_BRIDGE_FAILED; 03495 } 03496 /* Put them in native bridge mode */ 03497 if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) { 03498 iaxs[callno0]->bridgecallno = callno1; 03499 iaxs[callno1]->bridgecallno = callno0; 03500 } 03501 unlock_both(callno0, callno1); 03502 03503 /* If not, try to bridge until we can execute a transfer, if we can */ 03504 cs[0] = c0; 03505 cs[1] = c1; 03506 for (/* ever */;;) { 03507 /* Check in case we got masqueraded into */ 03508 if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) { 03509 if (option_verbose > 2) 03510 ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n"); 03511 /* Remove from native mode */ 03512 if (c0->tech == &iax2_tech) { 03513 ast_mutex_lock(&iaxsl[callno0]); 03514 iaxs[callno0]->bridgecallno = 0; 03515 ast_mutex_unlock(&iaxsl[callno0]); 03516 } 03517 if (c1->tech == &iax2_tech) { 03518 ast_mutex_lock(&iaxsl[callno1]); 03519 iaxs[callno1]->bridgecallno = 0; 03520 ast_mutex_unlock(&iaxsl[callno1]); 03521 } 03522 return AST_BRIDGE_FAILED_NOWARN; 03523 } 03524 if (c0->nativeformats != c1->nativeformats) { 03525 if (option_verbose > 2) { 03526 char buf0[255]; 03527 char buf1[255]; 03528 ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats); 03529 ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats); 03530 ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1); 03531 } 03532 /* Remove from native mode */ 03533 lock_both(callno0, callno1); 03534 if (iaxs[callno0]) 03535 iaxs[callno0]->bridgecallno = 0; 03536 if (iaxs[callno1]) 03537 iaxs[callno1]->bridgecallno = 0; 03538 unlock_both(callno0, callno1); 03539 return AST_BRIDGE_FAILED_NOWARN; 03540 } 03541 /* check if transfered and if we really want native bridging */ 03542 if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) { 03543 /* Try the transfer */ 03544 if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) || 03545 ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA))) 03546 ast_log(LOG_WARNING, "Unable to start the transfer\n"); 03547 transferstarted = 1; 03548 } 03549 if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) { 03550 /* Call has been transferred. We're no longer involved */ 03551 gettimeofday(&tv, NULL); 03552 if (ast_tvzero(waittimer)) { 03553 waittimer = tv; 03554 } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { 03555 c0->_softhangup |= AST_SOFTHANGUP_DEV; 03556 c1->_softhangup |= AST_SOFTHANGUP_DEV; 03557 *fo = NULL; 03558 *rc = c0; 03559 res = AST_BRIDGE_COMPLETE; 03560 break; 03561 } 03562 } 03563 to = 1000; 03564 who = ast_waitfor_n(cs, 2, &to); 03565 if (timeoutms > -1) { 03566 timeoutms -= (1000 - to); 03567 if (timeoutms < 0) 03568 timeoutms = 0; 03569 } 03570 if (!who) { 03571 if (!timeoutms) { 03572 res = AST_BRIDGE_RETRY; 03573 break; 03574 } 03575 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03576 res = AST_BRIDGE_FAILED; 03577 break; 03578 } 03579 continue; 03580 } 03581 f = ast_read(who); 03582 if (!f) { 03583 *fo = NULL; 03584 *rc = who; 03585 res = AST_BRIDGE_COMPLETE; 03586 break; 03587 } 03588 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03589 *fo = f; 03590 *rc = who; 03591 res = AST_BRIDGE_COMPLETE; 03592 break; 03593 } 03594 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 03595 if ((f->frametype == AST_FRAME_VOICE) || 03596 (f->frametype == AST_FRAME_TEXT) || 03597 (f->frametype == AST_FRAME_VIDEO) || 03598 (f->frametype == AST_FRAME_IMAGE) || 03599 (f->frametype == AST_FRAME_DTMF)) { 03600 /* monitored dtmf take out of the bridge. 03601 * check if we monitor the specific source. 03602 */ 03603 int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1; 03604 if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) { 03605 *rc = who; 03606 *fo = f; 03607 res = AST_BRIDGE_COMPLETE; 03608 /* Remove from native mode */ 03609 break; 03610 } 03611 /* everything else goes to the other side */ 03612 ast_write(other, f); 03613 } 03614 ast_frfree(f); 03615 /* Swap who gets priority */ 03616 cs[2] = cs[0]; 03617 cs[0] = cs[1]; 03618 cs[1] = cs[2]; 03619 } 03620 lock_both(callno0, callno1); 03621 if(iaxs[callno0]) 03622 iaxs[callno0]->bridgecallno = 0; 03623 if(iaxs[callno1]) 03624 iaxs[callno1]->bridgecallno = 0; 03625 unlock_both(callno0, callno1); 03626 return res; 03627 }
static int iax2_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 3223 of file chan_iax2.c.
References ast_channel::_state, create_addr_info::adsi, chan_iax2_pvt::adsi, ast_channel::adsicpe, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PRES_NUMBER_NOT_AVAILABLE, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, auto_congest(), iax_ie_data::buf, iax2_registry::callno, CALLNO_TO_PTR, capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, create_addr_info::context, ast_channel::context, parsed_dial_string::context, create_addr(), chan_iax2_pvt::encmethods, create_addr_info::encmethods, parsed_dial_string::exten, iax2_datetime(), iax2_sched_add(), IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, IAX_SENDANI, iaxs, iaxsl, chan_iax2_pvt::initid, parsed_dial_string::key, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, parsed_dial_string::options, create_addr_info::outkey, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, create_addr_info::peercontext, chan_iax2_pvt::pingtime, parsed_dial_string::port, iax_ie_data::pos, create_addr_info::prefs, PTR_TO_CALLNO, iax2_registry::secret, create_addr_info::secret, send_command(), create_addr_info::sockfd, chan_iax2_pvt::sockfd, ast_channel::tech_pvt, create_addr_info::timezone, create_addr_info::username, and parsed_dial_string::username.
03224 { 03225 struct sockaddr_in sin; 03226 char *l=NULL, *n=NULL, *tmpstr; 03227 struct iax_ie_data ied; 03228 char *defaultrdest = "s"; 03229 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03230 struct parsed_dial_string pds; 03231 struct create_addr_info cai; 03232 03233 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 03234 ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); 03235 return -1; 03236 } 03237 03238 memset(&cai, 0, sizeof(cai)); 03239 cai.encmethods = iax2_encryption; 03240 03241 memset(&pds, 0, sizeof(pds)); 03242 tmpstr = ast_strdupa(dest); 03243 parse_dial_string(tmpstr, &pds); 03244 03245 if (ast_strlen_zero(pds.peer)) { 03246 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest); 03247 return -1; 03248 } 03249 03250 if (!pds.exten) { 03251 pds.exten = defaultrdest; 03252 } 03253 03254 if (create_addr(pds.peer, c, &sin, &cai)) { 03255 ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); 03256 return -1; 03257 } 03258 03259 if (!pds.username && !ast_strlen_zero(cai.username)) 03260 pds.username = cai.username; 03261 if (!pds.password && !ast_strlen_zero(cai.secret)) 03262 pds.password = cai.secret; 03263 if (!pds.key && !ast_strlen_zero(cai.outkey)) 03264 pds.key = cai.outkey; 03265 if (!pds.context && !ast_strlen_zero(cai.peercontext)) 03266 pds.context = cai.peercontext; 03267 03268 /* Keep track of the context for outgoing calls too */ 03269 ast_copy_string(c->context, cai.context, sizeof(c->context)); 03270 03271 if (pds.port) 03272 sin.sin_port = htons(atoi(pds.port)); 03273 03274 l = c->cid.cid_num; 03275 n = c->cid.cid_name; 03276 03277 /* Now build request */ 03278 memset(&ied, 0, sizeof(ied)); 03279 03280 /* On new call, first IE MUST be IAX version of caller */ 03281 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 03282 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); 03283 if (pds.options && strchr(pds.options, 'a')) { 03284 /* Request auto answer */ 03285 iax_ie_append(&ied, IAX_IE_AUTOANSWER); 03286 } 03287 03288 iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); 03289 03290 if (l) { 03291 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); 03292 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03293 } else { 03294 if (n) 03295 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03296 else 03297 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); 03298 } 03299 03300 iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); 03301 iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); 03302 03303 if (n) 03304 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); 03305 if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) 03306 iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); 03307 03308 if (!ast_strlen_zero(c->language)) 03309 iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); 03310 if (!ast_strlen_zero(c->cid.cid_dnid)) 03311 iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); 03312 if (!ast_strlen_zero(c->cid.cid_rdnis)) 03313 iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis); 03314 03315 if (pds.context) 03316 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); 03317 03318 if (pds.username) 03319 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 03320 03321 if (cai.encmethods) 03322 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); 03323 03324 ast_mutex_lock(&iaxsl[callno]); 03325 03326 if (!ast_strlen_zero(c->context)) 03327 ast_string_field_set(iaxs[callno], context, c->context); 03328 03329 if (pds.username) 03330 ast_string_field_set(iaxs[callno], username, pds.username); 03331 03332 iaxs[callno]->encmethods = cai.encmethods; 03333 03334 iaxs[callno]->adsi = cai.adsi; 03335 03336 ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret); 03337 ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest); 03338 03339 if (pds.key) 03340 ast_string_field_set(iaxs[callno], outkey, pds.key); 03341 if (pds.password) 03342 ast_string_field_set(iaxs[callno], secret, pds.password); 03343 03344 iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); 03345 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); 03346 iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); 03347 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); 03348 03349 if (iaxs[callno]->maxtime) { 03350 /* Initialize pingtime and auto-congest time */ 03351 iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; 03352 iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno)); 03353 } else if (autokill) { 03354 iaxs[callno]->pingtime = autokill / 2; 03355 iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); 03356 } 03357 03358 /* send the command using the appropriate socket for this peer */ 03359 iaxs[callno]->sockfd = cai.sockfd; 03360 03361 /* Transmit the string in a "NEW" request */ 03362 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 03363 03364 ast_mutex_unlock(&iaxsl[callno]); 03365 ast_setstate(c, AST_STATE_RINGING); 03366 03367 return 0; 03368 }
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 10498 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_CANEXIST, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
10499 { 10500 int res = 0; 10501 struct iax2_dpcache *dp; 10502 #if 0 10503 ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10504 #endif 10505 if ((priority != 1) && (priority != 2)) 10506 return 0; 10507 ast_mutex_lock(&dpcache_lock); 10508 dp = find_cache(chan, data, context, exten, priority); 10509 if (dp) { 10510 if (dp->flags & CACHE_FLAG_CANEXIST) 10511 res= 1; 10512 } 10513 ast_mutex_unlock(&dpcache_lock); 10514 if (!dp) { 10515 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10516 } 10517 return res; 10518 }
static unsigned int iax2_datetime | ( | const char * | tz | ) | [static] |
Definition at line 3126 of file chan_iax2.c.
References ast_localtime(), ast_strlen_zero(), and t.
Referenced by iax2_call(), and update_registry().
03127 { 03128 time_t t; 03129 struct tm tm; 03130 unsigned int tmp; 03131 time(&t); 03132 if (!ast_strlen_zero(tz)) 03133 ast_localtime(&t, &tm, tz); 03134 else 03135 ast_localtime(&t, &tm, NULL); 03136 tmp = (tm.tm_sec >> 1) & 0x1f; /* 5 bits of seconds */ 03137 tmp |= (tm.tm_min & 0x3f) << 5; /* 6 bits of minutes */ 03138 tmp |= (tm.tm_hour & 0x1f) << 11; /* 5 bits of hours */ 03139 tmp |= (tm.tm_mday & 0x1f) << 16; /* 5 bits of day of month */ 03140 tmp |= ((tm.tm_mon + 1) & 0xf) << 21; /* 4 bits of month */ 03141 tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */ 03142 return tmp; 03143 }
static void iax2_destroy | ( | int | callno | ) | [static] |
Definition at line 1282 of file chan_iax2.c.
References ao2_ref(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, lastused, ast_channel::lock, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), and update_max_trunk().
Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __unload_module(), delete_users(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), peer_destructor(), and socket_process().
01283 { 01284 struct chan_iax2_pvt *pvt; 01285 struct ast_channel *owner; 01286 01287 retry: 01288 pvt = iaxs[callno]; 01289 gettimeofday(&lastused[callno], NULL); 01290 01291 owner = pvt ? pvt->owner : NULL; 01292 01293 if (owner) { 01294 if (ast_mutex_trylock(&owner->lock)) { 01295 if (option_debug > 2) 01296 ast_log(LOG_DEBUG, "Avoiding IAX destroy deadlock\n"); 01297 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01298 goto retry; 01299 } 01300 } 01301 if (!owner) { 01302 iaxs[callno] = NULL; 01303 } 01304 01305 if (pvt) { 01306 if (!owner) { 01307 pvt->owner = NULL; 01308 } else { 01309 /* If there's an owner, prod it to give up */ 01310 /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup() 01311 * because we already hold the owner channel lock. */ 01312 ast_queue_hangup(owner); 01313 } 01314 01315 if (pvt->peercallno) { 01316 remove_by_peercallno(pvt); 01317 } 01318 01319 if (!owner) { 01320 ao2_ref(pvt, -1); 01321 pvt = NULL; 01322 } 01323 } 01324 01325 if (owner) { 01326 ast_mutex_unlock(&owner->lock); 01327 } 01328 01329 if (callno & 0x4000) { 01330 update_max_trunk(); 01331 } 01332 }
static void iax2_destroy_helper | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1212 of file chan_iax2.c.
References ao2_find(), ast_clear_flag, AST_SCHED_DEL, ast_test_flag, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, iax2_user::curauthreq, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, chan_iax2_pvt::pingid, user_unref(), and users.
Referenced by iax2_predestroy(), pvt_destructor(), and stop_stuff().
01213 { 01214 /* Decrement AUTHREQ count if needed */ 01215 if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) { 01216 struct iax2_user *user; 01217 struct iax2_user tmp_user = { 01218 .name = pvt->username, 01219 }; 01220 01221 user = ao2_find(users, &tmp_user, OBJ_POINTER); 01222 if (user) { 01223 ast_atomic_fetchadd_int(&user->curauthreq, -1); 01224 user = user_unref(user); 01225 } 01226 01227 ast_clear_flag(pvt, IAX_MAXAUTHREQ); 01228 } 01229 01230 /* No more pings or lagrq's */ 01231 AST_SCHED_DEL(sched, pvt->pingid); 01232 AST_SCHED_DEL(sched, pvt->lagid); 01233 AST_SCHED_DEL(sched, pvt->autoid); 01234 AST_SCHED_DEL(sched, pvt->authid); 01235 AST_SCHED_DEL(sched, pvt->initid); 01236 AST_SCHED_DEL(sched, pvt->jbid); 01237 }
static int iax2_devicestate | ( | void * | data | ) | [static] |
Part of the device state notification system ---.
Definition at line 10685 of file chan_iax2.c.
References iax2_peer::addr, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::defaddr, find_peer(), iax2_peer::historicms, iax2_peer::lastms, LOG_DEBUG, LOG_WARNING, iax2_peer::maxms, option_debug, parse_dial_string(), parsed_dial_string::peer, and peer_unref().
10686 { 10687 struct parsed_dial_string pds; 10688 char *tmp = ast_strdupa(data); 10689 struct iax2_peer *p; 10690 int res = AST_DEVICE_INVALID; 10691 10692 memset(&pds, 0, sizeof(pds)); 10693 parse_dial_string(tmp, &pds); 10694 10695 if (ast_strlen_zero(pds.peer)) { 10696 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 10697 return res; 10698 } 10699 10700 if (option_debug > 2) 10701 ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer); 10702 10703 /* SLD: FIXME: second call to find_peer during registration */ 10704 if (!(p = find_peer(pds.peer, 1))) 10705 return res; 10706 10707 res = AST_DEVICE_UNAVAILABLE; 10708 if (option_debug > 2) 10709 ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", 10710 pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); 10711 10712 if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && 10713 (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { 10714 /* Peer is registered, or have default IP address 10715 and a valid registration */ 10716 if (p->historicms == 0 || p->historicms <= p->maxms) 10717 /* let the core figure out whether it is in use or not */ 10718 res = AST_DEVICE_UNKNOWN; 10719 } 10720 10721 peer_unref(p); 10722 10723 return res; 10724 }
static int iax2_digit_begin | ( | struct ast_channel * | c, | |
char | digit | |||
) | [static] |
Definition at line 2742 of file chan_iax2.c.
References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02743 { 02744 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); 02745 }
static int iax2_digit_end | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 2747 of file chan_iax2.c.
References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02748 { 02749 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); 02750 }
static int iax2_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4935 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04936 { 04937 if (argc < 2 || argc > 3) 04938 return RESULT_SHOWUSAGE; 04939 iaxdebug = 1; 04940 ast_cli(fd, "IAX2 Debugging Enabled\n"); 04941 return RESULT_SUCCESS; 04942 }
static int iax2_do_jb_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4953 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04954 { 04955 if (argc < 3 || argc > 4) 04956 return RESULT_SHOWUSAGE; 04957 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 04958 ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 04959 return RESULT_SUCCESS; 04960 }
static int iax2_do_register | ( | struct iax2_registry * | reg | ) | [static] |
Definition at line 8655 of file chan_iax2.c.
References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax_ie_data::buf, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_add(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, send_command(), and iax2_registry::username.
Referenced by __iax2_do_register_s(), load_module(), and reload_config().
08656 { 08657 struct iax_ie_data ied; 08658 if (option_debug && iaxdebug) 08659 ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username); 08660 08661 if (reg->dnsmgr && 08662 ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { 08663 /* Maybe the IP has changed, force DNS refresh */ 08664 ast_dnsmgr_refresh(reg->dnsmgr); 08665 } 08666 08667 /* 08668 * if IP has Changed, free allocated call to create a new one with new IP 08669 * call has the pointer to IP and must be updated to the new one 08670 */ 08671 if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) { 08672 ast_mutex_lock(&iaxsl[reg->callno]); 08673 iax2_destroy(reg->callno); 08674 ast_mutex_unlock(&iaxsl[reg->callno]); 08675 reg->callno = 0; 08676 } 08677 if (!reg->addr.sin_addr.s_addr) { 08678 if (option_debug && iaxdebug) 08679 ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username); 08680 /* Setup the next registration attempt */ 08681 AST_SCHED_DEL(sched, reg->expire); 08682 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 08683 return -1; 08684 } 08685 08686 if (!reg->callno) { 08687 if (option_debug) 08688 ast_log(LOG_DEBUG, "Allocate call number\n"); 08689 reg->callno = find_callno_locked(0, 0, ®->addr, NEW_FORCE, defaultsockfd, 0); 08690 if (reg->callno < 1) { 08691 ast_log(LOG_WARNING, "Unable to create call for registration\n"); 08692 return -1; 08693 } else if (option_debug) 08694 ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno); 08695 iaxs[reg->callno]->reg = reg; 08696 ast_mutex_unlock(&iaxsl[reg->callno]); 08697 } 08698 /* Schedule the next registration attempt */ 08699 AST_SCHED_DEL(sched, reg->expire); 08700 /* Setup the next registration a little early */ 08701 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 08702 /* Send the request */ 08703 memset(&ied, 0, sizeof(ied)); 08704 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 08705 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 08706 send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 08707 reg->regstate = REG_STATE_REGSENT; 08708 return 0; 08709 }
static int iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 5736 of file chan_iax2.c.
References __iax2_do_register_s(), and schedule_action.
Referenced by iax2_ack_registry(), and iax2_do_register().
05737 { 05738 #ifdef SCHED_MULTITHREADED 05739 if (schedule_action(__iax2_do_register_s, data)) 05740 #endif 05741 __iax2_do_register_s(data); 05742 return 0; 05743 }
static int iax2_do_trunk_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4944 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04945 { 04946 if (argc < 3 || argc > 4) 04947 return RESULT_SHOWUSAGE; 04948 iaxtrunkdebug = 1; 04949 ast_cli(fd, "IAX2 Trunk Debug Requested\n"); 04950 return RESULT_SUCCESS; 04951 }
static void iax2_dprequest | ( | struct iax2_dpcache * | dp, | |
int | callno | |||
) | [static] |
Definition at line 6427 of file chan_iax2.c.
References AST_FRAME_IAX, AST_SCHED_DEL, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_add(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, iaxs, iax_ie_data::pos, and send_command().
Referenced by find_cache(), and socket_process().
06428 { 06429 struct iax_ie_data ied; 06430 /* Auto-hangup with 30 seconds of inactivity */ 06431 AST_SCHED_DEL(sched, iaxs[callno]->autoid); 06432 iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno); 06433 memset(&ied, 0, sizeof(ied)); 06434 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten); 06435 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); 06436 dp->flags |= CACHE_FLAG_TRANSMITTED; 06437 }
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 10544 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_3.
10545 { 10546 char odata[256]; 10547 char req[256]; 10548 char *ncontext; 10549 struct iax2_dpcache *dp; 10550 struct ast_app *dial; 10551 #if 0 10552 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); 10553 #endif 10554 if (priority == 2) { 10555 /* Indicate status, can be overridden in dialplan */ 10556 const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS"); 10557 if (dialstatus) { 10558 dial = pbx_findapp(dialstatus); 10559 if (dial) 10560 pbx_exec(chan, dial, ""); 10561 } 10562 return -1; 10563 } else if (priority != 1) 10564 return -1; 10565 ast_mutex_lock(&dpcache_lock); 10566 dp = find_cache(chan, data, context, exten, priority); 10567 if (dp) { 10568 if (dp->flags & CACHE_FLAG_EXISTS) { 10569 ast_copy_string(odata, data, sizeof(odata)); 10570 ncontext = strchr(odata, '/'); 10571 if (ncontext) { 10572 *ncontext = '\0'; 10573 ncontext++; 10574 snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext); 10575 } else { 10576 snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten); 10577 } 10578 if (option_verbose > 2) 10579 ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req); 10580 } else { 10581 ast_mutex_unlock(&dpcache_lock); 10582 ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data); 10583 return -1; 10584 } 10585 } 10586 ast_mutex_unlock(&dpcache_lock); 10587 dial = pbx_findapp("Dial"); 10588 if (dial) { 10589 return pbx_exec(chan, dial, req); 10590 } else { 10591 ast_log(LOG_WARNING, "No dial application registered\n"); 10592 } 10593 return -1; 10594 }
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 10475 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
10476 { 10477 struct iax2_dpcache *dp; 10478 int res = 0; 10479 #if 0 10480 ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10481 #endif 10482 if ((priority != 1) && (priority != 2)) 10483 return 0; 10484 ast_mutex_lock(&dpcache_lock); 10485 dp = find_cache(chan, data, context, exten, priority); 10486 if (dp) { 10487 if (dp->flags & CACHE_FLAG_EXISTS) 10488 res= 1; 10489 } 10490 ast_mutex_unlock(&dpcache_lock); 10491 if (!dp) { 10492 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10493 } 10494 return res; 10495 }
static int iax2_fixup | ( | struct ast_channel * | oldchannel, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 2769 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iaxs, iaxsl, LOG_WARNING, chan_iax2_pvt::owner, PTR_TO_CALLNO, and ast_channel::tech_pvt.
02770 { 02771 unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt); 02772 ast_mutex_lock(&iaxsl[callno]); 02773 if (iaxs[callno]) 02774 iaxs[callno]->owner = newchan; 02775 else 02776 ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n"); 02777 ast_mutex_unlock(&iaxsl[callno]); 02778 return 0; 02779 }
static void iax2_frame_free | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 1276 of file chan_iax2.c.
References AST_SCHED_DEL, iax_frame_free(), and iax_frame::retrans.
Referenced by __attempt_transmit(), __do_deliver(), __get_from_jb(), complete_transfer(), pvt_destructor(), and schedule_delivery().
01277 { 01278 AST_SCHED_DEL(sched, fr->retrans); 01279 iax_frame_free(fr); 01280 }
static int iax2_getpeername | ( | struct sockaddr_in | sin, | |
char * | host, | |||
int | len | |||
) | [static] |
Definition at line 1182 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), peer_unref(), peers, and realtime_peer().
Referenced by __find_callno().
01183 { 01184 struct iax2_peer *peer = NULL; 01185 int res = 0; 01186 struct ao2_iterator i; 01187 01188 i = ao2_iterator_init(peers, 0); 01189 while ((peer = ao2_iterator_next(&i))) { 01190 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 01191 (peer->addr.sin_port == sin.sin_port)) { 01192 ast_copy_string(host, peer->name, len); 01193 peer_unref(peer); 01194 res = 1; 01195 break; 01196 } 01197 peer_unref(peer); 01198 } 01199 01200 if (!peer) { 01201 peer = realtime_peer(NULL, &sin); 01202 if (peer) { 01203 ast_copy_string(host, peer->name, len); 01204 peer_unref(peer); 01205 res = 1; 01206 } 01207 } 01208 01209 return res; 01210 }
static int iax2_getpeertrunk | ( | struct sockaddr_in | sin | ) | [static] |
Definition at line 3704 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_TRUNK, peer_unref(), and peers.
Referenced by check_access().
03705 { 03706 struct iax2_peer *peer; 03707 int res = 0; 03708 struct ao2_iterator i; 03709 03710 i = ao2_iterator_init(peers, 0); 03711 while ((peer = ao2_iterator_next(&i))) { 03712 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 03713 (peer->addr.sin_port == sin.sin_port)) { 03714 res = ast_test_flag(peer, IAX_TRUNK); 03715 peer_unref(peer); 03716 break; 03717 } 03718 peer_unref(peer); 03719 } 03720 03721 return res; 03722 }
static int iax2_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3370 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_verbose(), iax_ie_data::buf, iax2_registry::callno, error(), ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, iaxs, iaxsl, LOG_DEBUG, option_debug, option_verbose, iax_ie_data::pos, PTR_TO_CALLNO, send_command_final(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03371 { 03372 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03373 int alreadygone; 03374 struct iax_ie_data ied; 03375 memset(&ied, 0, sizeof(ied)); 03376 ast_mutex_lock(&iaxsl[callno]); 03377 if (callno && iaxs[callno]) { 03378 if (option_debug) 03379 ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause); 03380 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE); 03381 /* Send the hangup unless we have had a transmission error or are already gone */ 03382 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); 03383 if (!iaxs[callno]->error && !alreadygone) { 03384 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 03385 if (!iaxs[callno]) { 03386 ast_mutex_unlock(&iaxsl[callno]); 03387 return 0; 03388 } 03389 } 03390 /* Explicitly predestroy it */ 03391 iax2_predestroy(callno); 03392 /* If we were already gone to begin with, destroy us now */ 03393 if (alreadygone && iaxs[callno]) { 03394 if (option_debug) 03395 ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name); 03396 iax2_destroy(callno); 03397 } 03398 } 03399 ast_mutex_unlock(&iaxsl[callno]); 03400 if (option_verbose > 2) 03401 ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name); 03402 return 0; 03403 }
static int iax2_indicate | ( | struct ast_channel * | c, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 3637 of file chan_iax2.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, DEADLOCK_AVOIDANCE, iaxs, iaxsl, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.
03638 { 03639 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03640 struct chan_iax2_pvt *pvt; 03641 int res = 0; 03642 03643 if (option_debug && iaxdebug) 03644 ast_log(LOG_DEBUG, "Indicating condition %d\n", condition); 03645 03646 ast_mutex_lock(&iaxsl[callno]); 03647 pvt = iaxs[callno]; 03648 03649 if (!pvt->peercallno) { 03650 /* We don't know the remote side's call number, yet. :( */ 03651 int count = 10; 03652 while (count-- && pvt && !pvt->peercallno) { 03653 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 03654 pvt = iaxs[callno]; 03655 } 03656 if (!pvt->peercallno) { 03657 res = -1; 03658 goto done; 03659 } 03660 } 03661 03662 switch (condition) { 03663 case AST_CONTROL_HOLD: 03664 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03665 ast_moh_start(c, data, pvt->mohinterpret); 03666 goto done; 03667 } 03668 break; 03669 case AST_CONTROL_UNHOLD: 03670 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03671 ast_moh_stop(c); 03672 goto done; 03673 } 03674 } 03675 03676 res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); 03677 03678 done: 03679 ast_mutex_unlock(&iaxsl[callno]); 03680 03681 return res; 03682 }
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 10521 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_MATCHMORE, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
10522 { 10523 int res = 0; 10524 struct iax2_dpcache *dp; 10525 #if 0 10526 ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10527 #endif 10528 if ((priority != 1) && (priority != 2)) 10529 return 0; 10530 ast_mutex_lock(&dpcache_lock); 10531 dp = find_cache(chan, data, context, exten, priority); 10532 if (dp) { 10533 if (dp->flags & CACHE_FLAG_MATCHMORE) 10534 res= 1; 10535 } 10536 ast_mutex_unlock(&dpcache_lock); 10537 if (!dp) { 10538 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10539 } 10540 return res; 10541 }
static int iax2_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4962 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04963 { 04964 if (argc < 3 || argc > 4) 04965 return RESULT_SHOWUSAGE; 04966 iaxdebug = 0; 04967 ast_cli(fd, "IAX2 Debugging Disabled\n"); 04968 return RESULT_SUCCESS; 04969 }
static int iax2_no_jb_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4980 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04981 { 04982 if (argc < 4 || argc > 5) 04983 return RESULT_SHOWUSAGE; 04984 jb_setoutput(jb_error_output, jb_warning_output, NULL); 04985 jb_debug_output("\n"); 04986 ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 04987 return RESULT_SUCCESS; 04988 }
static int iax2_no_trunk_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4971 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04972 { 04973 if (argc < 4 || argc > 5) 04974 return RESULT_SHOWUSAGE; 04975 iaxtrunkdebug = 0; 04976 ast_cli(fd, "IAX2 Trunk Debugging Disabled\n"); 04977 return RESULT_SUCCESS; 04978 }
static int iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 8853 of file chan_iax2.c.
References __iax2_poke_noanswer(), peer_unref(), iax2_peer::pokeexpire, and schedule_action.
Referenced by iax2_poke_peer().
08854 { 08855 struct iax2_peer *peer = (struct iax2_peer *)data; 08856 peer->pokeexpire = -1; 08857 #ifdef SCHED_MULTITHREADED 08858 if (schedule_action(__iax2_poke_noanswer, data)) 08859 #endif 08860 __iax2_poke_noanswer(data); 08861 peer_unref(peer); 08862 return 0; 08863 }
static int iax2_poke_peer | ( | struct iax2_peer * | peer, | |
int | heldcall | |||
) | [static] |
Definition at line 8874 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, iax2_registry::callno, DEFAULT_MAXMS, iax2_peer::dnsmgr, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), iax2_sched_add(), IAX_COMMAND_POKE, iaxs, iaxsl, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, NEW_FORCE, peer_ref(), peer_unref(), chan_iax2_pvt::peerpoke, chan_iax2_pvt::pingtime, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, send_command(), and iax2_peer::sockfd.
Referenced by __iax2_poke_peer_s(), iax2_poke_peer_cb(), poke_all_peers(), reg_source_db(), and update_registry().
08875 { 08876 int callno; 08877 if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) { 08878 /* IF we have no IP without dnsmgr, or this isn't to be monitored, return 08879 immediately after clearing things out */ 08880 peer->lastms = 0; 08881 peer->historicms = 0; 08882 peer->pokeexpire = -1; 08883 peer->callno = 0; 08884 return 0; 08885 } 08886 08887 /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */ 08888 if ((callno = peer->callno) > 0) { 08889 ast_log(LOG_NOTICE, "Still have a callno...\n"); 08890 ast_mutex_lock(&iaxsl[callno]); 08891 iax2_destroy(callno); 08892 ast_mutex_unlock(&iaxsl[callno]); 08893 } 08894 if (heldcall) 08895 ast_mutex_unlock(&iaxsl[heldcall]); 08896 callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0); 08897 if (heldcall) 08898 ast_mutex_lock(&iaxsl[heldcall]); 08899 if (peer->callno < 1) { 08900 ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); 08901 return -1; 08902 } 08903 08904 /* Speed up retransmission times for this qualify call */ 08905 iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1; 08906 iaxs[peer->callno]->peerpoke = peer; 08907 08908 /* Remove any pending pokeexpire task */ 08909 if (peer->pokeexpire > -1) { 08910 if (!ast_sched_del(sched, peer->pokeexpire)) { 08911 peer->pokeexpire = -1; 08912 peer_unref(peer); 08913 } 08914 } 08915 08916 /* Queue up a new task to handle no reply */ 08917 /* If the host is already unreachable then use the unreachable interval instead */ 08918 if (peer->lastms < 0) { 08919 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer)); 08920 } else 08921 peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer)); 08922 08923 if (peer->pokeexpire == -1) 08924 peer_unref(peer); 08925 08926 /* And send the poke */ 08927 ast_mutex_lock(&iaxsl[callno]); 08928 if (iaxs[callno]) { 08929 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1); 08930 } 08931 ast_mutex_unlock(&iaxsl[callno]); 08932 08933 return 0; 08934 }
static int iax2_poke_peer_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 8865 of file chan_iax2.c.
References iax2_poke_peer().
Referenced by load_module().
08866 { 08867 struct iax2_peer *peer = obj; 08868 08869 iax2_poke_peer(peer, 0); 08870 08871 return 0; 08872 }
static int iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 6467 of file chan_iax2.c.
References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.
Referenced by __iax2_poke_noanswer(), and socket_process().
06468 { 06469 struct iax2_peer *peer = (struct iax2_peer *)data; 06470 peer->pokeexpire = -1; 06471 #ifdef SCHED_MULTITHREADED 06472 if (schedule_action(__iax2_poke_peer_s, data)) 06473 #endif 06474 __iax2_poke_peer_s(data); 06475 return 0; 06476 }
static int iax2_predestroy | ( | int | callno | ) | [static] |
Definition at line 2115 of file chan_iax2.c.
References ast_module_unref(), ast_set_flag, ast_test_flag, iax2_destroy_helper(), iax2_queue_hangup(), IAX_ALREADYGONE, iaxs, chan_iax2_pvt::owner, and ast_channel::tech_pvt.
Referenced by iax2_hangup(), and send_command_final().
02116 { 02117 struct ast_channel *c; 02118 struct chan_iax2_pvt *pvt = iaxs[callno]; 02119 02120 if (!pvt) 02121 return -1; 02122 if (!ast_test_flag(pvt, IAX_ALREADYGONE)) { 02123 iax2_destroy_helper(pvt); 02124 ast_set_flag(pvt, IAX_ALREADYGONE); 02125 } 02126 c = pvt->owner; 02127 if (c) { 02128 c->tech_pvt = NULL; 02129 iax2_queue_hangup(callno); 02130 pvt->owner = NULL; 02131 ast_module_unref(ast_module_info->self); 02132 } 02133 return 0; 02134 }
static void * iax2_process_thread | ( | void * | data | ) | [static] |
Definition at line 8530 of file chan_iax2.c.
References ast_cond_timedwait(), ast_cond_wait(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_tvadd(), handle_deferred_full_frames(), iax2_process_thread_cleanup(), IAX_IOSTATE_IDLE, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_READY, IAX_IOSTATE_SCHEDREADY, IAX_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), socket_process(), t, and thread.
Referenced by find_idle_thread(), and start_network_thread().
08531 { 08532 struct iax2_thread *thread = data; 08533 struct timeval tv; 08534 struct timespec ts; 08535 int put_into_idle = 0; 08536 08537 ast_atomic_fetchadd_int(&iaxactivethreadcount,1); 08538 pthread_cleanup_push(iax2_process_thread_cleanup, data); 08539 for(;;) { 08540 /* Wait for something to signal us to be awake */ 08541 ast_mutex_lock(&thread->lock); 08542 08543 /* Flag that we're ready to accept signals */ 08544 thread->ready_for_signal = 1; 08545 08546 /* Put into idle list if applicable */ 08547 if (put_into_idle) 08548 insert_idle_thread(thread); 08549 08550 if (thread->type == IAX_TYPE_DYNAMIC) { 08551 struct iax2_thread *t = NULL; 08552 /* Wait to be signalled or time out */ 08553 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 08554 ts.tv_sec = tv.tv_sec; 08555 ts.tv_nsec = tv.tv_usec * 1000; 08556 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) { 08557 /* This thread was never put back into the available dynamic 08558 * thread list, so just go away. */ 08559 if (!put_into_idle) { 08560 ast_mutex_unlock(&thread->lock); 08561 break; 08562 } 08563 AST_LIST_LOCK(&dynamic_list); 08564 /* Account for the case where this thread is acquired *right* after a timeout */ 08565 if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list))) 08566 iaxdynamicthreadcount--; 08567 AST_LIST_UNLOCK(&dynamic_list); 08568 if (t) { 08569 /* This dynamic thread timed out waiting for a task and was 08570 * not acquired immediately after the timeout, 08571 * so it's time to go away. */ 08572 ast_mutex_unlock(&thread->lock); 08573 break; 08574 } 08575 /* Someone grabbed our thread *right* after we timed out. 08576 * Wait for them to set us up with something to do and signal 08577 * us to continue. */ 08578 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 08579 ts.tv_sec = tv.tv_sec; 08580 ts.tv_nsec = tv.tv_usec * 1000; 08581 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) 08582 { 08583 ast_mutex_unlock(&thread->lock); 08584 break; 08585 } 08586 } 08587 } else { 08588 ast_cond_wait(&thread->cond, &thread->lock); 08589 } 08590 08591 /* Go back into our respective list */ 08592 put_into_idle = 1; 08593 08594 ast_mutex_unlock(&thread->lock); 08595 08596 if (thread->iostate == IAX_IOSTATE_IDLE) 08597 continue; 08598 08599 /* Add ourselves to the active list now */ 08600 AST_LIST_LOCK(&active_list); 08601 AST_LIST_INSERT_HEAD(&active_list, thread, list); 08602 AST_LIST_UNLOCK(&active_list); 08603 08604 /* See what we need to do */ 08605 switch(thread->iostate) { 08606 case IAX_IOSTATE_READY: 08607 thread->actions++; 08608 thread->iostate = IAX_IOSTATE_PROCESSING; 08609 socket_process(thread); 08610 handle_deferred_full_frames(thread); 08611 break; 08612 case IAX_IOSTATE_SCHEDREADY: 08613 thread->actions++; 08614 thread->iostate = IAX_IOSTATE_PROCESSING; 08615 #ifdef SCHED_MULTITHREADED 08616 thread->schedfunc(thread->scheddata); 08617 #endif 08618 break; 08619 } 08620 time(&thread->checktime); 08621 thread->iostate = IAX_IOSTATE_IDLE; 08622 #ifdef DEBUG_SCHED_MULTITHREAD 08623 thread->curfunc[0]='\0'; 08624 #endif 08625 08626 /* Now... remove ourselves from the active list, and return to the idle list */ 08627 AST_LIST_LOCK(&active_list); 08628 AST_LIST_REMOVE(&active_list, thread, list); 08629 AST_LIST_UNLOCK(&active_list); 08630 08631 /* Make sure another frame didn't sneak in there after we thought we were done. */ 08632 handle_deferred_full_frames(thread); 08633 } 08634 08635 /*!\note For some reason, idle threads are exiting without being removed 08636 * from an idle list, which is causing memory corruption. Forcibly remove 08637 * it from the list, if it's there. 08638 */ 08639 AST_LIST_LOCK(&idle_list); 08640 AST_LIST_REMOVE(&idle_list, thread, list); 08641 AST_LIST_UNLOCK(&idle_list); 08642 08643 AST_LIST_LOCK(&dynamic_list); 08644 AST_LIST_REMOVE(&dynamic_list, thread, list); 08645 AST_LIST_UNLOCK(&dynamic_list); 08646 08647 /* I am exiting here on my own volition, I need to clean up my own data structures 08648 * Assume that I am no longer in any of the lists (idle, active, or dynamic) 08649 */ 08650 pthread_cleanup_pop(1); 08651 08652 return NULL; 08653 }
static void iax2_process_thread_cleanup | ( | void * | data | ) | [static] |
Definition at line 8521 of file chan_iax2.c.
References ast_cond_destroy(), ast_mutex_destroy(), free, iaxactivethreadcount, and thread.
Referenced by iax2_process_thread().
08522 { 08523 struct iax2_thread *thread = data; 08524 ast_mutex_destroy(&thread->lock); 08525 ast_cond_destroy(&thread->cond); 08526 free(thread); 08527 ast_atomic_dec_and_test(&iaxactivethreadcount); 08528 }
static int iax2_prov_cmd | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 8808 of file chan_iax2.c.
References ast_cli(), iax2_provision(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
08809 { 08810 int force = 0; 08811 int res; 08812 if (argc < 4) 08813 return RESULT_SHOWUSAGE; 08814 if ((argc > 4)) { 08815 if (!strcasecmp(argv[4], "forced")) 08816 force = 1; 08817 else 08818 return RESULT_SHOWUSAGE; 08819 } 08820 res = iax2_provision(NULL, -1, argv[2], argv[3], force); 08821 if (res < 0) 08822 ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]); 08823 else if (res < 1) 08824 ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]); 08825 else 08826 ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : ""); 08827 return RESULT_SUCCESS; 08828 }
static char* iax2_prov_complete_template_3rd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 8711 of file chan_iax2.c.
References iax_prov_complete_template().
08712 { 08713 if (pos != 3) 08714 return NULL; 08715 return iax_prov_complete_template(line, word, pos, state); 08716 }
static int iax2_provision | ( | struct sockaddr_in * | end, | |
int | sockfd, | |||
char * | dest, | |||
const char * | template, | |||
int | force | |||
) | [static] |
Definition at line 8718 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_unlock(), AST_SCHED_DEL, ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, iax2_registry::callno, create_addr(), find_callno_locked(), iax2_sched_add(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), iaxs, iaxsl, LOG_DEBUG, NEW_FORCE, option_debug, iax_ie_data::pos, send_command(), and create_addr_info::sockfd.
Referenced by check_provisioning(), iax2_prov_app(), and iax2_prov_cmd().
08719 { 08720 /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning 08721 is found for template */ 08722 struct iax_ie_data provdata; 08723 struct iax_ie_data ied; 08724 unsigned int sig; 08725 struct sockaddr_in sin; 08726 int callno; 08727 struct create_addr_info cai; 08728 08729 memset(&cai, 0, sizeof(cai)); 08730 08731 if (option_debug) 08732 ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template); 08733 08734 if (iax_provision_build(&provdata, &sig, template, force)) { 08735 if (option_debug) 08736 ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template); 08737 return 0; 08738 } 08739 08740 if (end) { 08741 memcpy(&sin, end, sizeof(sin)); 08742 cai.sockfd = sockfd; 08743 } else if (create_addr(dest, NULL, &sin, &cai)) 08744 return -1; 08745 08746 /* Build the rest of the message */ 08747 memset(&ied, 0, sizeof(ied)); 08748 iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); 08749 08750 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 08751 if (!callno) 08752 return -1; 08753 08754 if (iaxs[callno]) { 08755 /* Schedule autodestruct in case they don't ever give us anything back */ 08756 AST_SCHED_DEL(sched, iaxs[callno]->autoid); 08757 iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno); 08758 ast_set_flag(iaxs[callno], IAX_PROVISION); 08759 /* Got a call number now, so go ahead and send the provisioning information */ 08760 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); 08761 } 08762 ast_mutex_unlock(&iaxsl[callno]); 08763 08764 return 1; 08765 }
static int iax2_prune_realtime | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2239 of file chan_iax2.c.
References ast_cli(), ast_set_flag, ast_test_flag, expire_registry(), find_peer(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, peer_ref(), peer_unref(), reload_config(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02240 { 02241 struct iax2_peer *peer; 02242 02243 if (argc != 4) 02244 return RESULT_SHOWUSAGE; 02245 if (!strcmp(argv[3],"all")) { 02246 reload_config(); 02247 ast_cli(fd, "OK cache is flushed.\n"); 02248 } else if ((peer = find_peer(argv[3], 0))) { 02249 if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 02250 ast_set_flag(peer, IAX_RTAUTOCLEAR); 02251 expire_registry(peer_ref(peer)); 02252 ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]); 02253 } else { 02254 ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]); 02255 } 02256 peer_unref(peer); 02257 } else { 02258 ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]); 02259 } 02260 02261 return RESULT_SUCCESS; 02262 }
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.
Definition at line 1725 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_control_data(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by socket_process().
01727 { 01728 for (;;) { 01729 if (iaxs[callno] && iaxs[callno]->owner) { 01730 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01731 /* Avoid deadlock by pausing and trying again */ 01732 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01733 } else { 01734 ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); 01735 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01736 break; 01737 } 01738 } else 01739 break; 01740 } 01741 return 0; 01742 }
static int iax2_queue_frame | ( | int | callno, | |
struct ast_frame * | f | |||
) | [static] |
Queue a frame to a call's owning asterisk channel.
Definition at line 1663 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), __get_from_jb(), and socket_process().
01664 { 01665 for (;;) { 01666 if (iaxs[callno] && iaxs[callno]->owner) { 01667 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01668 /* Avoid deadlock by pausing and trying again */ 01669 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01670 } else { 01671 ast_queue_frame(iaxs[callno]->owner, f); 01672 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01673 break; 01674 } 01675 } else 01676 break; 01677 } 01678 return 0; 01679 }
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.
Definition at line 1694 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by iax2_predestroy().
01695 { 01696 for (;;) { 01697 if (iaxs[callno] && iaxs[callno]->owner) { 01698 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01699 /* Avoid deadlock by pausing and trying again */ 01700 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01701 } else { 01702 ast_queue_hangup(iaxs[callno]->owner); 01703 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01704 break; 01705 } 01706 } else 01707 break; 01708 } 01709 return 0; 01710 }
static struct ast_frame * iax2_read | ( | struct ast_channel * | c | ) | [static, read] |
Definition at line 3431 of file chan_iax2.c.
References ast_log(), ast_null_frame, LOG_NOTICE, and option_verbose.
03432 { 03433 if (option_verbose > 3) 03434 ast_log(LOG_NOTICE, "I should never be called!\n"); 03435 return &ast_null_frame; 03436 }
static int iax2_register | ( | char * | value, | |
int | lineno | |||
) | [static] |
Definition at line 5949 of file chan_iax2.c.
References iax2_registry::addr, ast_calloc, ast_dnsmgr_lookup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), copy(), iax2_registry::dnsmgr, iax2_registry::expire, free, hostname, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, iax2_registry::refresh, iax2_registry::secret, strsep(), and iax2_registry::username.
Referenced by set_config().
05950 { 05951 struct iax2_registry *reg; 05952 char copy[256]; 05953 char *username, *hostname, *secret; 05954 char *porta; 05955 char *stringp=NULL; 05956 05957 if (!value) 05958 return -1; 05959 ast_copy_string(copy, value, sizeof(copy)); 05960 stringp=copy; 05961 username = strsep(&stringp, "@"); 05962 hostname = strsep(&stringp, "@"); 05963 if (!hostname) { 05964 ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno); 05965 return -1; 05966 } 05967 stringp=username; 05968 username = strsep(&stringp, ":"); 05969 secret = strsep(&stringp, ":"); 05970 stringp=hostname; 05971 hostname = strsep(&stringp, ":"); 05972 porta = strsep(&stringp, ":"); 05973 05974 if (porta && !atoi(porta)) { 05975 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 05976 return -1; 05977 } 05978 if (!(reg = ast_calloc(1, sizeof(*reg)))) 05979 return -1; 05980 if (ast_dnsmgr_lookup(hostname, ®->addr.sin_addr, ®->dnsmgr) < 0) { 05981 free(reg); 05982 return -1; 05983 } 05984 ast_copy_string(reg->username, username, sizeof(reg->username)); 05985 if (secret) 05986 ast_copy_string(reg->secret, secret, sizeof(reg->secret)); 05987 reg->expire = -1; 05988 reg->refresh = IAX_DEFAULT_REG_EXPIRE; 05989 reg->addr.sin_family = AF_INET; 05990 reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); 05991 AST_LIST_LOCK(®istrations); 05992 AST_LIST_INSERT_HEAD(®istrations, reg, entry); 05993 AST_LIST_UNLOCK(®istrations); 05994 05995 return 0; 05996 }
static int iax2_reload | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10244 of file chan_iax2.c.
References reload_config().
10245 { 10246 return reload_config(); 10247 }
static struct ast_channel * iax2_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static, read] |
Definition at line 8946 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(), iax2_registry::callno, create_addr_info::capability, create_addr(), find_callno_locked(), fmt, create_addr_info::found, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), create_addr_info::maxtime, chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), parsed_dial_string::peer, parsed_dial_string::port, ast_channel::readformat, create_addr_info::sockfd, and ast_channel::writeformat.
08947 { 08948 int callno; 08949 int res; 08950 int fmt, native; 08951 struct sockaddr_in sin; 08952 struct ast_channel *c; 08953 struct parsed_dial_string pds; 08954 struct create_addr_info cai; 08955 char *tmpstr; 08956 08957 memset(&pds, 0, sizeof(pds)); 08958 tmpstr = ast_strdupa(data); 08959 parse_dial_string(tmpstr, &pds); 08960 08961 if (ast_strlen_zero(pds.peer)) { 08962 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 08963 return NULL; 08964 } 08965 08966 memset(&cai, 0, sizeof(cai)); 08967 cai.capability = iax2_capability; 08968 08969 ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 08970 08971 /* Populate our address from the given */ 08972 if (create_addr(pds.peer, NULL, &sin, &cai)) { 08973 *cause = AST_CAUSE_UNREGISTERED; 08974 return NULL; 08975 } 08976 08977 if (pds.port) 08978 sin.sin_port = htons(atoi(pds.port)); 08979 08980 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 08981 if (callno < 1) { 08982 ast_log(LOG_WARNING, "Unable to create call\n"); 08983 *cause = AST_CAUSE_CONGESTION; 08984 return NULL; 08985 } 08986 08987 /* If this is a trunk, update it now */ 08988 ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 08989 if (ast_test_flag(&cai, IAX_TRUNK)) { 08990 int new_callno; 08991 if ((new_callno = make_trunk(callno, 1)) != -1) 08992 callno = new_callno; 08993 } 08994 iaxs[callno]->maxtime = cai.maxtime; 08995 if (cai.found) 08996 ast_string_field_set(iaxs[callno], host, pds.peer); 08997 08998 c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability); 08999 09000 ast_mutex_unlock(&iaxsl[callno]); 09001 09002 if (c) { 09003 /* Choose a format we can live with */ 09004 if (c->nativeformats & format) 09005 c->nativeformats &= format; 09006 else { 09007 native = c->nativeformats; 09008 fmt = format; 09009 res = ast_translator_best_choice(&fmt, &native); 09010 if (res < 0) { 09011 ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", 09012 ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); 09013 ast_hangup(c); 09014 return NULL; 09015 } 09016 c->nativeformats = native; 09017 } 09018 c->readformat = ast_best_codec(c->nativeformats); 09019 c->writeformat = c->readformat; 09020 } 09021 09022 return c; 09023 }
static int iax2_sched_add | ( | struct sched_context * | con, | |
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) | [static] |
Definition at line 986 of file chan_iax2.c.
References ast_sched_add(), and signal_condition().
Referenced by __attempt_transmit(), __find_callno(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), auth_fail(), iax2_ack_registry(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_poke_peer(), iax2_provision(), make_trunk(), network_thread(), realtime_peer(), reg_source_db(), socket_process(), update_jbsched(), and update_registry().
00987 { 00988 int res; 00989 00990 res = ast_sched_add(con, when, callback, data); 00991 signal_condition(&sched_lock, &sched_cond); 00992 00993 return res; 00994 }
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 4273 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, iax_frame::datalen, ast_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, chan_iax2_pvt::ecx, encrypt_frame(), iax_frame::final, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, LOG_WARNING, MAX_RETRY_TIME, MIN_RETRY_TIME, ast_iax2_full_hdr::oseqno, chan_iax2_pvt::oseqno, iax_frame::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, iax_frame::retrytime, ast_iax2_full_hdr::scallno, chan_iax2_pvt::semirand, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, iax_frame::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, ast_iax2_mini_hdr::ts, ast_iax2_video_hdr::ts, ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_full_hdr::type, and ast_iax2_video_hdr::zeros.
Referenced by __send_command(), iax2_write(), and socket_process().
04274 { 04275 /* Queue a packet for delivery on a given private structure. Use "ts" for 04276 timestamp, or calculate if ts is 0. Send immediately without retransmission 04277 or delayed, with retransmission */ 04278 struct ast_iax2_full_hdr *fh; 04279 struct ast_iax2_mini_hdr *mh; 04280 struct ast_iax2_video_hdr *vh; 04281 struct { 04282 struct iax_frame fr2; 04283 unsigned char buffer[4096]; 04284 } frb; 04285 struct iax_frame *fr; 04286 int res; 04287 int sendmini=0; 04288 unsigned int lastsent; 04289 unsigned int fts; 04290 04291 frb.fr2.afdatalen = sizeof(frb.buffer); 04292 04293 if (!pvt) { 04294 ast_log(LOG_WARNING, "No private structure for packet?\n"); 04295 return -1; 04296 } 04297 04298 lastsent = pvt->lastsent; 04299 04300 /* Calculate actual timestamp */ 04301 fts = calc_timestamp(pvt, ts, f); 04302 04303 /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out 04304 * (the endpoint should detect the lost packet itself). But, we want to do this here, so that we 04305 * increment the "predicted timestamps" for voice, if we're predecting */ 04306 if(f->frametype == AST_FRAME_VOICE && f->datalen == 0) 04307 return 0; 04308 04309 04310 if ((ast_test_flag(pvt, IAX_TRUNK) || 04311 (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) || 04312 ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L)))) 04313 /* High two bytes are the same on timestamp, or sending on a trunk */ && 04314 (f->frametype == AST_FRAME_VOICE) 04315 /* is a voice frame */ && 04316 (f->subclass == pvt->svoiceformat) 04317 /* is the same type */ ) { 04318 /* Force immediate rather than delayed transmission */ 04319 now = 1; 04320 /* Mark that mini-style frame is appropriate */ 04321 sendmini = 1; 04322 } 04323 if ( f->frametype == AST_FRAME_VIDEO ) { 04324 /* 04325 * If the lower 15 bits of the timestamp roll over, or if 04326 * the video format changed then send a full frame. 04327 * Otherwise send a mini video frame 04328 */ 04329 if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) && 04330 ((f->subclass & ~0x1) == pvt->svideoformat) 04331 ) { 04332 now = 1; 04333 sendmini = 1; 04334 } else { 04335 now = 0; 04336 sendmini = 0; 04337 } 04338 pvt->lastvsent = fts; 04339 } 04340 /* Allocate an iax_frame */ 04341 if (now) { 04342 fr = &frb.fr2; 04343 } else 04344 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)); 04345 if (!fr) { 04346 ast_log(LOG_WARNING, "Out of memory\n"); 04347 return -1; 04348 } 04349 /* Copy our prospective frame into our immediate or retransmitted wrapper */ 04350 iax_frame_wrap(fr, f); 04351 04352 fr->ts = fts; 04353 fr->callno = pvt->callno; 04354 fr->transfer = transfer; 04355 fr->final = final; 04356 if (!sendmini) { 04357 /* We need a full frame */ 04358 if (seqno > -1) 04359 fr->oseqno = seqno; 04360 else 04361 fr->oseqno = pvt->oseqno++; 04362 fr->iseqno = pvt->iseqno; 04363 fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr)); 04364 fh->scallno = htons(fr->callno | IAX_FLAG_FULL); 04365 fh->ts = htonl(fr->ts); 04366 fh->oseqno = fr->oseqno; 04367 if (transfer) { 04368 fh->iseqno = 0; 04369 } else 04370 fh->iseqno = fr->iseqno; 04371 /* Keep track of the last thing we've acknowledged */ 04372 if (!transfer) 04373 pvt->aseqno = fr->iseqno; 04374 fh->type = fr->af.frametype & 0xFF; 04375 if (fr->af.frametype == AST_FRAME_VIDEO) 04376 fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6); 04377 else 04378 fh->csub = compress_subclass(fr->af.subclass); 04379 if (transfer) { 04380 fr->dcallno = pvt->transfercallno; 04381 } else 04382 fr->dcallno = pvt->peercallno; 04383 fh->dcallno = htons(fr->dcallno); 04384 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); 04385 fr->data = fh; 04386 fr->retries = 0; 04387 /* Retry after 2x the ping time has passed */ 04388 fr->retrytime = pvt->pingtime * 2; 04389 if (fr->retrytime < MIN_RETRY_TIME) 04390 fr->retrytime = MIN_RETRY_TIME; 04391 if (fr->retrytime > MAX_RETRY_TIME) 04392 fr->retrytime = MAX_RETRY_TIME; 04393 /* Acks' don't get retried */ 04394 if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) 04395 fr->retries = -1; 04396 else if (f->frametype == AST_FRAME_VOICE) 04397 pvt->svoiceformat = f->subclass; 04398 else if (f->frametype == AST_FRAME_VIDEO) 04399 pvt->svideoformat = f->subclass & ~0x1; 04400 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 04401 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 04402 if (iaxdebug) { 04403 if (fr->transfer) 04404 iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 04405 else 04406 iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 04407 } 04408 encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen); 04409 } else 04410 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04411 } 04412 04413 if (now) { 04414 res = send_packet(fr); 04415 } else 04416 res = iax2_transmit(fr); 04417 } else { 04418 if (ast_test_flag(pvt, IAX_TRUNK)) { 04419 iax2_trunk_queue(pvt, fr); 04420 res = 0; 04421 } else if (fr->af.frametype == AST_FRAME_VIDEO) { 04422 /* Video frame have no sequence number */ 04423 fr->oseqno = -1; 04424 fr->iseqno = -1; 04425 vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr)); 04426 vh->zeros = 0; 04427 vh->callno = htons(0x8000 | fr->callno); 04428 vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); 04429 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); 04430 fr->data = vh; 04431 fr->retries = -1; 04432 res = send_packet(fr); 04433 } else { 04434 /* Mini-frames have no sequence number */ 04435 fr->oseqno = -1; 04436 fr->iseqno = -1; 04437 /* Mini frame will do */ 04438 mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr)); 04439 mh->callno = htons(fr->callno); 04440 mh->ts = htons(fr->ts & 0xFFFF); 04441 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); 04442 fr->data = mh; 04443 fr->retries = -1; 04444 if (pvt->transferring == TRANSFER_MEDIAPASS) 04445 fr->transfer = 1; 04446 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 04447 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 04448 encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen); 04449 } else 04450 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04451 } 04452 res = send_packet(fr); 04453 } 04454 } 04455 return res; 04456 }
static int iax2_sendhtml | ( | struct ast_channel * | c, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 2764 of file chan_iax2.c.
References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02765 { 02766 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1); 02767 }
static int iax2_sendimage | ( | struct ast_channel * | c, | |
struct ast_frame * | img | |||
) | [static] |
Definition at line 2759 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.
02760 { 02761 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1); 02762 }
static int iax2_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 2752 of file chan_iax2.c.
References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02753 { 02754 02755 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT, 02756 0, 0, (unsigned char *)text, strlen(text) + 1, -1); 02757 }
static int iax2_setoption | ( | struct ast_channel * | c, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3405 of file chan_iax2.c.
References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_malloc, AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, ast_option_header::data, errno, ast_option_header::flag, free, ast_option_header::option, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03406 { 03407 struct ast_option_header *h; 03408 int res; 03409 03410 switch (option) { 03411 case AST_OPTION_TXGAIN: 03412 case AST_OPTION_RXGAIN: 03413 /* these two cannot be sent, because they require a result */ 03414 errno = ENOSYS; 03415 return -1; 03416 default: 03417 if (!(h = ast_malloc(datalen + sizeof(*h)))) 03418 return -1; 03419 03420 h->flag = AST_OPTION_FLAG_REQUEST; 03421 h->option = htons(option); 03422 memcpy(h->data, data, datalen); 03423 res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL, 03424 AST_CONTROL_OPTION, 0, (unsigned char *) h, 03425 datalen + sizeof(*h), -1); 03426 free(h); 03427 return res; 03428 } 03429 }
static int iax2_show_cache | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2443 of file chan_iax2.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, CACHE_FLAG_TRANSMITTED, CACHE_FLAG_UNKNOWN, dpcache, iax2_dpcache::expiry, iax2_dpcache::exten, iax2_dpcache::flags, iax2_dpcache::next, iax2_dpcache::peercontext, RESULT_SUCCESS, s, and iax2_dpcache::waiters.
02444 { 02445 struct iax2_dpcache *dp; 02446 char tmp[1024], *pc; 02447 int s; 02448 int x,y; 02449 struct timeval tv; 02450 gettimeofday(&tv, NULL); 02451 ast_mutex_lock(&dpcache_lock); 02452 dp = dpcache; 02453 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags"); 02454 while(dp) { 02455 s = dp->expiry.tv_sec - tv.tv_sec; 02456 tmp[0] = '\0'; 02457 if (dp->flags & CACHE_FLAG_EXISTS) 02458 strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1); 02459 if (dp->flags & CACHE_FLAG_NONEXISTENT) 02460 strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1); 02461 if (dp->flags & CACHE_FLAG_CANEXIST) 02462 strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1); 02463 if (dp->flags & CACHE_FLAG_PENDING) 02464 strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1); 02465 if (dp->flags & CACHE_FLAG_TIMEOUT) 02466 strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1); 02467 if (dp->flags & CACHE_FLAG_TRANSMITTED) 02468 strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1); 02469 if (dp->flags & CACHE_FLAG_MATCHMORE) 02470 strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1); 02471 if (dp->flags & CACHE_FLAG_UNKNOWN) 02472 strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1); 02473 /* Trim trailing pipe */ 02474 if (!ast_strlen_zero(tmp)) 02475 tmp[strlen(tmp) - 1] = '\0'; 02476 else 02477 ast_copy_string(tmp, "(none)", sizeof(tmp)); 02478 y=0; 02479 pc = strchr(dp->peercontext, '@'); 02480 if (!pc) 02481 pc = dp->peercontext; 02482 else 02483 pc++; 02484 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 02485 if (dp->waiters[x] > -1) 02486 y++; 02487 if (s > 0) 02488 ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp); 02489 else 02490 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp); 02491 dp = dp->next; 02492 } 02493 ast_mutex_unlock(&dpcache_lock); 02494 return RESULT_SUCCESS; 02495 }
static int iax2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4800 of file chan_iax2.c.
References iax2_registry::addr, ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, jb_info::current, iax_rr::delay, FORMAT, FORMAT2, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), jb_info::jitter, jb_info::min, chan_iax2_pvt::remote_rr, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_OR.
04801 { 04802 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" 04803 #define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" 04804 #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" 04805 int x; 04806 int numchans = 0; 04807 04808 if (argc != 3) 04809 return RESULT_SHOWUSAGE; 04810 ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format"); 04811 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 04812 ast_mutex_lock(&iaxsl[x]); 04813 if (iaxs[x]) { 04814 int lag, jitter, localdelay; 04815 jb_info jbinfo; 04816 04817 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04818 jb_getinfo(iaxs[x]->jb, &jbinfo); 04819 jitter = jbinfo.jitter; 04820 localdelay = jbinfo.current - jbinfo.min; 04821 } else { 04822 jitter = -1; 04823 localdelay = 0; 04824 } 04825 lag = iaxs[x]->remote_rr.delay; 04826 ast_cli(fd, FORMAT, 04827 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04828 ast_inet_ntoa(iaxs[x]->addr.sin_addr), 04829 S_OR(iaxs[x]->username, "(None)"), 04830 iaxs[x]->callno, iaxs[x]->peercallno, 04831 iaxs[x]->oseqno, iaxs[x]->iseqno, 04832 lag, 04833 jitter, 04834 localdelay, 04835 ast_getformatname(iaxs[x]->voiceformat) ); 04836 numchans++; 04837 } 04838 ast_mutex_unlock(&iaxsl[x]); 04839 } 04840 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04841 return RESULT_SUCCESS; 04842 #undef FORMAT 04843 #undef FORMAT2 04844 #undef FORMATB 04845 }
static int iax2_show_firmware | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4711 of file chan_iax2.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, FORMAT, FORMAT2, iax_firmware::fwh, ast_firmware_list::lock, iax_firmware::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
04712 { 04713 #define FORMAT2 "%-15.15s %-15.15s %-15.15s\n" 04714 #if !defined(__FreeBSD__) 04715 #define FORMAT "%-15.15s %-15d %-15d\n" 04716 #else /* __FreeBSD__ */ 04717 #define FORMAT "%-15.15s %-15d %-15d\n" /* XXX 2.95 ? */ 04718 #endif /* __FreeBSD__ */ 04719 struct iax_firmware *cur; 04720 if ((argc != 3) && (argc != 4)) 04721 return RESULT_SHOWUSAGE; 04722 ast_mutex_lock(&waresl.lock); 04723 04724 ast_cli(fd, FORMAT2, "Device", "Version", "Size"); 04725 for (cur = waresl.wares;cur;cur = cur->next) { 04726 if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 04727 ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version), 04728 (int)ntohl(cur->fwh->datalen)); 04729 } 04730 ast_mutex_unlock(&waresl.lock); 04731 return RESULT_SUCCESS; 04732 #undef FORMAT 04733 #undef FORMAT2 04734 }
static int iax2_show_netstats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4923 of file chan_iax2.c.
References ast_cli(), ast_cli_netstats(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04924 { 04925 int numchans = 0; 04926 if (argc != 3) 04927 return RESULT_SHOWUSAGE; 04928 ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); 04929 ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n"); 04930 numchans = ast_cli_netstats(NULL, fd, 1); 04931 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04932 return RESULT_SUCCESS; 04933 }
static int iax2_show_peer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Show one peer in detail.
Definition at line 2333 of file chan_iax2.c.
References iax2_peer::addr, ast_callerid_merge(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, iax2_peer::capability, iax2_peer::defaddr, iax2_peer::expire, find_peer(), iax2_peer::ha, IAX_DYNAMIC, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_peer::prefs, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax2_peer::smoothing.
02334 { 02335 char status[30]; 02336 char cbuf[256]; 02337 struct iax2_peer *peer; 02338 char codec_buf[512]; 02339 int x = 0, codec = 0, load_realtime = 0; 02340 02341 if (argc < 4) 02342 return RESULT_SHOWUSAGE; 02343 02344 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0; 02345 02346 peer = find_peer(argv[3], load_realtime); 02347 if (peer) { 02348 ast_cli(fd,"\n\n"); 02349 ast_cli(fd, " * Name : %s\n", peer->name); 02350 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 02351 ast_cli(fd, " Context : %s\n", peer->context); 02352 ast_cli(fd, " Mailbox : %s\n", peer->mailbox); 02353 ast_cli(fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No"); 02354 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 02355 ast_cli(fd, " Expire : %d\n", peer->expire); 02356 ast_cli(fd, " ACL : %s\n", (peer->ha?"Yes":"No")); 02357 ast_cli(fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port)); 02358 ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 02359 ast_cli(fd, " Username : %s\n", peer->username); 02360 ast_cli(fd, " Codecs : "); 02361 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 02362 ast_cli(fd, "%s\n", codec_buf); 02363 02364 ast_cli(fd, " Codec Order : ("); 02365 for(x = 0; x < 32 ; x++) { 02366 codec = ast_codec_pref_index(&peer->prefs,x); 02367 if(!codec) 02368 break; 02369 ast_cli(fd, "%s", ast_getformatname(codec)); 02370 if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) 02371 ast_cli(fd, "|"); 02372 } 02373 02374 if (!x) 02375 ast_cli(fd, "none"); 02376 ast_cli(fd, ")\n"); 02377 02378 ast_cli(fd, " Status : "); 02379 peer_status(peer, status, sizeof(status)); 02380 ast_cli(fd, "%s\n",status); 02381 ast_cli(fd, " Qualify : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off"); 02382 ast_cli(fd,"\n"); 02383 peer_unref(peer); 02384 } else { 02385 ast_cli(fd,"Peer %s not found.\n", argv[3]); 02386 ast_cli(fd,"\n"); 02387 } 02388 02389 return RESULT_SUCCESS; 02390 }
static int iax2_show_peers | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4700 of file chan_iax2.c.
References __iax2_show_peers().
04701 { 04702 return __iax2_show_peers(0, fd, NULL, argc, argv); 04703 }
static int iax2_show_registry | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4772 of file chan_iax2.c.
References iax2_registry::addr, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax2_registry::dnsmgr, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), RESULT_SHOWUSAGE, RESULT_SUCCESS, iax2_registry::us, and iax2_registry::username.
04773 { 04774 #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" 04775 #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" 04776 struct iax2_registry *reg = NULL; 04777 04778 char host[80]; 04779 char perceived[80]; 04780 if (argc != 3) 04781 return RESULT_SHOWUSAGE; 04782 ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); 04783 AST_LIST_LOCK(®istrations); 04784 AST_LIST_TRAVERSE(®istrations, reg, entry) { 04785 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); 04786 if (reg->us.sin_addr.s_addr) 04787 snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 04788 else 04789 ast_copy_string(perceived, "<Unregistered>", sizeof(perceived)); 04790 ast_cli(fd, FORMAT, host, 04791 (reg->dnsmgr) ? "Y" : "N", 04792 reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); 04793 } 04794 AST_LIST_UNLOCK(®istrations); 04795 return RESULT_SUCCESS; 04796 #undef FORMAT 04797 #undef FORMAT2 04798 }
static int iax2_show_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2417 of file chan_iax2.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::final, iax_get_frames(), iax_get_iframes(), iax_get_oframes(), iaxq, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax_frame::retries.
02418 { 02419 struct iax_frame *cur; 02420 int cnt = 0, dead=0, final=0; 02421 02422 if (argc != 3) 02423 return RESULT_SHOWUSAGE; 02424 02425 AST_LIST_LOCK(&iaxq.queue); 02426 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 02427 if (cur->retries < 0) 02428 dead++; 02429 if (cur->final) 02430 final++; 02431 cnt++; 02432 } 02433 AST_LIST_UNLOCK(&iaxq.queue); 02434 02435 ast_cli(fd, " IAX Statistics\n"); 02436 ast_cli(fd, "---------------------\n"); 02437 ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); 02438 ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); 02439 02440 return RESULT_SUCCESS; 02441 }
static int iax2_show_threads | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4641 of file chan_iax2.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, IAX_TYPE_DYNAMIC, iaxthreadcount, RESULT_SHOWUSAGE, RESULT_SUCCESS, t, and thread.
04642 { 04643 struct iax2_thread *thread = NULL; 04644 time_t t; 04645 int threadcount = 0, dynamiccount = 0; 04646 char type; 04647 04648 if (argc != 3) 04649 return RESULT_SHOWUSAGE; 04650 04651 ast_cli(fd, "IAX2 Thread Information\n"); 04652 time(&t); 04653 ast_cli(fd, "Idle Threads:\n"); 04654 AST_LIST_LOCK(&idle_list); 04655 AST_LIST_TRAVERSE(&idle_list, thread, list) { 04656 #ifdef DEBUG_SCHED_MULTITHREAD 04657 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04658 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04659 #else 04660 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04661 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04662 #endif 04663 threadcount++; 04664 } 04665 AST_LIST_UNLOCK(&idle_list); 04666 ast_cli(fd, "Active Threads:\n"); 04667 AST_LIST_LOCK(&active_list); 04668 AST_LIST_TRAVERSE(&active_list, thread, list) { 04669 if (thread->type == IAX_TYPE_DYNAMIC) 04670 type = 'D'; 04671 else 04672 type = 'P'; 04673 #ifdef DEBUG_SCHED_MULTITHREAD 04674 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 04675 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04676 #else 04677 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 04678 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04679 #endif 04680 threadcount++; 04681 } 04682 AST_LIST_UNLOCK(&active_list); 04683 ast_cli(fd, "Dynamic Threads:\n"); 04684 AST_LIST_LOCK(&dynamic_list); 04685 AST_LIST_TRAVERSE(&dynamic_list, thread, list) { 04686 #ifdef DEBUG_SCHED_MULTITHREAD 04687 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04688 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04689 #else 04690 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04691 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04692 #endif 04693 dynamiccount++; 04694 } 04695 AST_LIST_UNLOCK(&dynamic_list); 04696 ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount); 04697 return RESULT_SUCCESS; 04698 }
static int iax2_show_users | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4458 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_strlen_zero(), ast_test_flag, iax2_user::authmethods, iax2_context::context, iax2_user::contexts, FORMAT, FORMAT2, iax2_user::ha, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, RESULT_SHOWUSAGE, RESULT_SUCCESS, user_unref(), and users.
04459 { 04460 regex_t regexbuf; 04461 int havepattern = 0; 04462 04463 #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" 04464 #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" 04465 04466 struct iax2_user *user = NULL; 04467 char auth[90]; 04468 char *pstr = ""; 04469 struct ao2_iterator i; 04470 04471 switch (argc) { 04472 case 5: 04473 if (!strcasecmp(argv[3], "like")) { 04474 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04475 return RESULT_SHOWUSAGE; 04476 havepattern = 1; 04477 } else 04478 return RESULT_SHOWUSAGE; 04479 case 3: 04480 break; 04481 default: 04482 return RESULT_SHOWUSAGE; 04483 } 04484 04485 ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); 04486 i = ao2_iterator_init(users, 0); 04487 for (user = ao2_iterator_next(&i); user; 04488 user_unref(user), user = ao2_iterator_next(&i)) { 04489 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) 04490 continue; 04491 04492 if (!ast_strlen_zero(user->secret)) { 04493 ast_copy_string(auth,user->secret,sizeof(auth)); 04494 } else if (!ast_strlen_zero(user->inkeys)) { 04495 snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys); 04496 } else 04497 ast_copy_string(auth, "-no secret-", sizeof(auth)); 04498 04499 if(ast_test_flag(user,IAX_CODEC_NOCAP)) 04500 pstr = "REQ Only"; 04501 else if(ast_test_flag(user,IAX_CODEC_NOPREFS)) 04502 pstr = "Disabled"; 04503 else 04504 pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host"; 04505 04506 ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 04507 user->contexts ? user->contexts->context : context, 04508 user->ha ? "Yes" : "No", pstr); 04509 } 04510 04511 if (havepattern) 04512 regfree(®exbuf); 04513 04514 return RESULT_SUCCESS; 04515 #undef FORMAT 04516 #undef FORMAT2 04517 }
static int iax2_start_transfer | ( | unsigned short | callno0, | |
unsigned short | callno1, | |||
int | mediaonly | |||
) | [static] |
Definition at line 3438 of file chan_iax2.c.
References iax2_registry::addr, AST_FRAME_IAX, ast_random(), iax_ie_data::buf, IAX_COMMAND_TXREQ, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), IAX_IE_CALLNO, IAX_IE_TRANSFERID, iaxs, iax_ie_data::pos, send_command(), TRANSFER_BEGIN, TRANSFER_MBEGIN, and chan_iax2_pvt::transferring.
Referenced by iax2_bridge().
03439 { 03440 int res; 03441 struct iax_ie_data ied0; 03442 struct iax_ie_data ied1; 03443 unsigned int transferid = (unsigned int)ast_random(); 03444 memset(&ied0, 0, sizeof(ied0)); 03445 iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr); 03446 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno); 03447 iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); 03448 03449 memset(&ied1, 0, sizeof(ied1)); 03450 iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr); 03451 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno); 03452 iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); 03453 03454 res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); 03455 if (res) 03456 return -1; 03457 res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); 03458 if (res) 03459 return -1; 03460 iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03461 iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03462 return 0; 03463 }
static int iax2_test_losspct | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2264 of file chan_iax2.c.
References RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02265 { 02266 if (argc != 4) 02267 return RESULT_SHOWUSAGE; 02268 02269 test_losspct = atoi(argv[3]); 02270 02271 return RESULT_SUCCESS; 02272 }
static int iax2_transfer | ( | struct ast_channel * | c, | |
const char * | dest | |||
) | [static] |
Definition at line 3684 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), iax_ie_data::buf, iax2_registry::callno, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, LOG_DEBUG, option_debug, iax_ie_data::pos, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03685 { 03686 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03687 struct iax_ie_data ied; 03688 char tmp[256], *context; 03689 ast_copy_string(tmp, dest, sizeof(tmp)); 03690 context = strchr(tmp, '@'); 03691 if (context) { 03692 *context = '\0'; 03693 context++; 03694 } 03695 memset(&ied, 0, sizeof(ied)); 03696 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp); 03697 if (context) 03698 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); 03699 if (option_debug) 03700 ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest); 03701 return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); 03702 }
static int iax2_transmit | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2723 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, iaxq, iax_frame::sentyet, and signal_condition().
Referenced by iax2_send().
02724 { 02725 /* Lock the queue and place this packet at the end */ 02726 /* By setting this to 0, the network thread will send it for us, and 02727 queue retransmission if necessary */ 02728 fr->sentyet = 0; 02729 AST_LIST_LOCK(&iaxq.queue); 02730 AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list); 02731 iaxq.count++; 02732 AST_LIST_UNLOCK(&iaxq.queue); 02733 /* Wake up the network and scheduler thread */ 02734 if (netthreadid != AST_PTHREADT_NULL) 02735 pthread_kill(netthreadid, SIGURG); 02736 signal_condition(&sched_lock, &sched_cond); 02737 return 0; 02738 }
static int iax2_trunk_expired | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [inline, static] |
Definition at line 6522 of file chan_iax2.c.
References iax2_trunk_peer::trunkact.
Referenced by timing_read().
06523 { 06524 /* Drop when trunk is about 5 seconds idle */ 06525 if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 06526 return 1; 06527 return 0; 06528 }
static int iax2_trunk_queue | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_frame * | fr | |||
) | [static] |
Definition at line 4047 of file chan_iax2.c.
References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, ast_frame::data, ast_frame::datalen, DEFAULT_TRUNKDATA, f, find_tpeer(), IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_DEBUG, LOG_WARNING, MAX_TRUNKDATA, ast_iax2_meta_trunk_mini::mini, option_debug, chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.
Referenced by iax2_send().
04048 { 04049 struct ast_frame *f; 04050 struct iax2_trunk_peer *tpeer; 04051 void *tmp, *ptr; 04052 struct ast_iax2_meta_trunk_entry *met; 04053 struct ast_iax2_meta_trunk_mini *mtm; 04054 04055 f = &fr->af; 04056 tpeer = find_tpeer(&pvt->addr, pvt->sockfd); 04057 if (tpeer) { 04058 if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) { 04059 /* Need to reallocate space */ 04060 if (tpeer->trunkdataalloc < MAX_TRUNKDATA) { 04061 if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) { 04062 ast_mutex_unlock(&tpeer->lock); 04063 return -1; 04064 } 04065 04066 tpeer->trunkdataalloc += DEFAULT_TRUNKDATA; 04067 tpeer->trunkdata = tmp; 04068 if (option_debug) 04069 ast_log(LOG_DEBUG, "Expanded trunk '%s:%d' to %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), tpeer->trunkdataalloc); 04070 } else { 04071 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)); 04072 ast_mutex_unlock(&tpeer->lock); 04073 return -1; 04074 } 04075 } 04076 04077 /* Append to meta frame */ 04078 ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen; 04079 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) { 04080 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 04081 mtm->len = htons(f->datalen); 04082 mtm->mini.callno = htons(pvt->callno); 04083 mtm->mini.ts = htons(0xffff & fr->ts); 04084 ptr += sizeof(struct ast_iax2_meta_trunk_mini); 04085 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini); 04086 } else { 04087 met = (struct ast_iax2_meta_trunk_entry *)ptr; 04088 /* Store call number and length in meta header */ 04089 met->callno = htons(pvt->callno); 04090 met->len = htons(f->datalen); 04091 /* Advance pointers/decrease length past trunk entry header */ 04092 ptr += sizeof(struct ast_iax2_meta_trunk_entry); 04093 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry); 04094 } 04095 /* Copy actual trunk data */ 04096 memcpy(ptr, f->data, f->datalen); 04097 tpeer->trunkdatalen += f->datalen; 04098 04099 tpeer->calls++; 04100 ast_mutex_unlock(&tpeer->lock); 04101 } 04102 return 0; 04103 }
static int iax2_vnak | ( | int | callno | ) | [static] |
Definition at line 6439 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_VNAK, iaxs, and send_command_immediate().
Referenced by socket_process().
06440 { 06441 return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno); 06442 }
static int iax2_write | ( | struct ast_channel * | c, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 4990 of file chan_iax2.c.
References AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, errno, error(), ast_frame::frametype, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, LOG_DEBUG, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.
04991 { 04992 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04993 int res = -1; 04994 ast_mutex_lock(&iaxsl[callno]); 04995 if (iaxs[callno]) { 04996 /* If there's an outstanding error, return failure now */ 04997 if (!iaxs[callno]->error) { 04998 if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) 04999 res = 0; 05000 /* Don't waste bandwidth sending null frames */ 05001 else if (f->frametype == AST_FRAME_NULL) 05002 res = 0; 05003 else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH)) 05004 res = 0; 05005 else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 05006 res = 0; 05007 else 05008 /* Simple, just queue for transmission */ 05009 res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0); 05010 } else { 05011 if (option_debug) 05012 ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno)); 05013 } 05014 } 05015 /* If it's already gone, just return */ 05016 ast_mutex_unlock(&iaxsl[callno]); 05017 return res; 05018 }
static int iax_check_version | ( | char * | dev | ) | [static] |
Definition at line 1898 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_iax2_firmware_header::devname, iax_firmware::fwh, ast_firmware_list::lock, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
Referenced by update_registry().
01899 { 01900 int res = 0; 01901 struct iax_firmware *cur; 01902 if (!ast_strlen_zero(dev)) { 01903 ast_mutex_lock(&waresl.lock); 01904 cur = waresl.wares; 01905 while(cur) { 01906 if (!strcmp(dev, (char *)cur->fwh->devname)) { 01907 res = ntohs(cur->fwh->version); 01908 break; 01909 } 01910 cur = cur->next; 01911 } 01912 ast_mutex_unlock(&waresl.lock); 01913 } 01914 return res; 01915 }
static void iax_debug_output | ( | const char * | data | ) | [static] |
Definition at line 764 of file chan_iax2.c.
References ast_verbose().
Referenced by load_module().
00765 { 00766 if (iaxdebug) 00767 ast_verbose("%s", data); 00768 }
static void iax_error_output | ( | const char * | data | ) | [static] |
Definition at line 770 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00771 { 00772 ast_log(LOG_WARNING, "%s", data); 00773 }
static int iax_firmware_append | ( | struct iax_ie_data * | ied, | |
const unsigned char * | dev, | |||
unsigned int | desc | |||
) | [static] |
Definition at line 1917 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, iax_firmware::fwh, iax_ie_append(), iax_ie_append_int(), iax_ie_append_raw(), IAX_IE_FWBLOCKDATA, IAX_IE_FWBLOCKDESC, ast_firmware_list::lock, iax_firmware::next, ast_firmware_list::wares, and waresl.
Referenced by socket_process().
01918 { 01919 int res = -1; 01920 unsigned int bs = desc & 0xff; 01921 unsigned int start = (desc >> 8) & 0xffffff; 01922 unsigned int bytes; 01923 struct iax_firmware *cur; 01924 if (!ast_strlen_zero((char *)dev) && bs) { 01925 start *= bs; 01926 ast_mutex_lock(&waresl.lock); 01927 cur = waresl.wares; 01928 while(cur) { 01929 if (!strcmp((char *)dev, (char *)cur->fwh->devname)) { 01930 iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc); 01931 if (start < ntohl(cur->fwh->datalen)) { 01932 bytes = ntohl(cur->fwh->datalen) - start; 01933 if (bytes > bs) 01934 bytes = bs; 01935 iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes); 01936 } else { 01937 bytes = 0; 01938 iax_ie_append(ied, IAX_IE_FWBLOCKDATA); 01939 } 01940 if (bytes == bs) 01941 res = 0; 01942 else 01943 res = 1; 01944 break; 01945 } 01946 cur = cur->next; 01947 } 01948 ast_mutex_unlock(&waresl.lock); 01949 } 01950 return res; 01951 }
static int iax_park | ( | struct ast_channel * | chan1, | |
struct ast_channel * | chan2 | |||
) | [static] |
Definition at line 6710 of file chan_iax2.c.
References ast_channel::amaflags, ast_calloc, ast_channel_alloc(), ast_channel_masquerade(), ast_do_masquerade(), ast_hangup(), ast_log(), ast_pthread_create_background, AST_STATE_DOWN, iax_dual::chan1, iax_dual::chan2, ast_channel::context, ast_channel::exten, free, iax_park_thread(), LOG_WARNING, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by socket_process().
06711 { 06712 struct iax_dual *d; 06713 struct ast_channel *chan1m, *chan2m; 06714 pthread_t th; 06715 chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 06716 chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name); 06717 if (chan2m && chan1m) { 06718 /* Make formats okay */ 06719 chan1m->readformat = chan1->readformat; 06720 chan1m->writeformat = chan1->writeformat; 06721 ast_channel_masquerade(chan1m, chan1); 06722 /* Setup the extensions and such */ 06723 ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context)); 06724 ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten)); 06725 chan1m->priority = chan1->priority; 06726 06727 /* We make a clone of the peer channel too, so we can play 06728 back the announcement */ 06729 /* Make formats okay */ 06730 chan2m->readformat = chan2->readformat; 06731 chan2m->writeformat = chan2->writeformat; 06732 ast_channel_masquerade(chan2m, chan2); 06733 /* Setup the extensions and such */ 06734 ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context)); 06735 ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten)); 06736 chan2m->priority = chan2->priority; 06737 if (ast_do_masquerade(chan2m)) { 06738 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 06739 ast_hangup(chan2m); 06740 return -1; 06741 } 06742 } else { 06743 if (chan1m) 06744 ast_hangup(chan1m); 06745 if (chan2m) 06746 ast_hangup(chan2m); 06747 return -1; 06748 } 06749 if ((d = ast_calloc(1, sizeof(*d)))) { 06750 pthread_attr_t attr; 06751 06752 pthread_attr_init(&attr); 06753 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06754 06755 d->chan1 = chan1m; 06756 d->chan2 = chan2m; 06757 if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) { 06758 pthread_attr_destroy(&attr); 06759 return 0; 06760 } 06761 pthread_attr_destroy(&attr); 06762 free(d); 06763 } 06764 return -1; 06765 }
static void* iax_park_thread | ( | void * | stuff | ) | [static] |
Definition at line 6690 of file chan_iax2.c.
References ast_frfree, ast_hangup(), ast_log(), ast_park_call(), ast_read(), iax_dual::chan1, iax_dual::chan2, ext, f, free, and LOG_NOTICE.
Referenced by iax_park().
06691 { 06692 struct ast_channel *chan1, *chan2; 06693 struct iax_dual *d; 06694 struct ast_frame *f; 06695 int ext; 06696 int res; 06697 d = stuff; 06698 chan1 = d->chan1; 06699 chan2 = d->chan2; 06700 free(d); 06701 f = ast_read(chan1); 06702 if (f) 06703 ast_frfree(f); 06704 res = ast_park_call(chan1, chan2, 0, &ext); 06705 ast_hangup(chan2); 06706 ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext); 06707 return NULL; 06708 }
Definition at line 1412 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().
01413 { 01414 struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable); 01415 if (new) { 01416 size_t afdatalen = new->afdatalen; 01417 memcpy(new, fr, sizeof(*new)); 01418 iax_frame_wrap(new, &fr->af); 01419 new->afdatalen = afdatalen; 01420 new->data = NULL; 01421 new->datalen = 0; 01422 new->direction = DIRECTION_INGRESS; 01423 new->retrans = -1; 01424 } 01425 return new; 01426 }
static void insert_idle_thread | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 894 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, and IAX_TYPE_DYNAMIC.
Referenced by iax2_process_thread().
00895 { 00896 if (thread->type == IAX_TYPE_DYNAMIC) { 00897 AST_LIST_LOCK(&dynamic_list); 00898 AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); 00899 AST_LIST_UNLOCK(&dynamic_list); 00900 } else { 00901 AST_LIST_LOCK(&idle_list); 00902 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 00903 AST_LIST_UNLOCK(&idle_list); 00904 } 00905 00906 return; 00907 }
static void jb_debug_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 799 of file chan_iax2.c.
References ast_verbose().
Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().
00800 { 00801 va_list args; 00802 char buf[1024]; 00803 00804 va_start(args, fmt); 00805 vsnprintf(buf, 1024, fmt, args); 00806 va_end(args); 00807 00808 ast_verbose(buf); 00809 }
static void jb_error_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 775 of file chan_iax2.c.
References ast_log(), and LOG_ERROR.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00776 { 00777 va_list args; 00778 char buf[1024]; 00779 00780 va_start(args, fmt); 00781 vsnprintf(buf, 1024, fmt, args); 00782 va_end(args); 00783 00784 ast_log(LOG_ERROR, buf); 00785 }
static void jb_warning_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 787 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00788 { 00789 va_list args; 00790 char buf[1024]; 00791 00792 va_start(args, fmt); 00793 vsnprintf(buf, 1024, fmt, args); 00794 va_end(args); 00795 00796 ast_log(LOG_WARNING, buf); 00797 }
static int load_module | ( | void | ) | [static] |
Load IAX2 module, load configuraiton ---.
Definition at line 11080 of file chan_iax2.c.
References __unload_module(), ao2_callback(), ao2_container_alloc(), ao2_ref(), ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register(), AST_LIST_HEAD_INIT, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_register_application(), ast_register_switch(), ast_verbose(), cli_iax2, config, errno, iax2_do_register(), iax2_poke_peer_cb(), iax2_prov_app(), iax2_switch, iax2_tech, iax_debug_output(), iax_error_output(), IAX_MAX_CALLS, iax_peercallno_pvts, iax_provision_reload(), iax_set_error(), iax_set_output(), iaxpeer_function, iaxq, iaxs, iaxsl, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, option_verbose, papp, pdescrip, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, psyn, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.
11081 { 11082 char *config = "iax.conf"; 11083 int res = 0; 11084 int x; 11085 struct iax2_registry *reg = NULL; 11086 11087 peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb); 11088 if (!peers) 11089 return AST_MODULE_LOAD_FAILURE; 11090 users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb); 11091 if (!users) { 11092 ao2_ref(peers, -1); 11093 return AST_MODULE_LOAD_FAILURE; 11094 } 11095 iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb); 11096 if (!iax_peercallno_pvts) { 11097 ao2_ref(peers, -1); 11098 ao2_ref(users, -1); 11099 return AST_MODULE_LOAD_FAILURE; 11100 } 11101 11102 ast_custom_function_register(&iaxpeer_function); 11103 11104 iax_set_output(iax_debug_output); 11105 iax_set_error(iax_error_output); 11106 jb_setoutput(jb_error_output, jb_warning_output, NULL); 11107 11108 #ifdef HAVE_ZAPTEL 11109 #ifdef ZT_TIMERACK 11110 timingfd = open("/dev/zap/timer", O_RDWR); 11111 if (timingfd < 0) 11112 #endif 11113 timingfd = open("/dev/zap/pseudo", O_RDWR); 11114 if (timingfd < 0) 11115 ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno)); 11116 #endif 11117 11118 memset(iaxs, 0, sizeof(iaxs)); 11119 11120 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 11121 ast_mutex_init(&iaxsl[x]); 11122 } 11123 11124 ast_cond_init(&sched_cond, NULL); 11125 11126 io = io_context_create(); 11127 sched = sched_context_create(); 11128 11129 if (!io || !sched) { 11130 ast_log(LOG_ERROR, "Out of memory\n"); 11131 return -1; 11132 } 11133 11134 netsock = ast_netsock_list_alloc(); 11135 if (!netsock) { 11136 ast_log(LOG_ERROR, "Could not allocate netsock list.\n"); 11137 return -1; 11138 } 11139 ast_netsock_init(netsock); 11140 11141 outsock = ast_netsock_list_alloc(); 11142 if (!outsock) { 11143 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 11144 return -1; 11145 } 11146 ast_netsock_init(outsock); 11147 11148 ast_mutex_init(&waresl.lock); 11149 11150 AST_LIST_HEAD_INIT(&iaxq.queue); 11151 11152 ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 11153 11154 ast_register_application(papp, iax2_prov_app, psyn, pdescrip); 11155 11156 ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" ); 11157 ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" ); 11158 11159 if(set_config(config, 0) == -1) 11160 return AST_MODULE_LOAD_DECLINE; 11161 11162 if (ast_channel_register(&iax2_tech)) { 11163 ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2"); 11164 __unload_module(); 11165 return -1; 11166 } 11167 11168 if (ast_register_switch(&iax2_switch)) 11169 ast_log(LOG_ERROR, "Unable to register IAX switch\n"); 11170 11171 res = start_network_thread(); 11172 if (!res) { 11173 if (option_verbose > 1) 11174 ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n"); 11175 } else { 11176 ast_log(LOG_ERROR, "Unable to start network thread\n"); 11177 ast_netsock_release(netsock); 11178 ast_netsock_release(outsock); 11179 } 11180 11181 AST_LIST_LOCK(®istrations); 11182 AST_LIST_TRAVERSE(®istrations, reg, entry) 11183 iax2_do_register(reg); 11184 AST_LIST_UNLOCK(®istrations); 11185 11186 ao2_callback(peers, 0, peer_set_sock_cb, NULL); 11187 ao2_callback(peers, 0, iax2_poke_peer_cb, NULL); 11188 11189 reload_firmware(0); 11190 iax_provision_reload(); 11191 return res; 11192 }
static void lock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3465 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), DEADLOCK_AVOIDANCE, and iaxsl.
Referenced by iax2_bridge().
03466 { 03467 ast_mutex_lock(&iaxsl[callno0]); 03468 while (ast_mutex_trylock(&iaxsl[callno1])) { 03469 DEADLOCK_AVOIDANCE(&iaxsl[callno0]); 03470 } 03471 }
static int make_trunk | ( | unsigned short | callno, | |
int | locked | |||
) | [static] |
Definition at line 1466 of file chan_iax2.c.
References ARRAY_LEN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, chan_iax2_pvt::callno, iax2_sched_add(), iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, option_debug, chan_iax2_pvt::pingid, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().
Referenced by iax2_request(), and socket_process().
01467 { 01468 int x; 01469 int res= 0; 01470 struct timeval now; 01471 if (iaxs[callno]->oseqno) { 01472 ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n"); 01473 return -1; 01474 } 01475 if (callno & TRUNK_CALL_START) { 01476 ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno); 01477 return -1; 01478 } 01479 gettimeofday(&now, NULL); 01480 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01481 ast_mutex_lock(&iaxsl[x]); 01482 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01483 iaxs[x] = iaxs[callno]; 01484 iaxs[x]->callno = x; 01485 iaxs[callno] = NULL; 01486 /* Update the two timers that should have been started */ 01487 AST_SCHED_DEL(sched, iaxs[x]->pingid); 01488 AST_SCHED_DEL(sched, iaxs[x]->lagid); 01489 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01490 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01491 if (locked) 01492 ast_mutex_unlock(&iaxsl[callno]); 01493 res = x; 01494 if (!locked) 01495 ast_mutex_unlock(&iaxsl[x]); 01496 break; 01497 } 01498 ast_mutex_unlock(&iaxsl[x]); 01499 } 01500 if (x >= ARRAY_LEN(iaxs) - 1) { 01501 ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n"); 01502 return -1; 01503 } 01504 if (option_debug) 01505 ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x); 01506 /* We move this call from a non-trunked to a trunked call */ 01507 update_max_trunk(); 01508 update_max_nontrunk(); 01509 return res; 01510 }
static int manager_iax2_show_netstats | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4704 of file chan_iax2.c.
References ast_cli_netstats(), astman_append(), and RESULT_SUCCESS.
Referenced by load_module().
04705 { 04706 ast_cli_netstats(s, -1, 0); 04707 astman_append(s, "\r\n"); 04708 return RESULT_SUCCESS; 04709 }
static int manager_iax2_show_peers | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4737 of file chan_iax2.c.
References __iax2_show_peers(), ast_strlen_zero(), astman_append(), and astman_get_header().
Referenced by load_module().
04738 { 04739 char *a[] = { "iax2", "show", "users" }; 04740 int ret; 04741 const char *id = astman_get_header(m,"ActionID"); 04742 04743 if (!ast_strlen_zero(id)) 04744 astman_append(s, "ActionID: %s\r\n",id); 04745 ret = __iax2_show_peers(1, -1, s, 3, a ); 04746 astman_append(s, "\r\n\r\n" ); 04747 return ret; 04748 } /* /JDG */
static int match | ( | struct sockaddr_in * | sin, | |
unsigned short | callno, | |||
unsigned short | dcallno, | |||
struct chan_iax2_pvt * | cur, | |||
int | check_dcallno | |||
) | [static] |
Definition at line 1432 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::callno, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, and chan_iax2_pvt::transferring.
Referenced by __find_callno(), ao2_callback(), ast_parse_device_state(), check_blacklist(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and softhangup_exec().
01433 { 01434 if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && 01435 (cur->addr.sin_port == sin->sin_port)) { 01436 /* This is the main host */ 01437 if ( (cur->peercallno == 0 || cur->peercallno == callno) && 01438 (check_dcallno ? dcallno == cur->callno : 1) ) { 01439 /* That's us. Be sure we keep track of the peer call number */ 01440 return 1; 01441 } 01442 } 01443 if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && 01444 (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { 01445 /* We're transferring */ 01446 if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno)) 01447 return 1; 01448 } 01449 return 0; 01450 }
static void memcpy_decrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 4111 of file chan_iax2.c.
References aes_decrypt(), ast_log(), and LOG_WARNING.
Referenced by decode_frame().
04112 { 04113 #if 0 04114 /* Debug with "fake encryption" */ 04115 int x; 04116 if (len % 16) 04117 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04118 for (x=0;x<len;x++) 04119 dst[x] = src[x] ^ 0xff; 04120 #else 04121 unsigned char lastblock[16] = { 0 }; 04122 int x; 04123 while(len > 0) { 04124 aes_decrypt(src, dst, dcx); 04125 for (x=0;x<16;x++) 04126 dst[x] ^= lastblock[x]; 04127 memcpy(lastblock, src, sizeof(lastblock)); 04128 dst += 16; 04129 src += 16; 04130 len -= 16; 04131 } 04132 #endif 04133 }
static void memcpy_encrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
aes_encrypt_ctx * | ecx | |||
) | [static] |
Definition at line 4135 of file chan_iax2.c.
References aes_encrypt(), ast_log(), and LOG_WARNING.
Referenced by encrypt_frame().
04136 { 04137 #if 0 04138 /* Debug with "fake encryption" */ 04139 int x; 04140 if (len % 16) 04141 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04142 for (x=0;x<len;x++) 04143 dst[x] = src[x] ^ 0xff; 04144 #else 04145 unsigned char curblock[16] = { 0 }; 04146 int x; 04147 while(len > 0) { 04148 for (x=0;x<16;x++) 04149 curblock[x] ^= src[x]; 04150 aes_encrypt(curblock, dst, ecx); 04151 memcpy(curblock, dst, sizeof(curblock)); 04152 dst += 16; 04153 src += 16; 04154 len -= 16; 04155 } 04156 #endif 04157 }
static void merge_encryption | ( | struct chan_iax2_pvt * | p, | |
unsigned int | enc | |||
) | [static] |
Definition at line 5315 of file chan_iax2.c.
References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.
Referenced by authenticate_reply(), and socket_process().
05316 { 05317 /* Select exactly one common encryption if there are any */ 05318 p->encmethods &= enc; 05319 if (p->encmethods) { 05320 if (p->encmethods & IAX_ENCRYPT_AES128) 05321 p->encmethods = IAX_ENCRYPT_AES128; 05322 else 05323 p->encmethods = 0; 05324 } 05325 }
static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 9053 of file chan_iax2.c.
References ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, f, iax2_sched_add(), iax_frame_free(), iaxq, iaxs, iaxsl, LOG_DEBUG, option_debug, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_packet(), iax_frame::sentyet, and timing_read().
Referenced by start_network_thread().
09054 { 09055 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 09056 from the network, and queue them for delivery to the channels */ 09057 int res, count, wakeup; 09058 struct iax_frame *f; 09059 09060 if (timingfd > -1) 09061 ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL); 09062 09063 for(;;) { 09064 pthread_testcancel(); 09065 09066 /* Go through the queue, sending messages which have not yet been 09067 sent, and scheduling retransmissions if appropriate */ 09068 AST_LIST_LOCK(&iaxq.queue); 09069 count = 0; 09070 wakeup = -1; 09071 AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) { 09072 if (f->sentyet) 09073 continue; 09074 09075 /* Try to lock the pvt, if we can't... don't fret - defer it till later */ 09076 if (ast_mutex_trylock(&iaxsl[f->callno])) { 09077 wakeup = 1; 09078 continue; 09079 } 09080 09081 f->sentyet++; 09082 09083 if (iaxs[f->callno]) { 09084 send_packet(f); 09085 count++; 09086 } 09087 09088 ast_mutex_unlock(&iaxsl[f->callno]); 09089 09090 if (f->retries < 0) { 09091 /* This is not supposed to be retransmitted */ 09092 AST_LIST_REMOVE_CURRENT(&iaxq.queue, list); 09093 iaxq.count--; 09094 /* Free the iax frame */ 09095 iax_frame_free(f); 09096 } else { 09097 /* We need reliable delivery. Schedule a retransmission */ 09098 f->retries++; 09099 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 09100 } 09101 } 09102 AST_LIST_TRAVERSE_SAFE_END 09103 AST_LIST_UNLOCK(&iaxq.queue); 09104 09105 pthread_testcancel(); 09106 09107 if (option_debug && count >= 20) 09108 ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count); 09109 09110 /* Now do the IO, and run scheduled tasks */ 09111 res = ast_io_wait(io, wakeup); 09112 if (res >= 0) { 09113 if (option_debug && res >= 20) 09114 ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res); 09115 } 09116 } 09117 return NULL; 09118 }
static struct chan_iax2_pvt* new_iax | ( | struct sockaddr_in * | sin, | |
const char * | host | |||
) | [static, read] |
Definition at line 1373 of file chan_iax2.c.
References ao2_alloc(), ao2_ref(), ast_string_field_init, ast_string_field_set, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, chan_iax2_pvt::bridgecallno, chan_iax2_pvt::callno, exten, chan_iax2_pvt::initid, chan_iax2_pvt::jb, jb_new(), jb_setconf(), chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, prefs, chan_iax2_pvt::prefs, pvt_destructor(), jb_conf::resync_threshold, and chan_iax2_pvt::transfercallno.
Referenced by __find_callno().
01374 { 01375 struct chan_iax2_pvt *tmp; 01376 jb_conf jbconf; 01377 01378 if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) { 01379 return NULL; 01380 } 01381 01382 if (ast_string_field_init(tmp, 32)) { 01383 ao2_ref(tmp, -1); 01384 tmp = NULL; 01385 return NULL; 01386 } 01387 01388 tmp->prefs = prefs; 01389 tmp->callno = 0; 01390 tmp->peercallno = 0; 01391 tmp->transfercallno = 0; 01392 tmp->bridgecallno = 0; 01393 tmp->pingid = -1; 01394 tmp->lagid = -1; 01395 tmp->autoid = -1; 01396 tmp->authid = -1; 01397 tmp->initid = -1; 01398 01399 ast_string_field_set(tmp,exten, "s"); 01400 ast_string_field_set(tmp,host, host); 01401 01402 tmp->jb = jb_new(); 01403 tmp->jbid = -1; 01404 jbconf.max_jitterbuf = maxjitterbuffer; 01405 jbconf.resync_threshold = resyncthreshold; 01406 jbconf.max_contig_interp = maxjitterinterps; 01407 jb_setconf(tmp->jb,&jbconf); 01408 01409 return tmp; 01410 }
static void parse_dial_string | ( | char * | data, | |
struct parsed_dial_string * | pds | |||
) | [static] |
Parses an IAX dial string into its component parts.
data | the string to be parsed | |
pds | pointer to a struct parsed_dial_string to be filled in |
The dial string format is: [username[:password]@]peer[:port][/exten[@context]][/options]
Definition at line 3183 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().
03184 { 03185 if (ast_strlen_zero(data)) 03186 return; 03187 03188 pds->peer = strsep(&data, "/"); 03189 pds->exten = strsep(&data, "/"); 03190 pds->options = data; 03191 03192 if (pds->exten) { 03193 data = pds->exten; 03194 pds->exten = strsep(&data, "@"); 03195 pds->context = data; 03196 } 03197 03198 if (strchr(pds->peer, '@')) { 03199 data = pds->peer; 03200 pds->username = strsep(&data, "@"); 03201 pds->peer = data; 03202 } 03203 03204 if (pds->username) { 03205 data = pds->username; 03206 pds->username = strsep(&data, ":"); 03207 pds->password = data; 03208 } 03209 03210 data = pds->peer; 03211 pds->peer = strsep(&data, ":"); 03212 pds->port = data; 03213 03214 /* check for a key name wrapped in [] in the secret position, if found, 03215 move it to the key field instead 03216 */ 03217 if (pds->password && (pds->password[0] == '[')) { 03218 pds->key = ast_strip_quoted(pds->password, "[", "]"); 03219 pds->password = NULL; 03220 } 03221 }
static int peer_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1111 of file chan_iax2.c.
Referenced by load_module().
01112 { 01113 struct iax2_peer *peer = obj, *peer2 = arg; 01114 01115 return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0; 01116 }
static int peer_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 9751 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
09752 { 09753 struct iax2_peer *peer = obj; 09754 09755 ast_set_flag(peer, IAX_DELME); 09756 09757 return 0; 09758 }
static void peer_destructor | ( | void * | obj | ) | [static] |
Definition at line 9276 of file chan_iax2.c.
References ast_dnsmgr_release(), ast_free_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_free_memory, iax2_peer::callno, iax2_peer::dnsmgr, iax2_peer::ha, iax2_destroy(), iaxsl, and register_peer_exten().
Referenced by build_peer().
09277 { 09278 struct iax2_peer *peer = obj; 09279 09280 ast_free_ha(peer->ha); 09281 09282 if (peer->callno > 0) { 09283 ast_mutex_lock(&iaxsl[peer->callno]); 09284 iax2_destroy(peer->callno); 09285 ast_mutex_unlock(&iaxsl[peer->callno]); 09286 } 09287 09288 register_peer_exten(peer, 0); 09289 09290 if (peer->dnsmgr) 09291 ast_dnsmgr_release(peer->dnsmgr); 09292 09293 ast_string_field_free_memory(peer); 09294 }
static int peer_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1101 of file chan_iax2.c.
References ast_str_hash().
Referenced by load_module().
01102 { 01103 const struct iax2_peer *peer = obj; 01104 01105 return ast_str_hash(peer->name); 01106 }
Definition at line 1158 of file chan_iax2.c.
References ao2_ref().
Referenced by __iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), realtime_peer(), reg_source_db(), socket_process(), and update_registry().
01159 { 01160 ao2_ref(peer, +1); 01161 return peer; 01162 }
static int peer_set_sock_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11051 of file chan_iax2.c.
References iax2_peer::sockfd.
Referenced by load_module().
11052 { 11053 struct iax2_peer *peer = obj; 11054 11055 if (peer->sockfd < 0) 11056 peer->sockfd = defaultsockfd; 11057 11058 return 0; 11059 }
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 9203 of file chan_iax2.c.
References iax2_registry::addr, ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, LOG_DEBUG, LOG_WARNING, option_debug, socket_read(), iax2_peer::sockfd, and strsep().
Referenced by build_peer().
09204 { 09205 struct sockaddr_in sin; 09206 int nonlocal = 1; 09207 int port = IAX_DEFAULT_PORTNO; 09208 int sockfd = defaultsockfd; 09209 char *tmp; 09210 char *addr; 09211 char *portstr; 09212 09213 if (!(tmp = ast_strdupa(srcaddr))) 09214 return -1; 09215 09216 addr = strsep(&tmp, ":"); 09217 portstr = tmp; 09218 09219 if (portstr) { 09220 port = atoi(portstr); 09221 if (port < 1) 09222 port = IAX_DEFAULT_PORTNO; 09223 } 09224 09225 if (!ast_get_ip(&sin, addr)) { 09226 struct ast_netsock *sock; 09227 int res; 09228 09229 sin.sin_port = 0; 09230 sin.sin_family = AF_INET; 09231 res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin)); 09232 if (res == 0) { 09233 /* ip address valid. */ 09234 sin.sin_port = htons(port); 09235 if (!(sock = ast_netsock_find(netsock, &sin))) 09236 sock = ast_netsock_find(outsock, &sin); 09237 if (sock) { 09238 sockfd = ast_netsock_sockfd(sock); 09239 nonlocal = 0; 09240 } else { 09241 unsigned int orig_saddr = sin.sin_addr.s_addr; 09242 /* INADDR_ANY matches anyway! */ 09243 sin.sin_addr.s_addr = INADDR_ANY; 09244 if (ast_netsock_find(netsock, &sin)) { 09245 sin.sin_addr.s_addr = orig_saddr; 09246 sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL); 09247 if (sock) { 09248 sockfd = ast_netsock_sockfd(sock); 09249 ast_netsock_unref(sock); 09250 nonlocal = 0; 09251 } else { 09252 nonlocal = 2; 09253 } 09254 } 09255 } 09256 } 09257 } 09258 09259 peer->sockfd = sockfd; 09260 09261 if (nonlocal == 1) { 09262 ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", 09263 srcaddr, peer->name); 09264 return -1; 09265 } else if (nonlocal == 2) { 09266 ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n", 09267 srcaddr, peer->name); 09268 return -1; 09269 } else { 09270 if (option_debug) 09271 ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); 09272 return 0; 09273 } 09274 }
static int peer_status | ( | struct iax2_peer * | peer, | |
char * | status, | |||
int | statuslen | |||
) | [static] |
peer_status: Report Peer status in character string
Definition at line 2310 of file chan_iax2.c.
References iax2_peer::lastms, and iax2_peer::maxms.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), function_iaxpeer(), function_sippeer(), and iax2_show_peer().
02311 { 02312 int res = 0; 02313 if (peer->maxms) { 02314 if (peer->lastms < 0) { 02315 ast_copy_string(status, "UNREACHABLE", statuslen); 02316 } else if (peer->lastms > peer->maxms) { 02317 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 02318 res = 1; 02319 } else if (peer->lastms) { 02320 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 02321 res = 1; 02322 } else { 02323 ast_copy_string(status, "UNKNOWN", statuslen); 02324 } 02325 } else { 02326 ast_copy_string(status, "Unmonitored", statuslen); 02327 res = -1; 02328 } 02329 return res; 02330 }
Definition at line 1164 of file chan_iax2.c.
References ao2_ref().
Referenced by __expire_registry(), __iax2_poke_noanswer(), __iax2_poke_peer_s(), __iax2_show_peers(), authenticate_reply(), build_peer(), complete_iax2_show_peer(), create_addr(), function_iaxpeer(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), iax2_show_peer(), poke_all_peers(), prune_peers(), realtime_peer(), reg_source_db(), register_verify(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().
01165 { 01166 ao2_ref(peer, -1); 01167 return NULL; 01168 }
static void poke_all_peers | ( | void | ) | [static] |
Definition at line 10212 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), iax2_poke_peer(), peer_unref(), and peers.
Referenced by reload_config().
10213 { 10214 struct ao2_iterator i; 10215 struct iax2_peer *peer; 10216 10217 i = ao2_iterator_init(peers, 0); 10218 while ((peer = ao2_iterator_next(&i))) { 10219 iax2_poke_peer(peer, 0); 10220 peer_unref(peer); 10221 } 10222 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 9809 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_DELME, peer_unref(), peers, and unlink_peer().
09810 { 09811 struct iax2_peer *peer; 09812 struct ao2_iterator i; 09813 09814 i = ao2_iterator_init(peers, 0); 09815 while ((peer = ao2_iterator_next(&i))) { 09816 if (ast_test_flag(peer, IAX_DELME)) 09817 unlink_peer(peer); 09818 peer_unref(peer); 09819 } 09820 }
static void prune_users | ( | void | ) | [static] |
Definition at line 9795 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ao2_unlink(), ast_test_flag, IAX_DELME, user_unref(), and users.
Referenced by reload_config().
09796 { 09797 struct iax2_user *user; 09798 struct ao2_iterator i; 09799 09800 i = ao2_iterator_init(users, 0); 09801 while ((user = ao2_iterator_next(&i))) { 09802 if (ast_test_flag(user, IAX_DELME)) 09803 ao2_unlink(users, user); 09804 user_unref(user); 09805 } 09806 }
static int pvt_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11068 of file chan_iax2.c.
References chan_iax2_pvt::frames_received, and match().
Referenced by load_module().
11069 { 11070 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 11071 11072 /* The frames_received field is used to hold whether we're matching 11073 * against a full frame or not ... */ 11074 11075 return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 11076 pvt2->frames_received) ? CMP_MATCH : 0; 11077 }
static void pvt_destructor | ( | void * | obj | ) | [static] |
Definition at line 1334 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_set_flag, ast_string_field_free_memory, ast_variables_destroy(), iax2_registry::callno, chan_iax2_pvt::callno, iax_frame::callno, jb_frame::data, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, iaxq, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, and chan_iax2_pvt::vars.
Referenced by new_iax().
01335 { 01336 struct chan_iax2_pvt *pvt = obj; 01337 struct iax_frame *cur = NULL; 01338 01339 iax2_destroy_helper(pvt); 01340 01341 /* Already gone */ 01342 ast_set_flag(pvt, IAX_ALREADYGONE); 01343 01344 AST_LIST_LOCK(&iaxq.queue); 01345 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 01346 /* Cancel any pending transmissions */ 01347 if (cur->callno == pvt->callno) { 01348 cur->retries = -1; 01349 } 01350 } 01351 AST_LIST_UNLOCK(&iaxq.queue); 01352 01353 if (pvt->reg) { 01354 pvt->reg->callno = 0; 01355 } 01356 01357 if (!pvt->owner) { 01358 jb_frame frame; 01359 if (pvt->vars) { 01360 ast_variables_destroy(pvt->vars); 01361 pvt->vars = NULL; 01362 } 01363 01364 while (jb_getall(pvt->jb, &frame) == JB_OK) { 01365 iax2_frame_free(frame.data); 01366 } 01367 01368 jb_destroy(pvt->jb); 01369 ast_string_field_free_memory(pvt); 01370 } 01371 }
static int pvt_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 11061 of file chan_iax2.c.
References chan_iax2_pvt::peercallno.
Referenced by load_module().
11062 { 11063 const struct chan_iax2_pvt *pvt = obj; 11064 11065 return pvt->peercallno; 11066 }
static int raw_hangup | ( | struct sockaddr_in * | sin, | |
unsigned short | src, | |||
unsigned short | dst, | |||
int | sockfd | |||
) | [static] |
Definition at line 5297 of file chan_iax2.c.
References AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_showframe(), ast_iax2_full_hdr::iseqno, LOG_DEBUG, option_debug, ast_iax2_full_hdr::oseqno, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.
Referenced by socket_process().
05298 { 05299 struct ast_iax2_full_hdr fh; 05300 fh.scallno = htons(src | IAX_FLAG_FULL); 05301 fh.dcallno = htons(dst); 05302 fh.ts = 0; 05303 fh.oseqno = 0; 05304 fh.iseqno = 0; 05305 fh.type = AST_FRAME_IAX; 05306 fh.csub = compress_subclass(IAX_COMMAND_INVAL); 05307 if (iaxdebug) 05308 iax_showframe(NULL, &fh, 0, sin, 0); 05309 if (option_debug) 05310 ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n", 05311 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst); 05312 return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin)); 05313 }
static struct iax2_peer * realtime_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin | |||
) | [static, read] |
Definition at line 2785 of file chan_iax2.c.
References iax2_peer::addr, ast_copy_flags, ast_get_time_t(), ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_log(), ast_sched_del(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_peer(), iax2_peer::expire, expire_registry(), hp, iax2_sched_add(), IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_TEMPONLY, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, peer_ref(), peer_unref(), peers, realtime_update_peer(), reg_source_db(), ast_variable::value, and var.
02786 { 02787 struct ast_variable *var = NULL; 02788 struct ast_variable *tmp; 02789 struct iax2_peer *peer=NULL; 02790 time_t regseconds = 0, nowtime; 02791 int dynamic=0; 02792 02793 if (peername) { 02794 var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL); 02795 if (!var && sin) 02796 var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL); 02797 } else if (sin) { 02798 char porta[25]; 02799 sprintf(porta, "%d", ntohs(sin->sin_port)); 02800 var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02801 if (var) { 02802 /* We'll need the peer name in order to build the structure! */ 02803 for (tmp = var; tmp; tmp = tmp->next) { 02804 if (!strcasecmp(tmp->name, "name")) 02805 peername = tmp->value; 02806 } 02807 } 02808 } 02809 if (!var && peername) { /* Last ditch effort */ 02810 var = ast_load_realtime("iaxpeers", "name", peername, NULL); 02811 /*!\note 02812 * If this one loaded something, then we need to ensure that the host 02813 * field matched. The only reason why we can't have this as a criteria 02814 * is because we only have the IP address and the host field might be 02815 * set as a name (and the reverse PTR might not match). 02816 */ 02817 if (var && sin) { 02818 for (tmp = var; tmp; tmp = tmp->next) { 02819 if (!strcasecmp(tmp->name, "host")) { 02820 struct ast_hostent ahp; 02821 struct hostent *hp; 02822 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 02823 /* No match */ 02824 ast_variables_destroy(var); 02825 var = NULL; 02826 } 02827 break; 02828 } 02829 } 02830 } 02831 } 02832 if (!var) 02833 return NULL; 02834 02835 peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); 02836 02837 if (!peer) { 02838 ast_variables_destroy(var); 02839 return NULL; 02840 } 02841 02842 for (tmp = var; tmp; tmp = tmp->next) { 02843 /* Make sure it's not a user only... */ 02844 if (!strcasecmp(tmp->name, "type")) { 02845 if (strcasecmp(tmp->value, "friend") && 02846 strcasecmp(tmp->value, "peer")) { 02847 /* Whoops, we weren't supposed to exist! */ 02848 peer = peer_unref(peer); 02849 break; 02850 } 02851 } else if (!strcasecmp(tmp->name, "regseconds")) { 02852 ast_get_time_t(tmp->value, ®seconds, 0, NULL); 02853 } else if (!strcasecmp(tmp->name, "ipaddr")) { 02854 inet_aton(tmp->value, &(peer->addr.sin_addr)); 02855 } else if (!strcasecmp(tmp->name, "port")) { 02856 peer->addr.sin_port = htons(atoi(tmp->value)); 02857 } else if (!strcasecmp(tmp->name, "host")) { 02858 if (!strcasecmp(tmp->value, "dynamic")) 02859 dynamic = 1; 02860 } 02861 } 02862 02863 ast_variables_destroy(var); 02864 02865 if (!peer) 02866 return NULL; 02867 02868 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 02869 ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS); 02870 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) { 02871 if (peer->expire > -1) { 02872 if (!ast_sched_del(sched, peer->expire)) { 02873 peer->expire = -1; 02874 peer_unref(peer); 02875 } 02876 } 02877 peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer)); 02878 if (peer->expire == -1) 02879 peer_unref(peer); 02880 } 02881 ao2_link(peers, peer); 02882 if (ast_test_flag(peer, IAX_DYNAMIC)) 02883 reg_source_db(peer); 02884 } else { 02885 ast_set_flag(peer, IAX_TEMPONLY); 02886 } 02887 02888 if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) { 02889 time(&nowtime); 02890 if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) { 02891 memset(&peer->addr, 0, sizeof(peer->addr)); 02892 realtime_update_peer(peer->name, &peer->addr, 0); 02893 if (option_debug) 02894 ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n", 02895 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02896 } 02897 else { 02898 if (option_debug) 02899 ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n", 02900 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02901 } 02902 } 02903 02904 return peer; 02905 }
static void realtime_update_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin, | |||
time_t | regtime | |||
) | [static] |
Definition at line 2978 of file chan_iax2.c.
References ast_inet_ntoa(), and ast_update_realtime().
Referenced by __expire_registry(), realtime_peer(), update_peer(), and update_registry().
02979 { 02980 char port[10]; 02981 char regseconds[20]; 02982 02983 snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); 02984 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 02985 ast_update_realtime("iaxpeers", "name", peername, 02986 "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 02987 "regseconds", regseconds, NULL); 02988 }
static struct iax2_user* realtime_user | ( | const char * | username, | |
struct sockaddr_in * | sin | |||
) | [static, read] |
Definition at line 2907 of file chan_iax2.c.
References ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_user(), hp, IAX_RTCACHEFRIENDS, IAX_TEMPONLY, ast_variable::name, ast_variable::next, users, ast_variable::value, and var.
02908 { 02909 struct ast_variable *var; 02910 struct ast_variable *tmp; 02911 struct iax2_user *user=NULL; 02912 02913 var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL); 02914 if (!var) 02915 var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL); 02916 if (!var && sin) { 02917 char porta[6]; 02918 snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port)); 02919 var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02920 if (!var) 02921 var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02922 } 02923 if (!var) { /* Last ditch effort */ 02924 var = ast_load_realtime("iaxusers", "name", username, NULL); 02925 /*!\note 02926 * If this one loaded something, then we need to ensure that the host 02927 * field matched. The only reason why we can't have this as a criteria 02928 * is because we only have the IP address and the host field might be 02929 * set as a name (and the reverse PTR might not match). 02930 */ 02931 if (var) { 02932 for (tmp = var; tmp; tmp = tmp->next) { 02933 if (!strcasecmp(tmp->name, "host")) { 02934 struct ast_hostent ahp; 02935 struct hostent *hp; 02936 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 02937 /* No match */ 02938 ast_variables_destroy(var); 02939 var = NULL; 02940 } 02941 break; 02942 } 02943 } 02944 } 02945 } 02946 if (!var) 02947 return NULL; 02948 02949 tmp = var; 02950 while(tmp) { 02951 /* Make sure it's not a peer only... */ 02952 if (!strcasecmp(tmp->name, "type")) { 02953 if (strcasecmp(tmp->value, "friend") && 02954 strcasecmp(tmp->value, "user")) { 02955 return NULL; 02956 } 02957 } 02958 tmp = tmp->next; 02959 } 02960 02961 user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); 02962 02963 ast_variables_destroy(var); 02964 02965 if (!user) 02966 return NULL; 02967 02968 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 02969 ast_set_flag(user, IAX_RTCACHEFRIENDS); 02970 ao2_link(users, user); 02971 } else { 02972 ast_set_flag(user, IAX_TEMPONLY); 02973 } 02974 02975 return user; 02976 }
static void reg_source_db | ( | struct iax2_peer * | p | ) | [static] |
Definition at line 6078 of file chan_iax2.c.
References iax2_peer::addr, ast_db_get(), ast_device_state_changed(), ast_inet_ntoa(), ast_sched_del(), ast_test_flag, ast_verbose(), iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), IAX_TEMPONLY, option_verbose, peer_ref(), peer_unref(), register_peer_exten(), and VERBOSE_PREFIX_3.
Referenced by build_peer(), realtime_peer(), set_config(), and temp_peer().
06079 { 06080 char data[80]; 06081 struct in_addr in; 06082 char *c, *d; 06083 if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { 06084 c = strchr(data, ':'); 06085 if (c) { 06086 *c = '\0'; 06087 c++; 06088 if (inet_aton(data, &in)) { 06089 d = strchr(c, ':'); 06090 if (d) { 06091 *d = '\0'; 06092 d++; 06093 if (option_verbose > 2) 06094 ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 06095 ast_inet_ntoa(in), atoi(c), atoi(d)); 06096 iax2_poke_peer(p, 0); 06097 p->expiry = atoi(d); 06098 memset(&p->addr, 0, sizeof(p->addr)); 06099 p->addr.sin_family = AF_INET; 06100 p->addr.sin_addr = in; 06101 p->addr.sin_port = htons(atoi(c)); 06102 if (p->expire > -1) { 06103 if (!ast_sched_del(sched, p->expire)) { 06104 p->expire = -1; 06105 peer_unref(p); 06106 } 06107 } 06108 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06109 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 06110 if (p->expire == -1) 06111 peer_unref(p); 06112 if (iax2_regfunk) 06113 iax2_regfunk(p->name, 1); 06114 register_peer_exten(p, 1); 06115 } 06116 06117 } 06118 } 06119 } 06120 }
static void register_peer_exten | ( | struct iax2_peer * | peer, | |
int | onoff | |||
) | [static] |
Definition at line 5998 of file chan_iax2.c.
References ast_add_extension(), ast_context_remove_extension(), ast_exists_extension(), ast_free, ast_strdup, ast_strlen_zero(), ext, S_OR, and strsep().
Referenced by __expire_registry(), expire_register(), parse_register_contact(), peer_destructor(), reg_source_db(), sip_destroy_peer(), and update_registry().
05999 { 06000 char multi[256]; 06001 char *stringp, *ext; 06002 if (!ast_strlen_zero(regcontext)) { 06003 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 06004 stringp = multi; 06005 while((ext = strsep(&stringp, "&"))) { 06006 if (onoff) { 06007 if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL)) 06008 ast_add_extension(regcontext, 1, ext, 1, NULL, NULL, 06009 "Noop", ast_strdup(peer->name), ast_free, "IAX2"); 06010 } else 06011 ast_context_remove_extension(regcontext, ext, 1, NULL); 06012 } 06013 } 06014 }
static int register_verify | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Verify inbound registration.
Definition at line 5461 of file chan_iax2.c.
References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_device_state_changed(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, iax2_registry::expire, chan_iax2_pvt::expiry, expiry, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, IAX_STATE_UNCHANGED, iaxs, iaxsl, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, peer_unref(), iax_ies::refresh, iax_ies::rsa_result, iax2_registry::secret, strsep(), and iax_ies::username.
Referenced by handle_request_register(), and socket_process().
05462 { 05463 char requeststr[256] = ""; 05464 char peer[256] = ""; 05465 char md5secret[256] = ""; 05466 char rsasecret[256] = ""; 05467 char secret[256] = ""; 05468 struct iax2_peer *p = NULL; 05469 struct ast_key *key; 05470 char *keyn; 05471 int x; 05472 int expire = 0; 05473 int res = -1; 05474 05475 ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED); 05476 /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */ 05477 if (ies->username) 05478 ast_copy_string(peer, ies->username, sizeof(peer)); 05479 if (ies->password) 05480 ast_copy_string(secret, ies->password, sizeof(secret)); 05481 if (ies->md5_result) 05482 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 05483 if (ies->rsa_result) 05484 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 05485 if (ies->refresh) 05486 expire = ies->refresh; 05487 05488 if (ast_strlen_zero(peer)) { 05489 ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr)); 05490 return -1; 05491 } 05492 05493 /* SLD: first call to lookup peer during registration */ 05494 ast_mutex_unlock(&iaxsl[callno]); 05495 p = find_peer(peer, 1); 05496 ast_mutex_lock(&iaxsl[callno]); 05497 if (!p || !iaxs[callno]) { 05498 if (authdebug && !p) 05499 ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05500 goto return_unref; 05501 } 05502 05503 if (!ast_test_flag(p, IAX_DYNAMIC)) { 05504 if (authdebug) 05505 ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05506 goto return_unref; 05507 } 05508 05509 if (!ast_apply_ha(p->ha, sin)) { 05510 if (authdebug) 05511 ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05512 goto return_unref; 05513 } 05514 if (!inaddrcmp(&p->addr, sin)) 05515 ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED); 05516 ast_string_field_set(iaxs[callno], secret, p->secret); 05517 ast_string_field_set(iaxs[callno], inkeys, p->inkeys); 05518 /* Check secret against what we have on file */ 05519 if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05520 if (!ast_strlen_zero(p->inkeys)) { 05521 char tmpkeys[256]; 05522 char *stringp=NULL; 05523 ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys)); 05524 stringp=tmpkeys; 05525 keyn = strsep(&stringp, ":"); 05526 while(keyn) { 05527 key = ast_key_get(keyn, AST_KEY_PUBLIC); 05528 if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) { 05529 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05530 break; 05531 } else if (!key) 05532 ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn); 05533 keyn = strsep(&stringp, ":"); 05534 } 05535 if (!keyn) { 05536 if (authdebug) 05537 ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys); 05538 goto return_unref; 05539 } 05540 } else { 05541 if (authdebug) 05542 ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer); 05543 goto return_unref; 05544 } 05545 } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05546 struct MD5Context md5; 05547 unsigned char digest[16]; 05548 char *tmppw, *stringp; 05549 05550 tmppw = ast_strdupa(p->secret); 05551 stringp = tmppw; 05552 while((tmppw = strsep(&stringp, ";"))) { 05553 MD5Init(&md5); 05554 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 05555 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05556 MD5Final(digest, &md5); 05557 for (x=0;x<16;x++) 05558 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05559 if (!strcasecmp(requeststr, md5secret)) 05560 break; 05561 } 05562 if (tmppw) { 05563 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05564 } else { 05565 if (authdebug) 05566 ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret); 05567 goto return_unref; 05568 } 05569 } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) { 05570 /* They've provided a plain text password and we support that */ 05571 if (strcmp(secret, p->secret)) { 05572 if (authdebug) 05573 ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05574 goto return_unref; 05575 } else 05576 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05577 } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) { 05578 if (authdebug) 05579 ast_log(LOG_NOTICE, "Inappropriate authentication received\n"); 05580 goto return_unref; 05581 } 05582 ast_string_field_set(iaxs[callno], peer, peer); 05583 /* Choose lowest expiry number */ 05584 if (expire && (expire < iaxs[callno]->expiry)) 05585 iaxs[callno]->expiry = expire; 05586 05587 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05588 05589 res = 0; 05590 05591 return_unref: 05592 if (p) 05593 peer_unref(p); 05594 05595 return res; 05596 }
static int registry_authrequest | ( | int | callno | ) | [static] |
Definition at line 6257 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strdupa, ast_string_field_set, iax2_peer::authmethods, iax_ie_data::buf, find_peer(), IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_REGAUTH, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CHALLENGE, IAX_IE_USERNAME, iaxs, iaxsl, LOG_WARNING, peer_unref(), iax_ie_data::pos, and send_command().
Referenced by socket_process().
06258 { 06259 struct iax_ie_data ied; 06260 struct iax2_peer *p; 06261 char challenge[10]; 06262 const char *peer_name; 06263 int res = -1; 06264 06265 peer_name = ast_strdupa(iaxs[callno]->peer); 06266 06267 /* SLD: third call to find_peer in registration */ 06268 ast_mutex_unlock(&iaxsl[callno]); 06269 p = find_peer(peer_name, 1); 06270 ast_mutex_lock(&iaxsl[callno]); 06271 if (!iaxs[callno]) 06272 goto return_unref; 06273 if (!p) { 06274 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 06275 goto return_unref; 06276 } 06277 06278 memset(&ied, 0, sizeof(ied)); 06279 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 06280 if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) { 06281 /* Build the challenge */ 06282 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 06283 ast_string_field_set(iaxs[callno], challenge, challenge); 06284 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge); 06285 } 06286 iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name); 06287 06288 res = 0; 06289 06290 return_unref: 06291 peer_unref(p); 06292 06293 return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);; 06294 }
static int registry_rerequest | ( | struct iax_ies * | ies, | |
int | callno, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 6296 of file chan_iax2.c.
References iax2_registry::addr, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax_ie_data::buf, iax_ies::challenge, IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_AUTHSENT, REG_STATE_NOAUTH, iax2_registry::regstate, iax2_registry::secret, send_command(), iax2_registry::username, and iax_ies::username.
Referenced by socket_process().
06297 { 06298 struct iax2_registry *reg; 06299 /* Start pessimistic */ 06300 struct iax_ie_data ied; 06301 char peer[256] = ""; 06302 char challenge[256] = ""; 06303 int res; 06304 int authmethods = 0; 06305 if (ies->authmethods) 06306 authmethods = ies->authmethods; 06307 if (ies->username) 06308 ast_copy_string(peer, ies->username, sizeof(peer)); 06309 if (ies->challenge) 06310 ast_copy_string(challenge, ies->challenge, sizeof(challenge)); 06311 memset(&ied, 0, sizeof(ied)); 06312 reg = iaxs[callno]->reg; 06313 if (reg) { 06314 if (inaddrcmp(®->addr, sin)) { 06315 ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 06316 return -1; 06317 } 06318 if (ast_strlen_zero(reg->secret)) { 06319 ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); 06320 reg->regstate = REG_STATE_NOAUTH; 06321 return -1; 06322 } 06323 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 06324 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 06325 if (reg->secret[0] == '[') { 06326 char tmpkey[256]; 06327 ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); 06328 tmpkey[strlen(tmpkey) - 1] = '\0'; 06329 res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL); 06330 } else 06331 res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL); 06332 if (!res) { 06333 reg->regstate = REG_STATE_AUTHSENT; 06334 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 06335 } else 06336 return -1; 06337 ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); 06338 } else 06339 ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); 06340 return -1; 06341 }
static char* regstate2str | ( | int | regstate | ) | [static] |
Definition at line 4750 of file chan_iax2.c.
References REG_STATE_AUTHSENT, REG_STATE_NOAUTH, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED.
Referenced by handle_response_register(), iax2_show_registry(), sip_reg_timeout(), and sip_show_registry().
04751 { 04752 switch(regstate) { 04753 case REG_STATE_UNREGISTERED: 04754 return "Unregistered"; 04755 case REG_STATE_REGSENT: 04756 return "Request Sent"; 04757 case REG_STATE_AUTHSENT: 04758 return "Auth. Sent"; 04759 case REG_STATE_REGISTERED: 04760 return "Registered"; 04761 case REG_STATE_REJECTED: 04762 return "Rejected"; 04763 case REG_STATE_TIMEOUT: 04764 return "Timeout"; 04765 case REG_STATE_NOAUTH: 04766 return "No Authentication"; 04767 default: 04768 return "Unknown"; 04769 } 04770 }
static int reload | ( | void | ) | [static] |
Definition at line 10249 of file chan_iax2.c.
References reload_config().
10250 { 10251 return reload_config(); 10252 }
static int reload_config | ( | void | ) | [static] |
Definition at line 10223 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, iax2_do_register(), iax_provision_reload(), poke_all_peers(), prune_peers(), prune_users(), reload_firmware(), and set_config().
10224 { 10225 char *config = "iax.conf"; 10226 struct iax2_registry *reg; 10227 10228 if (set_config(config, 1) > 0) { 10229 prune_peers(); 10230 prune_users(); 10231 AST_LIST_LOCK(®istrations); 10232 AST_LIST_TRAVERSE(®istrations, reg, entry) 10233 iax2_do_register(reg); 10234 AST_LIST_UNLOCK(®istrations); 10235 /* Qualify hosts, too */ 10236 poke_all_peers(); 10237 } 10238 reload_firmware(0); 10239 iax_provision_reload(); 10240 10241 return 0; 10242 }
static void reload_firmware | ( | int | unload | ) | [static] |
Definition at line 1954 of file chan_iax2.c.
References ast_config_AST_DATA_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), iax_firmware::dead, destroy_firmware(), errno, ast_firmware_list::lock, LOG_WARNING, iax_firmware::next, option_verbose, try_firmware(), VERBOSE_PREFIX_2, ast_firmware_list::wares, and waresl.
Referenced by __unload_module(), load_module(), and reload_config().
01955 { 01956 struct iax_firmware *cur, *curl, *curp; 01957 DIR *fwd; 01958 struct dirent *de; 01959 char dir[256]; 01960 char fn[256]; 01961 /* Mark all as dead */ 01962 ast_mutex_lock(&waresl.lock); 01963 cur = waresl.wares; 01964 while(cur) { 01965 cur->dead = 1; 01966 cur = cur->next; 01967 } 01968 01969 /* Now that we've freed them, load the new ones */ 01970 if (!unload) { 01971 snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR); 01972 fwd = opendir(dir); 01973 if (fwd) { 01974 while((de = readdir(fwd))) { 01975 if (de->d_name[0] != '.') { 01976 snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name); 01977 if (!try_firmware(fn)) { 01978 if (option_verbose > 1) 01979 ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name); 01980 } 01981 } 01982 } 01983 closedir(fwd); 01984 } else 01985 ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno)); 01986 } 01987 01988 /* Clean up leftovers */ 01989 cur = waresl.wares; 01990 curp = NULL; 01991 while(cur) { 01992 curl = cur; 01993 cur = cur->next; 01994 if (curl->dead) { 01995 if (curp) { 01996 curp->next = cur; 01997 } else { 01998 waresl.wares = cur; 01999 } 02000 destroy_firmware(curl); 02001 } else { 02002 curp = cur; 02003 } 02004 } 02005 ast_mutex_unlock(&waresl.lock); 02006 }
static void remove_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1249 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().
01250 { 01251 if (!pvt->peercallno) { 01252 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01253 return; 01254 } 01255 01256 ao2_unlink(iax_peercallno_pvts, pvt); 01257 }
Definition at line 6800 of file chan_iax2.c.
References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iaxs, iax_rr::jitter, iax_rr::losscnt, iax_rr::losspct, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::remote_rr, iax_ies::rr_delay, iax_ies::rr_dropped, iax_ies::rr_jitter, iax_ies::rr_loss, iax_ies::rr_ooo, and iax_ies::rr_pkts.
Referenced by socket_process().
06801 { 06802 iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter; 06803 iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24; 06804 iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff; 06805 iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts; 06806 iaxs[fr->callno]->remote_rr.delay = ies->rr_delay; 06807 iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped; 06808 iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; 06809 }
static void* sched_thread | ( | void * | ignore | ) | [static] |
Definition at line 9025 of file chan_iax2.c.
References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), LOG_DEBUG, and option_debug.
Referenced by start_network_thread().
09026 { 09027 int count; 09028 int res; 09029 struct timeval tv; 09030 struct timespec ts; 09031 09032 for (;;) { 09033 res = ast_sched_wait(sched); 09034 if ((res > 1000) || (res < 0)) 09035 res = 1000; 09036 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); 09037 ts.tv_sec = tv.tv_sec; 09038 ts.tv_nsec = tv.tv_usec * 1000; 09039 09040 pthread_testcancel(); 09041 ast_mutex_lock(&sched_lock); 09042 ast_cond_timedwait(&sched_cond, &sched_lock, &ts); 09043 ast_mutex_unlock(&sched_lock); 09044 pthread_testcancel(); 09045 09046 count = ast_sched_runq(sched); 09047 if (option_debug && count >= 20) 09048 ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); 09049 } 09050 return NULL; 09051 }
static int schedule_delivery | ( | struct iax_frame * | fr, | |
int | updatehistory, | |||
int | fromtrunk, | |||
unsigned int * | tsout | |||
) | [static] |
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 2638 of file chan_iax2.c.
References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), AST_FRAME_CNG, AST_FRAME_VOICE, ast_log(), AST_SCHED_DEL, ast_test_flag, ast_tvadd(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, iaxs, chan_iax2_pvt::jb, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, chan_iax2_pvt::jbid, len, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, ast_channel_tech::properties, chan_iax2_pvt::rxcore, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().
Referenced by socket_process().
02639 { 02640 int type, len; 02641 int ret; 02642 int needfree = 0; 02643 struct ast_channel *owner = NULL; 02644 struct ast_channel *bridge = NULL; 02645 02646 /* Attempt to recover wrapped timestamps */ 02647 unwrap_timestamp(fr); 02648 02649 /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */ 02650 if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) 02651 fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000)); 02652 else { 02653 #if 0 02654 if (option_debug) 02655 ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n"); 02656 #endif 02657 fr->af.delivery = ast_tv(0,0); 02658 } 02659 02660 type = JB_TYPE_CONTROL; 02661 len = 0; 02662 02663 if(fr->af.frametype == AST_FRAME_VOICE) { 02664 type = JB_TYPE_VOICE; 02665 len = ast_codec_get_samples(&fr->af) / 8; 02666 } else if(fr->af.frametype == AST_FRAME_CNG) { 02667 type = JB_TYPE_SILENCE; 02668 } 02669 02670 if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) { 02671 if (tsout) 02672 *tsout = fr->ts; 02673 __do_deliver(fr); 02674 return -1; 02675 } 02676 02677 if ((owner = iaxs[fr->callno]->owner)) 02678 bridge = ast_bridged_channel(owner); 02679 02680 /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to 02681 * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */ 02682 if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) { 02683 jb_frame frame; 02684 02685 /* deliver any frames in the jb */ 02686 while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { 02687 __do_deliver(frame.data); 02688 /* __do_deliver() can make the call disappear */ 02689 if (!iaxs[fr->callno]) 02690 return -1; 02691 } 02692 02693 jb_reset(iaxs[fr->callno]->jb); 02694 02695 AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid); 02696 02697 /* deliver this frame now */ 02698 if (tsout) 02699 *tsout = fr->ts; 02700 __do_deliver(fr); 02701 return -1; 02702 } 02703 02704 /* insert into jitterbuffer */ 02705 /* TODO: Perhaps we could act immediately if it's not droppable and late */ 02706 ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts, 02707 calc_rxstamp(iaxs[fr->callno],fr->ts)); 02708 if (ret == JB_DROP) { 02709 needfree++; 02710 } else if (ret == JB_SCHED) { 02711 update_jbsched(iaxs[fr->callno]); 02712 } 02713 if (tsout) 02714 *tsout = fr->ts; 02715 if (needfree) { 02716 /* Free our iax frame */ 02717 iax2_frame_free(fr); 02718 return -1; 02719 } 02720 return 0; 02721 }
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 3156 of file chan_iax2.c.
References AST_FRAME_IAX, compress_subclass(), and ast_iax2_full_hdr::scallno.
Referenced by socket_process().
03157 { 03158 struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno), 03159 .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX, 03160 .csub = compress_subclass(command) }; 03161 03162 return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin)); 03163 }
static int send_command | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno | |||
) | [static] |
Definition at line 5034 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().
05035 { 05036 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); 05037 }
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] |
Definition at line 5053 of file chan_iax2.c.
References __send_command(), chan_iax2_pvt::callno, iax2_predestroy(), and iaxs.
Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_hangup(), socket_process(), and update_registry().
05054 { 05055 int call_num = i->callno; 05056 /* It is assumed that the callno has already been locked */ 05057 iax2_predestroy(i->callno); 05058 if (!iaxs[call_num]) 05059 return -1; 05060 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1); 05061 }
static int send_command_immediate | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno | |||
) | [static] |
Definition at line 5063 of file chan_iax2.c.
References __send_command().
Referenced by iax2_vnak(), and socket_process().
05064 { 05065 return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0); 05066 }
static int send_command_locked | ( | unsigned short | callno, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno | |||
) | [static] |
Definition at line 5039 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, and send_command().
Referenced by iax2_answer(), iax2_digit_begin(), iax2_digit_end(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), and iax2_transfer().
05040 { 05041 int res; 05042 ast_mutex_lock(&iaxsl[callno]); 05043 res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno); 05044 ast_mutex_unlock(&iaxsl[callno]); 05045 return res; 05046 }
static int send_command_transfer | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 5068 of file chan_iax2.c.
References __send_command().
Referenced by socket_process(), and try_transfer().
05069 { 05070 return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0); 05071 }
static int send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1055 of file chan_iax2.c.
References __send_lagrq(), and schedule_action.
Referenced by __find_callno(), __send_lagrq(), and make_trunk().
01056 { 01057 #ifdef SCHED_MULTITHREADED 01058 if (schedule_action(__send_lagrq, data)) 01059 #endif 01060 __send_lagrq(data); 01061 return 0; 01062 }
static int send_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2079 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax2_registry::addr, ast_inet_ntoa(), ast_log(), iax_frame::callno, iax2_registry::callno, iax_frame::data, iax_frame::datalen, errno, error(), handle_error(), iax_showframe(), iaxs, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, transfer, iax_frame::transfer, and iax_frame::ts.
Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().
02080 { 02081 int res; 02082 int callno = f->callno; 02083 02084 /* Don't send if there was an error, but return error instead */ 02085 if (!callno || !iaxs[callno] || iaxs[callno]->error) 02086 return -1; 02087 02088 /* Called with iaxsl held */ 02089 if (option_debug > 2 && iaxdebug) 02090 ast_log(LOG_DEBUG, "Sending %d on %d/%d to %s:%d\n", f->ts, callno, iaxs[callno]->peercallno, ast_inet_ntoa(iaxs[callno]->addr.sin_addr), ntohs(iaxs[callno]->addr.sin_port)); 02091 if (f->transfer) { 02092 if (iaxdebug) 02093 iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02094 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, 02095 sizeof(iaxs[callno]->transfer)); 02096 } else { 02097 if (iaxdebug) 02098 iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02099 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, 02100 sizeof(iaxs[callno]->addr)); 02101 } 02102 if (res < 0) { 02103 if (option_debug && iaxdebug) 02104 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 02105 handle_error(); 02106 } else 02107 res = 0; 02108 return res; 02109 }
static int send_ping | ( | const void * | data | ) | [static] |
Definition at line 1015 of file chan_iax2.c.
References __send_ping(), and schedule_action.
Referenced by __find_callno(), __send_ping(), and make_trunk().
01016 { 01017 #ifdef SCHED_MULTITHREADED 01018 if (schedule_action(__send_ping, data)) 01019 #endif 01020 __send_ping(data); 01021 return 0; 01022 }
static int send_trunk | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [static] |
Definition at line 6478 of file chan_iax2.c.
References iax2_trunk_peer::addr, iax_frame::afdata, ast_inet_ntoa(), ast_log(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, LOG_DEBUG, ast_iax2_meta_hdr::metacmd, option_debug, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.
Referenced by timing_read().
06479 { 06480 int res = 0; 06481 struct iax_frame *fr; 06482 struct ast_iax2_meta_hdr *meta; 06483 struct ast_iax2_meta_trunk_hdr *mth; 06484 int calls = 0; 06485 06486 /* Point to frame */ 06487 fr = (struct iax_frame *)tpeer->trunkdata; 06488 /* Point to meta data */ 06489 meta = (struct ast_iax2_meta_hdr *)fr->afdata; 06490 mth = (struct ast_iax2_meta_trunk_hdr *)meta->data; 06491 if (tpeer->trunkdatalen) { 06492 /* We're actually sending a frame, so fill the meta trunk header and meta header */ 06493 meta->zeros = 0; 06494 meta->metacmd = IAX_META_TRUNK; 06495 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) 06496 meta->cmddata = IAX_META_TRUNK_MINI; 06497 else 06498 meta->cmddata = IAX_META_TRUNK_SUPERMINI; 06499 mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now)); 06500 /* And the rest of the ast_iax2 header */ 06501 fr->direction = DIRECTION_OUTGRESS; 06502 fr->retrans = -1; 06503 fr->transfer = 0; 06504 /* Any appropriate call will do */ 06505 fr->data = fr->afdata; 06506 fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr); 06507 res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd); 06508 calls = tpeer->calls; 06509 #if 0 06510 if (option_debug) 06511 ast_log(LOG_DEBUG, "Trunking %d call chunks in %d bytes to %s:%d, ts=%d\n", calls, fr->datalen, ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), ntohl(mth->ts)); 06512 #endif 06513 /* Reset transmit trunk side data */ 06514 tpeer->trunkdatalen = 0; 06515 tpeer->calls = 0; 06516 } 06517 if (res < 0) 06518 return res; 06519 return calls; 06520 }
static int set_config | ( | char * | config_file, | |
int | reload | |||
) | [static] |
Load configuration.
Definition at line 9853 of file chan_iax2.c.
References __ao2_link(), ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load(), ast_context_create(), ast_context_find(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_netsock_bind(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_netsock_sockfd(), ast_netsock_unref(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), build_peer(), build_user(), capability, DEFAULT_MAXMS, errno, format, gen, get_encrypt_methods(), iax2_register(), IAX_ALLOWFWDOWNLOAD, IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_RTUPDATE, IAX_TRANSFERMEDIA, IAX_TRUNKTIMESTAMPS, IAX_USEJITTERBUF, iaxmaxthreadcount, iaxthreadcount, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_PEER_BUCKETS, ast_variable::name, ast_variable::next, option_verbose, peer_unref(), peers, portno, prefs, reg_source_db(), iax2_registry::secret, set_config_destroy(), set_timing(), socket_read(), user_unref(), users, ast_variable::value, and VERBOSE_PREFIX_2.
Referenced by load_module(), reload(), and reload_config().
09854 { 09855 struct ast_config *cfg, *ucfg; 09856 int capability=iax2_capability; 09857 struct ast_variable *v; 09858 char *cat; 09859 const char *utype; 09860 const char *tosval; 09861 int format; 09862 int portno = IAX_DEFAULT_PORTNO; 09863 int x; 09864 struct iax2_user *user; 09865 struct iax2_peer *peer; 09866 struct ast_netsock *ns; 09867 #if 0 09868 static unsigned short int last_port=0; 09869 #endif 09870 09871 cfg = ast_config_load(config_file); 09872 09873 if (!cfg) { 09874 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 09875 return -1; 09876 } 09877 09878 if (reload) { 09879 set_config_destroy(); 09880 } 09881 09882 /* Reset global codec prefs */ 09883 memset(&prefs, 0 , sizeof(struct ast_codec_pref)); 09884 09885 /* Reset Global Flags */ 09886 memset(&globalflags, 0, sizeof(globalflags)); 09887 ast_set_flag(&globalflags, IAX_RTUPDATE); 09888 09889 #ifdef SO_NO_CHECK 09890 nochecksums = 0; 09891 #endif 09892 09893 min_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09894 max_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09895 09896 maxauthreq = 3; 09897 09898 v = ast_variable_browse(cfg, "general"); 09899 09900 /* Seed initial tos value */ 09901 tosval = ast_variable_retrieve(cfg, "general", "tos"); 09902 if (tosval) { 09903 if (ast_str2tos(tosval, &tos)) 09904 ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n"); 09905 } 09906 while(v) { 09907 if (!strcasecmp(v->name, "bindport")){ 09908 if (reload) 09909 ast_log(LOG_NOTICE, "Ignoring bindport on reload\n"); 09910 else 09911 portno = atoi(v->value); 09912 } else if (!strcasecmp(v->name, "pingtime")) 09913 ping_time = atoi(v->value); 09914 else if (!strcasecmp(v->name, "iaxthreadcount")) { 09915 if (reload) { 09916 if (atoi(v->value) != iaxthreadcount) 09917 ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n"); 09918 } else { 09919 iaxthreadcount = atoi(v->value); 09920 if (iaxthreadcount < 1) { 09921 ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n"); 09922 iaxthreadcount = 1; 09923 } else if (iaxthreadcount > 256) { 09924 ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n"); 09925 iaxthreadcount = 256; 09926 } 09927 } 09928 } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) { 09929 if (reload) { 09930 AST_LIST_LOCK(&dynamic_list); 09931 iaxmaxthreadcount = atoi(v->value); 09932 AST_LIST_UNLOCK(&dynamic_list); 09933 } else { 09934 iaxmaxthreadcount = atoi(v->value); 09935 if (iaxmaxthreadcount < 0) { 09936 ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n"); 09937 iaxmaxthreadcount = 0; 09938 } else if (iaxmaxthreadcount > 256) { 09939 ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n"); 09940 iaxmaxthreadcount = 256; 09941 } 09942 } 09943 } else if (!strcasecmp(v->name, "nochecksums")) { 09944 #ifdef SO_NO_CHECK 09945 if (ast_true(v->value)) 09946 nochecksums = 1; 09947 else 09948 nochecksums = 0; 09949 #else 09950 if (ast_true(v->value)) 09951 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 09952 #endif 09953 } 09954 else if (!strcasecmp(v->name, "maxjitterbuffer")) 09955 maxjitterbuffer = atoi(v->value); 09956 else if (!strcasecmp(v->name, "resyncthreshold")) 09957 resyncthreshold = atoi(v->value); 09958 else if (!strcasecmp(v->name, "maxjitterinterps")) 09959 maxjitterinterps = atoi(v->value); 09960 else if (!strcasecmp(v->name, "lagrqtime")) 09961 lagrq_time = atoi(v->value); 09962 else if (!strcasecmp(v->name, "maxregexpire")) 09963 max_reg_expire = atoi(v->value); 09964 else if (!strcasecmp(v->name, "minregexpire")) 09965 min_reg_expire = atoi(v->value); 09966 else if (!strcasecmp(v->name, "bindaddr")) { 09967 if (reload) { 09968 ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n"); 09969 } else { 09970 if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) { 09971 ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno); 09972 } else { 09973 if (option_verbose > 1) { 09974 if (strchr(v->value, ':')) 09975 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value); 09976 else 09977 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno); 09978 } 09979 if (defaultsockfd < 0) 09980 defaultsockfd = ast_netsock_sockfd(ns); 09981 ast_netsock_unref(ns); 09982 } 09983 } 09984 } else if (!strcasecmp(v->name, "authdebug")) 09985 authdebug = ast_true(v->value); 09986 else if (!strcasecmp(v->name, "encryption")) 09987 iax2_encryption = get_encrypt_methods(v->value); 09988 else if (!strcasecmp(v->name, "notransfer")) { 09989 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09990 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 09991 ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER); 09992 } else if (!strcasecmp(v->name, "transfer")) { 09993 if (!strcasecmp(v->value, "mediaonly")) { 09994 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09995 } else if (ast_true(v->value)) { 09996 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09997 } else 09998 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09999 } else if (!strcasecmp(v->name, "codecpriority")) { 10000 if(!strcasecmp(v->value, "caller")) 10001 ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST); 10002 else if(!strcasecmp(v->value, "disabled")) 10003 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 10004 else if(!strcasecmp(v->value, "reqonly")) { 10005 ast_set_flag((&globalflags), IAX_CODEC_NOCAP); 10006 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 10007 } 10008 } else if (!strcasecmp(v->name, "jitterbuffer")) 10009 ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 10010 else if (!strcasecmp(v->name, "forcejitterbuffer")) 10011 ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF); 10012 else if (!strcasecmp(v->name, "delayreject")) 10013 delayreject = ast_true(v->value); 10014 else if (!strcasecmp(v->name, "allowfwdownload")) 10015 ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD); 10016 else if (!strcasecmp(v->name, "rtcachefriends")) 10017 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS); 10018 else if (!strcasecmp(v->name, "rtignoreregexpire")) 10019 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE); 10020 else if (!strcasecmp(v->name, "rtupdate")) 10021 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE); 10022 else if (!strcasecmp(v->name, "trunktimestamps")) 10023 ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS); 10024 else if (!strcasecmp(v->name, "rtautoclear")) { 10025 int i = atoi(v->value); 10026 if(i > 0) 10027 global_rtautoclear = i; 10028 else 10029 i = 0; 10030 ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR); 10031 } else if (!strcasecmp(v->name, "trunkfreq")) { 10032 trunkfreq = atoi(v->value); 10033 if (trunkfreq < 10) 10034 trunkfreq = 10; 10035 } else if (!strcasecmp(v->name, "autokill")) { 10036 if (sscanf(v->value, "%d", &x) == 1) { 10037 if (x >= 0) 10038 autokill = x; 10039 else 10040 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 10041 } else if (ast_true(v->value)) { 10042 autokill = DEFAULT_MAXMS; 10043 } else { 10044 autokill = 0; 10045 } 10046 } else if (!strcasecmp(v->name, "bandwidth")) { 10047 if (!strcasecmp(v->value, "low")) { 10048 capability = IAX_CAPABILITY_LOWBANDWIDTH; 10049 } else if (!strcasecmp(v->value, "medium")) { 10050 capability = IAX_CAPABILITY_MEDBANDWIDTH; 10051 } else if (!strcasecmp(v->value, "high")) { 10052 capability = IAX_CAPABILITY_FULLBANDWIDTH; 10053 } else 10054 ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); 10055 } else if (!strcasecmp(v->name, "allow")) { 10056 ast_parse_allow_disallow(&prefs, &capability, v->value, 1); 10057 } else if (!strcasecmp(v->name, "disallow")) { 10058 ast_parse_allow_disallow(&prefs, &capability, v->value, 0); 10059 } else if (!strcasecmp(v->name, "register")) { 10060 iax2_register(v->value, v->lineno); 10061 } else if (!strcasecmp(v->name, "iaxcompat")) { 10062 iaxcompat = ast_true(v->value); 10063 } else if (!strcasecmp(v->name, "regcontext")) { 10064 ast_copy_string(regcontext, v->value, sizeof(regcontext)); 10065 /* Create context if it doesn't exist already */ 10066 if (!ast_context_find(regcontext)) 10067 ast_context_create(NULL, regcontext, "IAX2"); 10068 } else if (!strcasecmp(v->name, "tos")) { 10069 if (ast_str2tos(v->value, &tos)) 10070 ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno); 10071 } else if (!strcasecmp(v->name, "accountcode")) { 10072 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 10073 } else if (!strcasecmp(v->name, "mohinterpret")) { 10074 ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret)); 10075 } else if (!strcasecmp(v->name, "mohsuggest")) { 10076 ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest)); 10077 } else if (!strcasecmp(v->name, "amaflags")) { 10078 format = ast_cdr_amaflags2int(v->value); 10079 if (format < 0) { 10080 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 10081 } else { 10082 amaflags = format; 10083 } 10084 } else if (!strcasecmp(v->name, "language")) { 10085 ast_copy_string(language, v->value, sizeof(language)); 10086 } else if (!strcasecmp(v->name, "maxauthreq")) { 10087 maxauthreq = atoi(v->value); 10088 if (maxauthreq < 0) 10089 maxauthreq = 0; 10090 } else if (!strcasecmp(v->name, "adsi")) { 10091 adsi = ast_true(v->value); 10092 } /*else if (strcasecmp(v->name,"type")) */ 10093 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 10094 v = v->next; 10095 } 10096 10097 if (defaultsockfd < 0) { 10098 if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) { 10099 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 10100 } else { 10101 if (option_verbose > 1) 10102 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno); 10103 defaultsockfd = ast_netsock_sockfd(ns); 10104 ast_netsock_unref(ns); 10105 } 10106 } 10107 if (reload) { 10108 ast_netsock_release(outsock); 10109 outsock = ast_netsock_list_alloc(); 10110 if (!outsock) { 10111 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 10112 return -1; 10113 } 10114 ast_netsock_init(outsock); 10115 } 10116 10117 if (min_reg_expire > max_reg_expire) { 10118 ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n", 10119 min_reg_expire, max_reg_expire, max_reg_expire); 10120 min_reg_expire = max_reg_expire; 10121 } 10122 iax2_capability = capability; 10123 10124 ucfg = ast_config_load("users.conf"); 10125 if (ucfg) { 10126 struct ast_variable *gen; 10127 int genhasiax; 10128 int genregisteriax; 10129 const char *hasiax, *registeriax; 10130 10131 genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); 10132 genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); 10133 gen = ast_variable_browse(ucfg, "general"); 10134 cat = ast_category_browse(ucfg, NULL); 10135 while (cat) { 10136 if (strcasecmp(cat, "general")) { 10137 hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); 10138 registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); 10139 if (ast_true(hasiax) || (!hasiax && genhasiax)) { 10140 /* Start with general parameters, then specific parameters, user and peer */ 10141 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 10142 if (user) { 10143 __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10144 user = user_unref(user); 10145 } 10146 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 10147 if (peer) { 10148 if (ast_test_flag(peer, IAX_DYNAMIC)) 10149 reg_source_db(peer); 10150 __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10151 peer = peer_unref(peer); 10152 } 10153 } 10154 if (ast_true(registeriax) || (!registeriax && genregisteriax)) { 10155 char tmp[256]; 10156 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 10157 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 10158 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 10159 if (!host) 10160 host = ast_variable_retrieve(ucfg, "general", "host"); 10161 if (!username) 10162 username = ast_variable_retrieve(ucfg, "general", "username"); 10163 if (!secret) 10164 secret = ast_variable_retrieve(ucfg, "general", "secret"); 10165 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 10166 if (!ast_strlen_zero(secret)) 10167 snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); 10168 else 10169 snprintf(tmp, sizeof(tmp), "%s@%s", username, host); 10170 iax2_register(tmp, 0); 10171 } 10172 } 10173 } 10174 cat = ast_category_browse(ucfg, cat); 10175 } 10176 ast_config_destroy(ucfg); 10177 } 10178 10179 cat = ast_category_browse(cfg, NULL); 10180 while(cat) { 10181 if (strcasecmp(cat, "general")) { 10182 utype = ast_variable_retrieve(cfg, cat, "type"); 10183 if (utype) { 10184 if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { 10185 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 10186 if (user) { 10187 __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10188 user = user_unref(user); 10189 } 10190 } 10191 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { 10192 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 10193 if (peer) { 10194 if (ast_test_flag(peer, IAX_DYNAMIC)) 10195 reg_source_db(peer); 10196 __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10197 peer = peer_unref(peer); 10198 } 10199 } else if (strcasecmp(utype, "user")) { 10200 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file); 10201 } 10202 } else 10203 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 10204 } 10205 cat = ast_category_browse(cfg, cat); 10206 } 10207 ast_config_destroy(cfg); 10208 set_timing(); 10209 return 1; 10210 }
static void set_config_destroy | ( | void | ) | [static] |
Definition at line 9837 of file chan_iax2.c.
References ast_clear_flag, delete_users(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, and IAX_USEJITTERBUF.
Referenced by set_config().
09838 { 09839 strcpy(accountcode, ""); 09840 strcpy(language, ""); 09841 strcpy(mohinterpret, "default"); 09842 strcpy(mohsuggest, ""); 09843 amaflags = 0; 09844 delayreject = 0; 09845 ast_clear_flag((&globalflags), IAX_NOTRANSFER); 09846 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 09847 ast_clear_flag((&globalflags), IAX_USEJITTERBUF); 09848 ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF); 09849 delete_users(); 09850 }
static void set_timing | ( | void | ) | [static] |
Definition at line 9822 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by set_config().
09823 { 09824 #ifdef HAVE_ZAPTEL 09825 int bs = trunkfreq * 8; 09826 if (timingfd > -1) { 09827 if ( 09828 #ifdef ZT_TIMERACK 09829 ioctl(timingfd, ZT_TIMERCONFIG, &bs) && 09830 #endif 09831 ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs)) 09832 ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n"); 09833 } 09834 #endif 09835 }
static void signal_condition | ( | ast_mutex_t * | lock, | |
ast_cond_t * | cond | |||
) | [static] |
Definition at line 757 of file chan_iax2.c.
References ast_cond_signal(), ast_mutex_lock(), and ast_mutex_unlock().
Referenced by __schedule_action(), iax2_sched_add(), iax2_transmit(), and socket_read().
00758 { 00759 ast_mutex_lock(lock); 00760 ast_cond_signal(cond); 00761 ast_mutex_unlock(lock); 00762 }
static int socket_process | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 6952 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_device_state_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_parking_ext(), ast_sched_del(), AST_SCHED_DEL, ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), chan_iax2_pvt::authmethods, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, iax_frame::cacheable, calc_timestamp(), iax_ies::called_number, iax2_peer::callno, chan_iax2_pvt::callno, ast_iax2_meta_trunk_entry::callno, ast_iax2_mini_hdr::callno, iax2_registry::callno, iax_frame::callno, chan_iax2_pvt::capability, iax_ies::cause, iax_ies::causecode, check_access(), check_provisioning(), chan_iax2_pvt::chosenformat, cid_num, ast_iax2_meta_hdr::cmddata, iax_ies::codec_prefs, complete_dpreply(), complete_transfer(), construct_rr(), ast_iax2_full_hdr::csub, ast_frame::data, ast_iax2_meta_trunk_hdr::data, ast_iax2_meta_hdr::data, ast_frame::datalen, ast_iax2_full_hdr::dcallno, DEADLOCK_AVOIDANCE, decrypt_frame(), iax_ies::devicetype, dp_lookup(), chan_iax2_pvt::encmethods, iax_ies::encmethods, chan_iax2_pvt::error, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, iax_frame::final, find_callno(), find_callno_locked(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, iax_ies::format, format, chan_iax2_pvt::frames_received, ast_frame::frametype, iax_ies::fwdesc, ast_channel::hangupcause, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_vnak(), IAX_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), iaxq, iaxs, iaxsl, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, ast_iax2_full_hdr::iseqno, iax_frame::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_frame::len, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), ast_frame::mallocd, manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, iax_ies::musiconhold, ast_channel::nativeformats, NEW_ALLOW, NEW_PREVENT, ast_frame::offset, option_debug, option_verbose, chan_iax2_pvt::oseqno, iax_frame::oseqno, ast_iax2_full_hdr::oseqno, iax_frame::outoforder, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, peer_ref(), peer_unref(), chan_iax2_pvt::peercallno, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, chan_iax2_pvt::prefs, iax_ies::provver, iax_ies::provverpres, raw_hangup(), ast_channel::readformat, iax_ies::refresh, REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rprefs, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, ast_frame::samples, save_rr(), ast_iax2_full_hdr::scallno, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, spawn_dp_lookup(), ast_frame::src, chan_iax2_pvt::state, stop_stuff(), store_by_peercallno(), ast_frame::subclass, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MEDIAPASS, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_mini_hdr::ts, ast_iax2_meta_trunk_hdr::ts, ast_iax2_full_hdr::type, uncompress_subclass(), update_registry(), iax_ies::username, VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.
Referenced by handle_deferred_full_frames(), and iax2_process_thread().
06953 { 06954 struct sockaddr_in sin; 06955 int res; 06956 int updatehistory=1; 06957 int new = NEW_PREVENT; 06958 void *ptr; 06959 int dcallno = 0; 06960 struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf; 06961 struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf; 06962 struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf; 06963 struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf; 06964 struct ast_iax2_meta_trunk_hdr *mth; 06965 struct ast_iax2_meta_trunk_entry *mte; 06966 struct ast_iax2_meta_trunk_mini *mtm; 06967 struct iax_frame *fr; 06968 struct iax_frame *cur; 06969 struct ast_frame f = { 0, }; 06970 struct ast_channel *c; 06971 struct iax2_dpcache *dp; 06972 struct iax2_peer *peer; 06973 struct iax2_trunk_peer *tpeer; 06974 struct timeval rxtrunktime; 06975 struct iax_ies ies; 06976 struct iax_ie_data ied0, ied1; 06977 int format; 06978 int fd; 06979 int exists; 06980 int minivid = 0; 06981 unsigned int ts; 06982 char empty[32]=""; /* Safety measure */ 06983 struct iax_frame *duped_fr; 06984 char host_pref_buf[128]; 06985 char caller_pref_buf[128]; 06986 struct ast_codec_pref pref; 06987 char *using_prefs = "mine"; 06988 06989 /* allocate an iax_frame with 4096 bytes of data buffer */ 06990 fr = alloca(sizeof(*fr) + 4096); 06991 memset(fr, 0, sizeof(*fr)); 06992 fr->afdatalen = 4096; /* From alloca() above */ 06993 06994 /* Copy frequently used parameters to the stack */ 06995 res = thread->buf_len; 06996 fd = thread->iofd; 06997 memcpy(&sin, &thread->iosin, sizeof(sin)); 06998 06999 if (res < sizeof(*mh)) { 07000 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh)); 07001 return 1; 07002 } 07003 if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { 07004 if (res < sizeof(*vh)) { 07005 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)); 07006 return 1; 07007 } 07008 07009 /* This is a video frame, get call number */ 07010 fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0); 07011 minivid = 1; 07012 } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) { 07013 unsigned char metatype; 07014 07015 if (res < sizeof(*meta)) { 07016 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07017 return 1; 07018 } 07019 07020 /* This is a meta header */ 07021 switch(meta->metacmd) { 07022 case IAX_META_TRUNK: 07023 if (res < (sizeof(*meta) + sizeof(*mth))) { 07024 ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res, 07025 sizeof(*meta) + sizeof(*mth)); 07026 return 1; 07027 } 07028 mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data); 07029 ts = ntohl(mth->ts); 07030 metatype = meta->cmddata; 07031 res -= (sizeof(*meta) + sizeof(*mth)); 07032 ptr = mth->data; 07033 tpeer = find_tpeer(&sin, fd); 07034 if (!tpeer) { 07035 ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07036 return 1; 07037 } 07038 tpeer->trunkact = ast_tvnow(); 07039 if (!ts || ast_tvzero(tpeer->rxtrunktime)) 07040 tpeer->rxtrunktime = tpeer->trunkact; 07041 rxtrunktime = tpeer->rxtrunktime; 07042 ast_mutex_unlock(&tpeer->lock); 07043 while(res >= sizeof(*mte)) { 07044 /* Process channels */ 07045 unsigned short callno, trunked_ts, len; 07046 07047 if (metatype == IAX_META_TRUNK_MINI) { 07048 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 07049 ptr += sizeof(*mtm); 07050 res -= sizeof(*mtm); 07051 len = ntohs(mtm->len); 07052 callno = ntohs(mtm->mini.callno); 07053 trunked_ts = ntohs(mtm->mini.ts); 07054 } else if (metatype == IAX_META_TRUNK_SUPERMINI) { 07055 mte = (struct ast_iax2_meta_trunk_entry *)ptr; 07056 ptr += sizeof(*mte); 07057 res -= sizeof(*mte); 07058 len = ntohs(mte->len); 07059 callno = ntohs(mte->callno); 07060 trunked_ts = 0; 07061 } else { 07062 ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07063 break; 07064 } 07065 /* Stop if we don't have enough data */ 07066 if (len > res) 07067 break; 07068 fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, fd, 0); 07069 if (fr->callno) { 07070 /* If it's a valid call, deliver the contents. If not, we 07071 drop it, since we don't have a scallno to use for an INVAL */ 07072 /* Process as a mini frame */ 07073 memset(&f, 0, sizeof(f)); 07074 f.frametype = AST_FRAME_VOICE; 07075 if (iaxs[fr->callno]) { 07076 if (iaxs[fr->callno]->voiceformat > 0) { 07077 f.subclass = iaxs[fr->callno]->voiceformat; 07078 f.datalen = len; 07079 if (f.datalen >= 0) { 07080 if (f.datalen) 07081 f.data = ptr; 07082 if(trunked_ts) { 07083 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff); 07084 } else 07085 fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts); 07086 /* Don't pass any packets until we're started */ 07087 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07088 /* Common things */ 07089 f.src = "IAX2"; 07090 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 07091 f.samples = ast_codec_get_samples(&f); 07092 iax_frame_wrap(fr, &f); 07093 duped_fr = iaxfrdup2(fr); 07094 if (duped_fr) { 07095 schedule_delivery(duped_fr, updatehistory, 1, &fr->ts); 07096 } 07097 /* It is possible for the pvt structure to go away after we call schedule_delivery */ 07098 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 07099 iaxs[fr->callno]->last = fr->ts; 07100 #if 1 07101 if (option_debug && iaxdebug) 07102 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 07103 #endif 07104 } 07105 } 07106 } else { 07107 ast_log(LOG_WARNING, "Datalen < 0?\n"); 07108 } 07109 } else { 07110 ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n "); 07111 iax2_vnak(fr->callno); 07112 } 07113 } 07114 ast_mutex_unlock(&iaxsl[fr->callno]); 07115 } 07116 ptr += len; 07117 res -= len; 07118 } 07119 07120 } 07121 return 1; 07122 } 07123 07124 #ifdef DEBUG_SUPPORT 07125 if (iaxdebug && (res >= sizeof(*fh))) 07126 iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh)); 07127 #endif 07128 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07129 if (res < sizeof(*fh)) { 07130 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)); 07131 return 1; 07132 } 07133 07134 /* Get the destination call number */ 07135 dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; 07136 /* Retrieve the type and subclass */ 07137 f.frametype = fh->type; 07138 if (f.frametype == AST_FRAME_VIDEO) { 07139 f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 07140 } else { 07141 f.subclass = uncompress_subclass(fh->csub); 07142 } 07143 07144 /* Deal with POKE/PONG without allocating a callno */ 07145 if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) { 07146 /* Reply back with a PONG, but don't care about the result. */ 07147 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohs(fh->ts), fh->oseqno); 07148 return 1; 07149 } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) { 07150 /* Ignore */ 07151 return 1; 07152 } 07153 07154 if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) || 07155 (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) || 07156 (f.subclass == IAX_COMMAND_REGREL))) 07157 new = NEW_ALLOW; 07158 } else { 07159 /* Don't know anything about it yet */ 07160 f.frametype = AST_FRAME_NULL; 07161 f.subclass = 0; 07162 } 07163 07164 if (!fr->callno) { 07165 int check_dcallno = 0; 07166 07167 /* 07168 * We enforce accurate destination call numbers for all full frames except 07169 * LAGRQ and PING commands. This is because older versions of Asterisk 07170 * schedule these commands to get sent very quickly, and they will sometimes 07171 * be sent before they receive the first frame from the other side. When 07172 * that happens, it doesn't contain the destination call number. However, 07173 * not checking it for these frames is safe. 07174 * 07175 * Discussed in the following thread: 07176 * http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 07177 */ 07178 07179 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07180 check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1; 07181 } 07182 07183 fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno); 07184 } 07185 07186 if (fr->callno > 0) 07187 ast_mutex_lock(&iaxsl[fr->callno]); 07188 07189 if (!fr->callno || !iaxs[fr->callno]) { 07190 /* A call arrived for a nonexistent destination. Unless it's an "inval" 07191 frame, reply with an inval */ 07192 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07193 /* We can only raw hangup control frames */ 07194 if (((f.subclass != IAX_COMMAND_INVAL) && 07195 (f.subclass != IAX_COMMAND_TXCNT) && 07196 (f.subclass != IAX_COMMAND_TXACC) && 07197 (f.subclass != IAX_COMMAND_FWDOWNL))|| 07198 (f.frametype != AST_FRAME_IAX)) 07199 raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL, 07200 fd); 07201 } 07202 if (fr->callno > 0) 07203 ast_mutex_unlock(&iaxsl[fr->callno]); 07204 return 1; 07205 } 07206 if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) { 07207 if (decrypt_frame(fr->callno, fh, &f, &res)) { 07208 ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); 07209 ast_mutex_unlock(&iaxsl[fr->callno]); 07210 return 1; 07211 } 07212 #ifdef DEBUG_SUPPORT 07213 else if (iaxdebug) 07214 iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh)); 07215 #endif 07216 } 07217 07218 /* count this frame */ 07219 iaxs[fr->callno]->frames_received++; 07220 07221 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid && 07222 f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */ 07223 f.subclass != IAX_COMMAND_TXACC) { /* for attended transfer */ 07224 unsigned short new_peercallno; 07225 07226 new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL); 07227 if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) { 07228 if (iaxs[fr->callno]->peercallno) { 07229 remove_by_peercallno(iaxs[fr->callno]); 07230 } 07231 iaxs[fr->callno]->peercallno = new_peercallno; 07232 store_by_peercallno(iaxs[fr->callno]); 07233 } 07234 } 07235 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07236 if (option_debug && iaxdebug) 07237 ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); 07238 /* Check if it's out of order (and not an ACK or INVAL) */ 07239 fr->oseqno = fh->oseqno; 07240 fr->iseqno = fh->iseqno; 07241 fr->ts = ntohl(fh->ts); 07242 #ifdef IAXTESTS 07243 if (test_resync) { 07244 if (option_debug) 07245 ast_log(LOG_DEBUG, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync); 07246 fr->ts += test_resync; 07247 } 07248 #endif /* IAXTESTS */ 07249 #if 0 07250 if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || 07251 ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX && 07252 (f.subclass == IAX_COMMAND_NEW || 07253 f.subclass == IAX_COMMAND_AUTHREQ || 07254 f.subclass == IAX_COMMAND_ACCEPT || 07255 f.subclass == IAX_COMMAND_REJECT)) ) ) 07256 #endif 07257 if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE)) 07258 updatehistory = 0; 07259 if ((iaxs[fr->callno]->iseqno != fr->oseqno) && 07260 (iaxs[fr->callno]->iseqno || 07261 ((f.subclass != IAX_COMMAND_TXCNT) && 07262 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 07263 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 07264 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 07265 (f.subclass != IAX_COMMAND_TXACC)) || 07266 (f.frametype != AST_FRAME_IAX))) { 07267 if ( 07268 ((f.subclass != IAX_COMMAND_ACK) && 07269 (f.subclass != IAX_COMMAND_INVAL) && 07270 (f.subclass != IAX_COMMAND_TXCNT) && 07271 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 07272 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 07273 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 07274 (f.subclass != IAX_COMMAND_TXACC) && 07275 (f.subclass != IAX_COMMAND_VNAK)) || 07276 (f.frametype != AST_FRAME_IAX)) { 07277 /* If it's not an ACK packet, it's out of order. */ 07278 if (option_debug) 07279 ast_log(LOG_DEBUG, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 07280 iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass); 07281 /* Check to see if we need to request retransmission, 07282 * and take sequence number wraparound into account */ 07283 if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) { 07284 /* If we've already seen it, ack it XXX There's a border condition here XXX */ 07285 if ((f.frametype != AST_FRAME_IAX) || 07286 ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) { 07287 if (option_debug) 07288 ast_log(LOG_DEBUG, "Acking anyway\n"); 07289 /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if 07290 we have anything to send, we'll retransmit and get an ACK back anyway XXX */ 07291 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07292 } 07293 } else { 07294 /* Send a VNAK requesting retransmission */ 07295 iax2_vnak(fr->callno); 07296 } 07297 ast_mutex_unlock(&iaxsl[fr->callno]); 07298 return 1; 07299 } 07300 } else { 07301 /* Increment unless it's an ACK or VNAK */ 07302 if (((f.subclass != IAX_COMMAND_ACK) && 07303 (f.subclass != IAX_COMMAND_INVAL) && 07304 (f.subclass != IAX_COMMAND_TXCNT) && 07305 (f.subclass != IAX_COMMAND_TXACC) && 07306 (f.subclass != IAX_COMMAND_VNAK)) || 07307 (f.frametype != AST_FRAME_IAX)) 07308 iaxs[fr->callno]->iseqno++; 07309 } 07310 /* A full frame */ 07311 if (res < sizeof(*fh)) { 07312 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh)); 07313 ast_mutex_unlock(&iaxsl[fr->callno]); 07314 return 1; 07315 } 07316 /* Ensure text frames are NULL-terminated */ 07317 if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') { 07318 if (res < thread->buf_size) 07319 thread->buf[res++] = '\0'; 07320 else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */ 07321 thread->buf[res - 1] = '\0'; 07322 } 07323 f.datalen = res - sizeof(*fh); 07324 07325 /* Handle implicit ACKing unless this is an INVAL, and only if this is 07326 from the real peer, not the transfer peer */ 07327 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 07328 ((f.subclass != IAX_COMMAND_INVAL) || 07329 (f.frametype != AST_FRAME_IAX))) { 07330 unsigned char x; 07331 int call_to_destroy; 07332 /* XXX This code is not very efficient. Surely there is a better way which still 07333 properly handles boundary conditions? XXX */ 07334 /* First we have to qualify that the ACKed value is within our window */ 07335 for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++) 07336 if (fr->iseqno == x) 07337 break; 07338 if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) { 07339 /* The acknowledgement is within our window. Time to acknowledge everything 07340 that it says to */ 07341 for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) { 07342 /* Ack the packet with the given timestamp */ 07343 if (option_debug && iaxdebug) 07344 ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x); 07345 call_to_destroy = 0; 07346 AST_LIST_LOCK(&iaxq.queue); 07347 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 07348 /* If it's our call, and our timestamp, mark -1 retries */ 07349 if ((fr->callno == cur->callno) && (x == cur->oseqno)) { 07350 cur->retries = -1; 07351 /* Destroy call if this is the end */ 07352 if (cur->final) 07353 call_to_destroy = fr->callno; 07354 } 07355 } 07356 AST_LIST_UNLOCK(&iaxq.queue); 07357 if (call_to_destroy) { 07358 if (iaxdebug && option_debug) 07359 ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy); 07360 ast_mutex_lock(&iaxsl[call_to_destroy]); 07361 iax2_destroy(call_to_destroy); 07362 ast_mutex_unlock(&iaxsl[call_to_destroy]); 07363 } 07364 } 07365 /* Note how much we've received acknowledgement for */ 07366 if (iaxs[fr->callno]) 07367 iaxs[fr->callno]->rseqno = fr->iseqno; 07368 else { 07369 /* Stop processing now */ 07370 ast_mutex_unlock(&iaxsl[fr->callno]); 07371 return 1; 07372 } 07373 } else if (option_debug) 07374 ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno); 07375 } 07376 if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 07377 ((f.frametype != AST_FRAME_IAX) || 07378 ((f.subclass != IAX_COMMAND_TXACC) && 07379 (f.subclass != IAX_COMMAND_TXCNT)))) { 07380 /* Only messages we accept from a transfer host are TXACC and TXCNT */ 07381 ast_mutex_unlock(&iaxsl[fr->callno]); 07382 return 1; 07383 } 07384 07385 if (f.datalen) { 07386 if (f.frametype == AST_FRAME_IAX) { 07387 if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) { 07388 ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); 07389 ast_mutex_unlock(&iaxsl[fr->callno]); 07390 return 1; 07391 } 07392 f.data = NULL; 07393 f.datalen = 0; 07394 } else 07395 f.data = thread->buf + sizeof(*fh); 07396 } else { 07397 if (f.frametype == AST_FRAME_IAX) 07398 f.data = NULL; 07399 else 07400 f.data = empty; 07401 memset(&ies, 0, sizeof(ies)); 07402 } 07403 07404 /* when we receive the first full frame for a new incoming channel, 07405 it is safe to start the PBX on the channel because we have now 07406 completed a 3-way handshake with the peer */ 07407 if ((f.frametype == AST_FRAME_VOICE) || 07408 (f.frametype == AST_FRAME_VIDEO) || 07409 (f.frametype == AST_FRAME_IAX)) { 07410 if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) { 07411 ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 07412 if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) { 07413 ast_mutex_unlock(&iaxsl[fr->callno]); 07414 return 1; 07415 } 07416 } 07417 } 07418 07419 if (f.frametype == AST_FRAME_VOICE) { 07420 if (f.subclass != iaxs[fr->callno]->voiceformat) { 07421 iaxs[fr->callno]->voiceformat = f.subclass; 07422 if (option_debug) 07423 ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass); 07424 if (iaxs[fr->callno]->owner) { 07425 int orignative; 07426 retryowner: 07427 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 07428 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 07429 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; 07430 } 07431 if (iaxs[fr->callno]) { 07432 if (iaxs[fr->callno]->owner) { 07433 orignative = iaxs[fr->callno]->owner->nativeformats; 07434 iaxs[fr->callno]->owner->nativeformats = f.subclass; 07435 if (iaxs[fr->callno]->owner->readformat) 07436 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 07437 iaxs[fr->callno]->owner->nativeformats = orignative; 07438 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 07439 } 07440 } else { 07441 if (option_debug) 07442 ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n"); 07443 ast_mutex_unlock(&iaxsl[fr->callno]); 07444 return 1; 07445 } 07446 } 07447 } 07448 } 07449 if (f.frametype == AST_FRAME_VIDEO) { 07450 if (f.subclass != iaxs[fr->callno]->videoformat) { 07451 if (option_debug) 07452 ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1); 07453 iaxs[fr->callno]->videoformat = f.subclass & ~0x1; 07454 } 07455 } 07456 if (f.frametype == AST_FRAME_IAX) { 07457 AST_SCHED_DEL(sched, iaxs[fr->callno]->initid); 07458 /* Handle the IAX pseudo frame itself */ 07459 if (option_debug && iaxdebug) 07460 ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass); 07461 07462 /* Update last ts unless the frame's timestamp originated with us. */ 07463 if (iaxs[fr->callno]->last < fr->ts && 07464 f.subclass != IAX_COMMAND_ACK && 07465 f.subclass != IAX_COMMAND_PONG && 07466 f.subclass != IAX_COMMAND_LAGRP) { 07467 iaxs[fr->callno]->last = fr->ts; 07468 if (option_debug && iaxdebug) 07469 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 07470 } 07471 07472 switch(f.subclass) { 07473 case IAX_COMMAND_ACK: 07474 /* Do nothing */ 07475 break; 07476 case IAX_COMMAND_QUELCH: 07477 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07478 /* Generate Manager Hold event, if necessary*/ 07479 if (iaxs[fr->callno]->owner) { 07480 manager_event(EVENT_FLAG_CALL, "Hold", 07481 "Channel: %s\r\n" 07482 "Uniqueid: %s\r\n", 07483 iaxs[fr->callno]->owner->name, 07484 iaxs[fr->callno]->owner->uniqueid); 07485 } 07486 07487 ast_set_flag(iaxs[fr->callno], IAX_QUELCH); 07488 if (ies.musiconhold) { 07489 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 07490 const char *mohsuggest = iaxs[fr->callno]->mohsuggest; 07491 iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 07492 S_OR(mohsuggest, NULL), 07493 !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0); 07494 if (!iaxs[fr->callno]) { 07495 ast_mutex_unlock(&iaxsl[fr->callno]); 07496 return 1; 07497 } 07498 } 07499 } 07500 } 07501 break; 07502 case IAX_COMMAND_UNQUELCH: 07503 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07504 /* Generate Manager Unhold event, if necessary*/ 07505 if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) { 07506 manager_event(EVENT_FLAG_CALL, "Unhold", 07507 "Channel: %s\r\n" 07508 "Uniqueid: %s\r\n", 07509 iaxs[fr->callno]->owner->name, 07510 iaxs[fr->callno]->owner->uniqueid); 07511 } 07512 07513 ast_clear_flag(iaxs[fr->callno], IAX_QUELCH); 07514 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 07515 iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); 07516 if (!iaxs[fr->callno]) { 07517 ast_mutex_unlock(&iaxsl[fr->callno]); 07518 return 1; 07519 } 07520 } 07521 } 07522 break; 07523 case IAX_COMMAND_TXACC: 07524 if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { 07525 /* Ack the packet with the given timestamp */ 07526 AST_LIST_LOCK(&iaxq.queue); 07527 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 07528 /* Cancel any outstanding txcnt's */ 07529 if ((fr->callno == cur->callno) && (cur->transfer)) 07530 cur->retries = -1; 07531 } 07532 AST_LIST_UNLOCK(&iaxq.queue); 07533 memset(&ied1, 0, sizeof(ied1)); 07534 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno); 07535 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1); 07536 iaxs[fr->callno]->transferring = TRANSFER_READY; 07537 } 07538 break; 07539 case IAX_COMMAND_NEW: 07540 /* Ignore if it's already up */ 07541 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) 07542 break; 07543 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 07544 ast_mutex_unlock(&iaxsl[fr->callno]); 07545 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 07546 ast_mutex_lock(&iaxsl[fr->callno]); 07547 if (!iaxs[fr->callno]) { 07548 ast_mutex_unlock(&iaxsl[fr->callno]); 07549 return 1; 07550 } 07551 } 07552 /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ 07553 if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) { 07554 int new_callno; 07555 if ((new_callno = make_trunk(fr->callno, 1)) != -1) 07556 fr->callno = new_callno; 07557 } 07558 /* For security, always ack immediately */ 07559 if (delayreject) 07560 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07561 if (check_access(fr->callno, &sin, &ies)) { 07562 /* They're not allowed on */ 07563 auth_fail(fr->callno, IAX_COMMAND_REJECT); 07564 if (authdebug) 07565 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); 07566 break; 07567 } 07568 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 07569 const char *context, *exten, *cid_num; 07570 07571 context = ast_strdupa(iaxs[fr->callno]->context); 07572 exten = ast_strdupa(iaxs[fr->callno]->exten); 07573 cid_num = ast_strdupa(iaxs[fr->callno]->cid_num); 07574 07575 /* This might re-enter the IAX code and need the lock */ 07576 ast_mutex_unlock(&iaxsl[fr->callno]); 07577 exists = ast_exists_extension(NULL, context, exten, 1, cid_num); 07578 ast_mutex_lock(&iaxsl[fr->callno]); 07579 07580 if (!iaxs[fr->callno]) { 07581 ast_mutex_unlock(&iaxsl[fr->callno]); 07582 return 1; 07583 } 07584 } else 07585 exists = 0; 07586 if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { 07587 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 07588 memset(&ied0, 0, sizeof(ied0)); 07589 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 07590 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 07591 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07592 if (!iaxs[fr->callno]) { 07593 ast_mutex_unlock(&iaxsl[fr->callno]); 07594 return 1; 07595 } 07596 if (authdebug) 07597 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); 07598 } else { 07599 /* Select an appropriate format */ 07600 07601 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07602 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07603 using_prefs = "reqonly"; 07604 } else { 07605 using_prefs = "disabled"; 07606 } 07607 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 07608 memset(&pref, 0, sizeof(pref)); 07609 strcpy(caller_pref_buf, "disabled"); 07610 strcpy(host_pref_buf, "disabled"); 07611 } else { 07612 using_prefs = "mine"; 07613 /* If the information elements are in here... use them */ 07614 if (ies.codec_prefs) 07615 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 07616 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07617 /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ 07618 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07619 pref = iaxs[fr->callno]->rprefs; 07620 using_prefs = "caller"; 07621 } else { 07622 pref = iaxs[fr->callno]->prefs; 07623 } 07624 } else 07625 pref = iaxs[fr->callno]->prefs; 07626 07627 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 07628 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 07629 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 07630 } 07631 if (!format) { 07632 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07633 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 07634 if (!format) { 07635 memset(&ied0, 0, sizeof(ied0)); 07636 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07637 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07638 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07639 if (!iaxs[fr->callno]) { 07640 ast_mutex_unlock(&iaxsl[fr->callno]); 07641 return 1; 07642 } 07643 if (authdebug) { 07644 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07645 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); 07646 else 07647 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); 07648 } 07649 } else { 07650 /* Pick one... */ 07651 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07652 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 07653 format = 0; 07654 } else { 07655 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07656 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 07657 memset(&pref, 0, sizeof(pref)); 07658 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07659 strcpy(caller_pref_buf,"disabled"); 07660 strcpy(host_pref_buf,"disabled"); 07661 } else { 07662 using_prefs = "mine"; 07663 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07664 /* Do the opposite of what we tried above. */ 07665 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07666 pref = iaxs[fr->callno]->prefs; 07667 } else { 07668 pref = iaxs[fr->callno]->rprefs; 07669 using_prefs = "caller"; 07670 } 07671 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 07672 07673 } else /* if no codec_prefs IE do it the old way */ 07674 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07675 } 07676 } 07677 07678 if (!format) { 07679 memset(&ied0, 0, sizeof(ied0)); 07680 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07681 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07682 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07683 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07684 if (!iaxs[fr->callno]) { 07685 ast_mutex_unlock(&iaxsl[fr->callno]); 07686 return 1; 07687 } 07688 if (authdebug) 07689 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); 07690 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07691 break; 07692 } 07693 } 07694 } 07695 if (format) { 07696 /* No authentication required, let them in */ 07697 memset(&ied1, 0, sizeof(ied1)); 07698 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 07699 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 07700 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 07701 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07702 if (option_verbose > 2) 07703 ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n" 07704 "%srequested format = %s,\n" 07705 "%srequested prefs = %s,\n" 07706 "%sactual format = %s,\n" 07707 "%shost prefs = %s,\n" 07708 "%spriority = %s\n", 07709 ast_inet_ntoa(sin.sin_addr), 07710 VERBOSE_PREFIX_4, 07711 ast_getformatname(iaxs[fr->callno]->peerformat), 07712 VERBOSE_PREFIX_4, 07713 caller_pref_buf, 07714 VERBOSE_PREFIX_4, 07715 ast_getformatname(format), 07716 VERBOSE_PREFIX_4, 07717 host_pref_buf, 07718 VERBOSE_PREFIX_4, 07719 using_prefs); 07720 07721 iaxs[fr->callno]->chosenformat = format; 07722 ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 07723 } else { 07724 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 07725 /* If this is a TBD call, we're ready but now what... */ 07726 if (option_verbose > 2) 07727 ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 07728 } 07729 } 07730 } 07731 break; 07732 } 07733 if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5) 07734 merge_encryption(iaxs[fr->callno],ies.encmethods); 07735 else 07736 iaxs[fr->callno]->encmethods = 0; 07737 if (!authenticate_request(fr->callno) && iaxs[fr->callno]) 07738 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); 07739 if (!iaxs[fr->callno]) { 07740 ast_mutex_unlock(&iaxsl[fr->callno]); 07741 return 1; 07742 } 07743 break; 07744 case IAX_COMMAND_DPREQ: 07745 /* Request status in the dialplan */ 07746 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) && 07747 !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) { 07748 if (iaxcompat) { 07749 /* Spawn a thread for the lookup */ 07750 spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num); 07751 } else { 07752 /* Just look it up */ 07753 dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1); 07754 } 07755 } 07756 break; 07757 case IAX_COMMAND_HANGUP: 07758 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07759 if (option_debug) 07760 ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr->callno); 07761 /* Set hangup cause according to remote */ 07762 if (ies.causecode && iaxs[fr->callno]->owner) 07763 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07764 /* Send ack immediately, before we destroy */ 07765 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07766 iax2_destroy(fr->callno); 07767 break; 07768 case IAX_COMMAND_REJECT: 07769 /* Set hangup cause according to remote */ 07770 if (ies.causecode && iaxs[fr->callno]->owner) 07771 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07772 07773 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07774 if (iaxs[fr->callno]->owner && authdebug) 07775 ast_log(LOG_WARNING, "Call rejected by %s: %s\n", 07776 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), 07777 ies.cause ? ies.cause : "<Unknown>"); 07778 if (option_debug) 07779 ast_log(LOG_DEBUG, "Immediately destroying %d, having received reject\n", 07780 fr->callno); 07781 } 07782 /* Send ack immediately, before we destroy */ 07783 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, 07784 fr->ts, NULL, 0, fr->iseqno); 07785 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) 07786 iaxs[fr->callno]->error = EPERM; 07787 iax2_destroy(fr->callno); 07788 break; 07789 case IAX_COMMAND_TRANSFER: 07790 { 07791 struct ast_channel *bridged_chan; 07792 07793 if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) { 07794 /* Set BLINDTRANSFER channel variables */ 07795 07796 ast_mutex_unlock(&iaxsl[fr->callno]); 07797 pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name); 07798 ast_mutex_lock(&iaxsl[fr->callno]); 07799 if (!iaxs[fr->callno]) { 07800 ast_mutex_unlock(&iaxsl[fr->callno]); 07801 return 1; 07802 } 07803 07804 pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name); 07805 if (!strcmp(ies.called_number, ast_parking_ext())) { 07806 if (iax_park(bridged_chan, iaxs[fr->callno]->owner)) { 07807 ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name); 07808 } else { 07809 ast_log(LOG_DEBUG, "Parked call on '%s'\n", bridged_chan->name); 07810 } 07811 } else { 07812 if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1)) 07813 ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 07814 ies.called_number, iaxs[fr->callno]->context); 07815 else 07816 ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 07817 ies.called_number, iaxs[fr->callno]->context); 07818 } 07819 } else 07820 ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr->callno); 07821 07822 break; 07823 } 07824 case IAX_COMMAND_ACCEPT: 07825 /* Ignore if call is already up or needs authentication or is a TBD */ 07826 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED)) 07827 break; 07828 if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07829 /* Send ack immediately, before we destroy */ 07830 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07831 iax2_destroy(fr->callno); 07832 break; 07833 } 07834 if (ies.format) { 07835 iaxs[fr->callno]->peerformat = ies.format; 07836 } else { 07837 if (iaxs[fr->callno]->owner) 07838 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; 07839 else 07840 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; 07841 } 07842 if (option_verbose > 2) 07843 ast_verbose(VERBOSE_PREFIX_3 "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat)); 07844 if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { 07845 memset(&ied0, 0, sizeof(ied0)); 07846 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07847 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07848 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07849 if (!iaxs[fr->callno]) { 07850 ast_mutex_unlock(&iaxsl[fr->callno]); 07851 return 1; 07852 } 07853 if (authdebug) 07854 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); 07855 } else { 07856 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07857 if (iaxs[fr->callno]->owner) { 07858 /* Switch us to use a compatible format */ 07859 iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; 07860 if (option_verbose > 2) 07861 ast_verbose(VERBOSE_PREFIX_3 "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); 07862 retryowner2: 07863 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 07864 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 07865 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; 07866 } 07867 07868 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { 07869 /* Setup read/write formats properly. */ 07870 if (iaxs[fr->callno]->owner->writeformat) 07871 ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); 07872 if (iaxs[fr->callno]->owner->readformat) 07873 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 07874 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 07875 } 07876 } 07877 } 07878 if (iaxs[fr->callno]) { 07879 ast_mutex_lock(&dpcache_lock); 07880 dp = iaxs[fr->callno]->dpentries; 07881 while(dp) { 07882 if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) { 07883 iax2_dprequest(dp, fr->callno); 07884 } 07885 dp = dp->peer; 07886 } 07887 ast_mutex_unlock(&dpcache_lock); 07888 } 07889 break; 07890 case IAX_COMMAND_POKE: 07891 /* Send back a pong packet with the original timestamp */ 07892 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); 07893 if (!iaxs[fr->callno]) { 07894 ast_mutex_unlock(&iaxsl[fr->callno]); 07895 return 1; 07896 } 07897 break; 07898 case IAX_COMMAND_PING: 07899 { 07900 struct iax_ie_data pingied; 07901 construct_rr(iaxs[fr->callno], &pingied); 07902 /* Send back a pong packet with the original timestamp */ 07903 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1); 07904 } 07905 break; 07906 case IAX_COMMAND_PONG: 07907 /* Calculate ping time */ 07908 iaxs[fr->callno]->pingtime = calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts; 07909 /* save RR info */ 07910 save_rr(fr, &ies); 07911 07912 if (iaxs[fr->callno]->peerpoke) { 07913 peer = iaxs[fr->callno]->peerpoke; 07914 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) { 07915 if (iaxs[fr->callno]->pingtime <= peer->maxms) { 07916 ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime); 07917 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07918 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07919 } 07920 } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) { 07921 if (iaxs[fr->callno]->pingtime > peer->maxms) { 07922 ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime); 07923 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07924 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07925 } 07926 } 07927 peer->lastms = iaxs[fr->callno]->pingtime; 07928 if (peer->smoothing && (peer->lastms > -1)) 07929 peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2; 07930 else if (peer->smoothing && peer->lastms < 0) 07931 peer->historicms = (0 + peer->historicms) / 2; 07932 else 07933 peer->historicms = iaxs[fr->callno]->pingtime; 07934 07935 /* Remove scheduled iax2_poke_noanswer */ 07936 if (peer->pokeexpire > -1) { 07937 if (!ast_sched_del(sched, peer->pokeexpire)) { 07938 peer_unref(peer); 07939 peer->pokeexpire = -1; 07940 } 07941 } 07942 /* Schedule the next cycle */ 07943 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) 07944 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 07945 else 07946 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer)); 07947 if (peer->pokeexpire == -1) 07948 peer_unref(peer); 07949 /* and finally send the ack */ 07950 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07951 /* And wrap up the qualify call */ 07952 iax2_destroy(fr->callno); 07953 peer->callno = 0; 07954 if (option_debug) 07955 ast_log(LOG_DEBUG, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms); 07956 } 07957 break; 07958 case IAX_COMMAND_LAGRQ: 07959 case IAX_COMMAND_LAGRP: 07960 f.src = "LAGRQ"; 07961 f.mallocd = 0; 07962 f.offset = 0; 07963 f.samples = 0; 07964 iax_frame_wrap(fr, &f); 07965 if(f.subclass == IAX_COMMAND_LAGRQ) { 07966 /* Received a LAGRQ - echo back a LAGRP */ 07967 fr->af.subclass = IAX_COMMAND_LAGRP; 07968 iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0); 07969 } else { 07970 /* Received LAGRP in response to our LAGRQ */ 07971 unsigned int ts; 07972 /* This is a reply we've been given, actually measure the difference */ 07973 ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af); 07974 iaxs[fr->callno]->lag = ts - fr->ts; 07975 if (option_debug && iaxdebug) 07976 ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n", 07977 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag); 07978 } 07979 break; 07980 case IAX_COMMAND_AUTHREQ: 07981 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 07982 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>"); 07983 break; 07984 } 07985 if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) { 07986 struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL, 07987 .subclass = AST_CONTROL_HANGUP, 07988 }; 07989 ast_log(LOG_WARNING, 07990 "I don't know how to authenticate %s to %s\n", 07991 ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); 07992 iax2_queue_frame(fr->callno, &hangup_fr); 07993 } 07994 if (!iaxs[fr->callno]) { 07995 ast_mutex_unlock(&iaxsl[fr->callno]); 07996 return 1; 07997 } 07998 break; 07999 case IAX_COMMAND_AUTHREP: 08000 /* For security, always ack immediately */ 08001 if (delayreject) 08002 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08003 /* Ignore once we've started */ 08004 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 08005 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>"); 08006 break; 08007 } 08008 if (authenticate_verify(iaxs[fr->callno], &ies)) { 08009 if (authdebug) 08010 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); 08011 memset(&ied0, 0, sizeof(ied0)); 08012 auth_fail(fr->callno, IAX_COMMAND_REJECT); 08013 break; 08014 } 08015 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 08016 /* This might re-enter the IAX code and need the lock */ 08017 exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num); 08018 } else 08019 exists = 0; 08020 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 08021 if (authdebug) 08022 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); 08023 memset(&ied0, 0, sizeof(ied0)); 08024 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08025 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 08026 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08027 if (!iaxs[fr->callno]) { 08028 ast_mutex_unlock(&iaxsl[fr->callno]); 08029 return 1; 08030 } 08031 } else { 08032 /* Select an appropriate format */ 08033 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08034 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08035 using_prefs = "reqonly"; 08036 } else { 08037 using_prefs = "disabled"; 08038 } 08039 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 08040 memset(&pref, 0, sizeof(pref)); 08041 strcpy(caller_pref_buf, "disabled"); 08042 strcpy(host_pref_buf, "disabled"); 08043 } else { 08044 using_prefs = "mine"; 08045 if (ies.codec_prefs) 08046 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 08047 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08048 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08049 pref = iaxs[fr->callno]->rprefs; 08050 using_prefs = "caller"; 08051 } else { 08052 pref = iaxs[fr->callno]->prefs; 08053 } 08054 } else /* if no codec_prefs IE do it the old way */ 08055 pref = iaxs[fr->callno]->prefs; 08056 08057 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 08058 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 08059 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 08060 } 08061 if (!format) { 08062 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08063 if (option_debug) 08064 ast_log(LOG_DEBUG, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability); 08065 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 08066 } 08067 if (!format) { 08068 if (authdebug) { 08069 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08070 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); 08071 else 08072 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); 08073 } 08074 memset(&ied0, 0, sizeof(ied0)); 08075 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08076 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08077 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08078 if (!iaxs[fr->callno]) { 08079 ast_mutex_unlock(&iaxsl[fr->callno]); 08080 return 1; 08081 } 08082 } else { 08083 /* Pick one... */ 08084 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08085 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 08086 format = 0; 08087 } else { 08088 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08089 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 08090 memset(&pref, 0, sizeof(pref)); 08091 format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? 08092 iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08093 strcpy(caller_pref_buf,"disabled"); 08094 strcpy(host_pref_buf,"disabled"); 08095 } else { 08096 using_prefs = "mine"; 08097 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08098 /* Do the opposite of what we tried above. */ 08099 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08100 pref = iaxs[fr->callno]->prefs; 08101 } else { 08102 pref = iaxs[fr->callno]->rprefs; 08103 using_prefs = "caller"; 08104 } 08105 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 08106 } else /* if no codec_prefs IE do it the old way */ 08107 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08108 } 08109 } 08110 if (!format) { 08111 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08112 if (authdebug) { 08113 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08114 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); 08115 else 08116 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); 08117 } 08118 memset(&ied0, 0, sizeof(ied0)); 08119 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08120 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08121 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08122 if (!iaxs[fr->callno]) { 08123 ast_mutex_unlock(&iaxsl[fr->callno]); 08124 return 1; 08125 } 08126 } 08127 } 08128 } 08129 if (format) { 08130 /* Authentication received */ 08131 memset(&ied1, 0, sizeof(ied1)); 08132 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 08133 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 08134 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 08135 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08136 if (option_verbose > 2) 08137 ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n" 08138 "%srequested format = %s,\n" 08139 "%srequested prefs = %s,\n" 08140 "%sactual format = %s,\n" 08141 "%shost prefs = %s,\n" 08142 "%spriority = %s\n", 08143 ast_inet_ntoa(sin.sin_addr), 08144 VERBOSE_PREFIX_4, 08145 ast_getformatname(iaxs[fr->callno]->peerformat), 08146 VERBOSE_PREFIX_4, 08147 caller_pref_buf, 08148 VERBOSE_PREFIX_4, 08149 ast_getformatname(format), 08150 VERBOSE_PREFIX_4, 08151 host_pref_buf, 08152 VERBOSE_PREFIX_4, 08153 using_prefs); 08154 08155 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08156 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format))) 08157 iax2_destroy(fr->callno); 08158 } else { 08159 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08160 /* If this is a TBD call, we're ready but now what... */ 08161 if (option_verbose > 2) 08162 ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 08163 } 08164 } 08165 } 08166 break; 08167 case IAX_COMMAND_DIAL: 08168 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) { 08169 ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08170 ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); 08171 if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { 08172 if (authdebug) 08173 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); 08174 memset(&ied0, 0, sizeof(ied0)); 08175 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08176 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 08177 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08178 if (!iaxs[fr->callno]) { 08179 ast_mutex_unlock(&iaxsl[fr->callno]); 08180 return 1; 08181 } 08182 } else { 08183 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08184 if (option_verbose > 2) 08185 ast_verbose(VERBOSE_PREFIX_3 "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat); 08186 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08187 send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); 08188 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat))) 08189 iax2_destroy(fr->callno); 08190 } 08191 } 08192 break; 08193 case IAX_COMMAND_INVAL: 08194 iaxs[fr->callno]->error = ENOTCONN; 08195 if (option_debug) 08196 ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr->callno); 08197 iax2_destroy(fr->callno); 08198 if (option_debug) 08199 ast_log(LOG_DEBUG, "Destroying call %d\n", fr->callno); 08200 break; 08201 case IAX_COMMAND_VNAK: 08202 if (option_debug) 08203 ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n"); 08204 /* Force retransmission */ 08205 vnak_retransmit(fr->callno, fr->iseqno); 08206 break; 08207 case IAX_COMMAND_REGREQ: 08208 case IAX_COMMAND_REGREL: 08209 /* For security, always ack immediately */ 08210 if (delayreject) 08211 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08212 if (register_verify(fr->callno, &sin, &ies)) { 08213 if (!iaxs[fr->callno]) { 08214 ast_mutex_unlock(&iaxsl[fr->callno]); 08215 return 1; 08216 } 08217 /* Send delayed failure */ 08218 auth_fail(fr->callno, IAX_COMMAND_REGREJ); 08219 break; 08220 } 08221 if (!iaxs[fr->callno]) { 08222 ast_mutex_unlock(&iaxsl[fr->callno]); 08223 return 1; 08224 } 08225 if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 08226 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) { 08227 if (f.subclass == IAX_COMMAND_REGREL) 08228 memset(&sin, 0, sizeof(sin)); 08229 if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) 08230 ast_log(LOG_WARNING, "Registry error\n"); 08231 if (!iaxs[fr->callno]) { 08232 ast_mutex_unlock(&iaxsl[fr->callno]); 08233 return 1; 08234 } 08235 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 08236 ast_mutex_unlock(&iaxsl[fr->callno]); 08237 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 08238 ast_mutex_lock(&iaxsl[fr->callno]); 08239 if (!iaxs[fr->callno]) { 08240 ast_mutex_unlock(&iaxsl[fr->callno]); 08241 return 1; 08242 } 08243 } 08244 break; 08245 } 08246 registry_authrequest(fr->callno); 08247 if (!iaxs[fr->callno]) { 08248 ast_mutex_unlock(&iaxsl[fr->callno]); 08249 return 1; 08250 } 08251 break; 08252 case IAX_COMMAND_REGACK: 08253 if (iax2_ack_registry(&ies, &sin, fr->callno)) 08254 ast_log(LOG_WARNING, "Registration failure\n"); 08255 /* Send ack immediately, before we destroy */ 08256 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08257 iax2_destroy(fr->callno); 08258 break; 08259 case IAX_COMMAND_REGREJ: 08260 if (iaxs[fr->callno]->reg) { 08261 if (authdebug) { 08262 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)); 08263 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>"); 08264 } 08265 iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; 08266 } 08267 /* Send ack immediately, before we destroy */ 08268 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08269 iax2_destroy(fr->callno); 08270 break; 08271 case IAX_COMMAND_REGAUTH: 08272 /* Authentication request */ 08273 if (registry_rerequest(&ies, fr->callno, &sin)) { 08274 memset(&ied0, 0, sizeof(ied0)); 08275 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); 08276 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 08277 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08278 if (!iaxs[fr->callno]) { 08279 ast_mutex_unlock(&iaxsl[fr->callno]); 08280 return 1; 08281 } 08282 } 08283 break; 08284 case IAX_COMMAND_TXREJ: 08285 iaxs[fr->callno]->transferring = 0; 08286 if (option_verbose > 2) 08287 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 08288 memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer)); 08289 if (iaxs[fr->callno]->bridgecallno) { 08290 if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { 08291 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0; 08292 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 08293 } 08294 } 08295 break; 08296 case IAX_COMMAND_TXREADY: 08297 if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || 08298 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) { 08299 if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) 08300 iaxs[fr->callno]->transferring = TRANSFER_MREADY; 08301 else 08302 iaxs[fr->callno]->transferring = TRANSFER_READY; 08303 if (option_verbose > 2) 08304 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 08305 if (iaxs[fr->callno]->bridgecallno) { 08306 if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || 08307 (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { 08308 /* They're both ready, now release them. */ 08309 if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) { 08310 if (option_verbose > 2) 08311 ast_verbose(VERBOSE_PREFIX_3 "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 08312 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 08313 08314 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; 08315 iaxs[fr->callno]->transferring = TRANSFER_MEDIA; 08316 08317 memset(&ied0, 0, sizeof(ied0)); 08318 memset(&ied1, 0, sizeof(ied1)); 08319 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 08320 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 08321 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1); 08322 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1); 08323 } else { 08324 if (option_verbose > 2) 08325 ast_verbose(VERBOSE_PREFIX_3 "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 08326 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 08327 08328 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED; 08329 iaxs[fr->callno]->transferring = TRANSFER_RELEASED; 08330 ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE); 08331 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 08332 08333 /* Stop doing lag & ping requests */ 08334 stop_stuff(fr->callno); 08335 stop_stuff(iaxs[fr->callno]->bridgecallno); 08336 08337 memset(&ied0, 0, sizeof(ied0)); 08338 memset(&ied1, 0, sizeof(ied1)); 08339 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 08340 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 08341 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1); 08342 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1); 08343 } 08344 08345 } 08346 } 08347 } 08348 break; 08349 case IAX_COMMAND_TXREQ: 08350 try_transfer(iaxs[fr->callno], &ies); 08351 break; 08352 case IAX_COMMAND_TXCNT: 08353 if (iaxs[fr->callno]->transferring) 08354 send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); 08355 break; 08356 case IAX_COMMAND_TXREL: 08357 /* Send ack immediately, rather than waiting until we've changed addresses */ 08358 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08359 complete_transfer(fr->callno, &ies); 08360 stop_stuff(fr->callno); /* for attended transfer to work with libiax */ 08361 break; 08362 case IAX_COMMAND_TXMEDIA: 08363 if (iaxs[fr->callno]->transferring == TRANSFER_READY) { 08364 AST_LIST_LOCK(&iaxq.queue); 08365 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 08366 /* Cancel any outstanding frames and start anew */ 08367 if ((fr->callno == cur->callno) && (cur->transfer)) { 08368 cur->retries = -1; 08369 } 08370 } 08371 AST_LIST_UNLOCK(&iaxq.queue); 08372 /* Start sending our media to the transfer address, but otherwise leave the call as-is */ 08373 iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS; 08374 } 08375 break; 08376 case IAX_COMMAND_DPREP: 08377 complete_dpreply(iaxs[fr->callno], &ies); 08378 break; 08379 case IAX_COMMAND_UNSUPPORT: 08380 ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown); 08381 break; 08382 case IAX_COMMAND_FWDOWNL: 08383 /* Firmware download */ 08384 if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) { 08385 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1); 08386 break; 08387 } 08388 memset(&ied0, 0, sizeof(ied0)); 08389 res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc); 08390 if (res < 0) 08391 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08392 else if (res > 0) 08393 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 08394 else 08395 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 08396 if (!iaxs[fr->callno]) { 08397 ast_mutex_unlock(&iaxsl[fr->callno]); 08398 return 1; 08399 } 08400 break; 08401 default: 08402 if (option_debug) 08403 ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno); 08404 memset(&ied0, 0, sizeof(ied0)); 08405 iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass); 08406 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1); 08407 } 08408 /* Don't actually pass these frames along */ 08409 if ((f.subclass != IAX_COMMAND_ACK) && 08410 (f.subclass != IAX_COMMAND_TXCNT) && 08411 (f.subclass != IAX_COMMAND_TXACC) && 08412 (f.subclass != IAX_COMMAND_INVAL) && 08413 (f.subclass != IAX_COMMAND_VNAK)) { 08414 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 08415 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08416 } 08417 ast_mutex_unlock(&iaxsl[fr->callno]); 08418 return 1; 08419 } 08420 /* Unless this is an ACK or INVAL frame, ack it */ 08421 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 08422 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08423 } else if (minivid) { 08424 f.frametype = AST_FRAME_VIDEO; 08425 if (iaxs[fr->callno]->videoformat > 0) 08426 f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); 08427 else { 08428 ast_log(LOG_WARNING, "Received mini frame before first full video frame\n "); 08429 iax2_vnak(fr->callno); 08430 ast_mutex_unlock(&iaxsl[fr->callno]); 08431 return 1; 08432 } 08433 f.datalen = res - sizeof(*vh); 08434 if (f.datalen) 08435 f.data = thread->buf + sizeof(*vh); 08436 else 08437 f.data = NULL; 08438 #ifdef IAXTESTS 08439 if (test_resync) { 08440 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff); 08441 } else 08442 #endif /* IAXTESTS */ 08443 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff); 08444 } else { 08445 /* A mini frame */ 08446 f.frametype = AST_FRAME_VOICE; 08447 if (iaxs[fr->callno]->voiceformat > 0) 08448 f.subclass = iaxs[fr->callno]->voiceformat; 08449 else { 08450 if (option_debug) 08451 ast_log(LOG_DEBUG, "Received mini frame before first full voice frame\n"); 08452 iax2_vnak(fr->callno); 08453 ast_mutex_unlock(&iaxsl[fr->callno]); 08454 return 1; 08455 } 08456 f.datalen = res - sizeof(struct ast_iax2_mini_hdr); 08457 if (f.datalen < 0) { 08458 ast_log(LOG_WARNING, "Datalen < 0?\n"); 08459 ast_mutex_unlock(&iaxsl[fr->callno]); 08460 return 1; 08461 } 08462 if (f.datalen) 08463 f.data = thread->buf + sizeof(*mh); 08464 else 08465 f.data = NULL; 08466 #ifdef IAXTESTS 08467 if (test_resync) { 08468 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff); 08469 } else 08470 #endif /* IAXTESTS */ 08471 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts); 08472 /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */ 08473 } 08474 /* Don't pass any packets until we're started */ 08475 if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08476 ast_mutex_unlock(&iaxsl[fr->callno]); 08477 return 1; 08478 } 08479 /* Common things */ 08480 f.src = "IAX2"; 08481 f.mallocd = 0; 08482 f.offset = 0; 08483 f.len = 0; 08484 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { 08485 f.samples = ast_codec_get_samples(&f); 08486 /* We need to byteswap incoming slinear samples from network byte order */ 08487 if (f.subclass == AST_FORMAT_SLINEAR) 08488 ast_frame_byteswap_be(&f); 08489 } else 08490 f.samples = 0; 08491 iax_frame_wrap(fr, &f); 08492 08493 /* If this is our most recent packet, use it as our basis for timestamping */ 08494 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 08495 /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/ 08496 fr->outoforder = 0; 08497 } else { 08498 if (option_debug && iaxdebug && iaxs[fr->callno]) 08499 ast_log(LOG_DEBUG, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr->ts, iaxs[fr->callno]->last); 08500 fr->outoforder = -1; 08501 } 08502 fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO)); 08503 duped_fr = iaxfrdup2(fr); 08504 if (duped_fr) { 08505 schedule_delivery(duped_fr, updatehistory, 0, &fr->ts); 08506 } 08507 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 08508 iaxs[fr->callno]->last = fr->ts; 08509 #if 1 08510 if (option_debug && iaxdebug) 08511 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 08512 #endif 08513 } 08514 08515 /* Always run again */ 08516 ast_mutex_unlock(&iaxsl[fr->callno]); 08517 return 1; 08518 }
static int socket_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 6874 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_registry::callno, ast_iax2_full_hdr::csub, defer_full_frame(), errno, iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), len, LOG_DEBUG, LOG_WARNING, option_debug, ast_iax2_full_hdr::scallno, signal_condition(), t, thread, and ast_iax2_full_hdr::type.
Referenced by network_thread(), peer_set_srcaddr(), and set_config().
06875 { 06876 struct iax2_thread *thread; 06877 socklen_t len; 06878 time_t t; 06879 static time_t last_errtime = 0; 06880 struct ast_iax2_full_hdr *fh; 06881 06882 if (!(thread = find_idle_thread())) { 06883 time(&t); 06884 if (t != last_errtime && option_debug) 06885 ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n"); 06886 last_errtime = t; 06887 usleep(1); 06888 return 1; 06889 } 06890 06891 len = sizeof(thread->iosin); 06892 thread->iofd = fd; 06893 thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len); 06894 thread->buf_size = sizeof(thread->readbuf); 06895 thread->buf = thread->readbuf; 06896 if (thread->buf_len < 0) { 06897 if (errno != ECONNREFUSED && errno != EAGAIN) 06898 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 06899 handle_error(); 06900 thread->iostate = IAX_IOSTATE_IDLE; 06901 signal_condition(&thread->lock, &thread->cond); 06902 return 1; 06903 } 06904 if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */ 06905 thread->iostate = IAX_IOSTATE_IDLE; 06906 signal_condition(&thread->lock, &thread->cond); 06907 return 1; 06908 } 06909 06910 /* Determine if this frame is a full frame; if so, and any thread is currently 06911 processing a full frame for the same callno from this peer, then drop this 06912 frame (and the peer will retransmit it) */ 06913 fh = (struct ast_iax2_full_hdr *) thread->buf; 06914 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 06915 struct iax2_thread *cur = NULL; 06916 uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL; 06917 06918 AST_LIST_LOCK(&active_list); 06919 AST_LIST_TRAVERSE(&active_list, cur, list) { 06920 if ((cur->ffinfo.callno == callno) && 06921 !inaddrcmp(&cur->ffinfo.sin, &thread->iosin)) 06922 break; 06923 } 06924 if (cur) { 06925 /* we found another thread processing a full frame for this call, 06926 so queue it up for processing later. */ 06927 defer_full_frame(thread, cur); 06928 AST_LIST_UNLOCK(&active_list); 06929 thread->iostate = IAX_IOSTATE_IDLE; 06930 signal_condition(&thread->lock, &thread->cond); 06931 return 1; 06932 } else { 06933 /* this thread is going to process this frame, so mark it */ 06934 thread->ffinfo.callno = callno; 06935 memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin)); 06936 thread->ffinfo.type = fh->type; 06937 thread->ffinfo.csub = fh->csub; 06938 } 06939 AST_LIST_UNLOCK(&active_list); 06940 } 06941 06942 /* Mark as ready and send on its way */ 06943 thread->iostate = IAX_IOSTATE_READY; 06944 #ifdef DEBUG_SCHED_MULTITHREAD 06945 ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc)); 06946 #endif 06947 signal_condition(&thread->lock, &thread->cond); 06948 06949 return 1; 06950 }
static void spawn_dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid | |||
) | [static] |
Definition at line 6661 of file chan_iax2.c.
References ast_calloc, ast_log(), ast_pthread_create, ast_strdup, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup_thread(), and LOG_WARNING.
Referenced by socket_process().
06662 { 06663 pthread_t newthread; 06664 struct dpreq_data *dpr; 06665 pthread_attr_t attr; 06666 06667 if (!(dpr = ast_calloc(1, sizeof(*dpr)))) 06668 return; 06669 06670 pthread_attr_init(&attr); 06671 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06672 06673 dpr->callno = callno; 06674 ast_copy_string(dpr->context, context, sizeof(dpr->context)); 06675 ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum)); 06676 if (callerid) 06677 dpr->callerid = ast_strdup(callerid); 06678 if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) { 06679 ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); 06680 } 06681 06682 pthread_attr_destroy(&attr); 06683 }
static int start_network_thread | ( | void | ) | [static] |
Definition at line 9120 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create, ast_pthread_create_background, ast_verbose(), free, iax2_process_thread(), IAX_TYPE_POOL, iaxthreadcount, LOG_WARNING, network_thread(), option_verbose, sched_thread(), thread, and VERBOSE_PREFIX_2.
Referenced by load_module().
09121 { 09122 pthread_attr_t attr; 09123 int threadcount = 0; 09124 int x; 09125 for (x = 0; x < iaxthreadcount; x++) { 09126 struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread)); 09127 if (thread) { 09128 thread->type = IAX_TYPE_POOL; 09129 thread->threadnum = ++threadcount; 09130 ast_mutex_init(&thread->lock); 09131 ast_cond_init(&thread->cond, NULL); 09132 pthread_attr_init(&attr); 09133 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 09134 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 09135 ast_log(LOG_WARNING, "Failed to create new thread!\n"); 09136 free(thread); 09137 thread = NULL; 09138 } 09139 AST_LIST_LOCK(&idle_list); 09140 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 09141 AST_LIST_UNLOCK(&idle_list); 09142 } 09143 } 09144 ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL); 09145 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 09146 if (option_verbose > 1) 09147 ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount); 09148 return 0; 09149 }
static void stop_stuff | ( | int | callno | ) | [static] |
Definition at line 6343 of file chan_iax2.c.
References iax2_destroy_helper(), and iaxs.
Referenced by socket_process().
06344 { 06345 iax2_destroy_helper(iaxs[callno]); 06346 }
static void store_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1239 of file chan_iax2.c.
References ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by __find_callno(), complete_transfer(), and socket_process().
01240 { 01241 if (!pvt->peercallno) { 01242 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01243 return; 01244 } 01245 01246 ao2_link(iax_peercallno_pvts, pvt); 01247 }
static int timing_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 6530 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_inet_ntoa(), AST_IO_PRI, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, iax2_trunk_expired(), iax2_trunk_peer::lock, LOG_DEBUG, LOG_WARNING, MAX_TRUNKDATA, iax2_trunk_peer::next, option_debug, send_trunk(), tpeers, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.
Referenced by network_thread().
06531 { 06532 char buf[1024]; 06533 int res; 06534 struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL; 06535 int processed = 0; 06536 int totalcalls = 0; 06537 #ifdef ZT_TIMERACK 06538 int x = 1; 06539 #endif 06540 struct timeval now; 06541 if (iaxtrunkdebug) 06542 ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA); 06543 gettimeofday(&now, NULL); 06544 if (events & AST_IO_PRI) { 06545 #ifdef ZT_TIMERACK 06546 /* Great, this is a timing interface, just call the ioctl */ 06547 if (ioctl(fd, ZT_TIMERACK, &x)) { 06548 ast_log(LOG_WARNING, "Unable to acknowledge zap timer. IAX trunking will fail!\n"); 06549 usleep(1); 06550 return -1; 06551 } 06552 #endif 06553 } else { 06554 /* Read and ignore from the pseudo channel for timing */ 06555 res = read(fd, buf, sizeof(buf)); 06556 if (res < 1) { 06557 ast_log(LOG_WARNING, "Unable to read from timing fd\n"); 06558 return 1; 06559 } 06560 } 06561 /* For each peer that supports trunking... */ 06562 ast_mutex_lock(&tpeerlock); 06563 tpeer = tpeers; 06564 while(tpeer) { 06565 processed++; 06566 res = 0; 06567 ast_mutex_lock(&tpeer->lock); 06568 /* We can drop a single tpeer per pass. That makes all this logic 06569 substantially easier */ 06570 if (!drop && iax2_trunk_expired(tpeer, &now)) { 06571 /* Take it out of the list, but don't free it yet, because it 06572 could be in use */ 06573 if (prev) 06574 prev->next = tpeer->next; 06575 else 06576 tpeers = tpeer->next; 06577 drop = tpeer; 06578 } else { 06579 res = send_trunk(tpeer, &now); 06580 if (iaxtrunkdebug) 06581 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); 06582 } 06583 totalcalls += res; 06584 res = 0; 06585 ast_mutex_unlock(&tpeer->lock); 06586 prev = tpeer; 06587 tpeer = tpeer->next; 06588 } 06589 ast_mutex_unlock(&tpeerlock); 06590 if (drop) { 06591 ast_mutex_lock(&drop->lock); 06592 /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 06593 because by the time they could get tpeerlock, we've already grabbed it */ 06594 if (option_debug) 06595 ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); 06596 if (drop->trunkdata) { 06597 free(drop->trunkdata); 06598 drop->trunkdata = NULL; 06599 } 06600 ast_mutex_unlock(&drop->lock); 06601 ast_mutex_destroy(&drop->lock); 06602 free(drop); 06603 06604 } 06605 if (iaxtrunkdebug) 06606 ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls); 06607 iaxtrunkdebug =0; 06608 return 1; 06609 }
static int transmit_trunk | ( | struct iax_frame * | f, | |
struct sockaddr_in * | sin, | |||
int | sockfd | |||
) | [static] |
Definition at line 2065 of file chan_iax2.c.
References ast_log(), iax_frame::data, iax_frame::datalen, errno, handle_error(), LOG_DEBUG, and option_debug.
Referenced by send_trunk().
02066 { 02067 int res; 02068 res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin, 02069 sizeof(*sin)); 02070 if (res < 0) { 02071 if (option_debug) 02072 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 02073 handle_error(); 02074 } else 02075 res = 0; 02076 return res; 02077 }
static int try_firmware | ( | char * | s | ) | [static] |
Definition at line 1753 of file chan_iax2.c.
References ast_calloc, ast_log(), ast_random(), ast_strlen_zero(), MD5Context::buf, ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, errno, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, len, LOG_WARNING, ast_iax2_firmware_header::magic, MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
Referenced by reload_firmware().
01754 { 01755 struct stat stbuf; 01756 struct iax_firmware *cur; 01757 int ifd; 01758 int fd; 01759 int res; 01760 01761 struct ast_iax2_firmware_header *fwh, fwh2; 01762 struct MD5Context md5; 01763 unsigned char sum[16]; 01764 unsigned char buf[1024]; 01765 int len, chunk; 01766 char *s2; 01767 char *last; 01768 s2 = alloca(strlen(s) + 100); 01769 if (!s2) { 01770 ast_log(LOG_WARNING, "Alloca failed!\n"); 01771 return -1; 01772 } 01773 last = strrchr(s, '/'); 01774 if (last) 01775 last++; 01776 else 01777 last = s; 01778 snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random()); 01779 res = stat(s, &stbuf); 01780 if (res < 0) { 01781 ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno)); 01782 return -1; 01783 } 01784 /* Make sure it's not a directory */ 01785 if (S_ISDIR(stbuf.st_mode)) 01786 return -1; 01787 ifd = open(s, O_RDONLY); 01788 if (ifd < 0) { 01789 ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); 01790 return -1; 01791 } 01792 fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600); 01793 if (fd < 0) { 01794 ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); 01795 close(ifd); 01796 return -1; 01797 } 01798 /* Unlink our newly created file */ 01799 unlink(s2); 01800 01801 /* Now copy the firmware into it */ 01802 len = stbuf.st_size; 01803 while(len) { 01804 chunk = len; 01805 if (chunk > sizeof(buf)) 01806 chunk = sizeof(buf); 01807 res = read(ifd, buf, chunk); 01808 if (res != chunk) { 01809 ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01810 close(ifd); 01811 close(fd); 01812 return -1; 01813 } 01814 res = write(fd, buf, chunk); 01815 if (res != chunk) { 01816 ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01817 close(ifd); 01818 close(fd); 01819 return -1; 01820 } 01821 len -= chunk; 01822 } 01823 close(ifd); 01824 /* Return to the beginning */ 01825 lseek(fd, 0, SEEK_SET); 01826 if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) { 01827 ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s); 01828 close(fd); 01829 return -1; 01830 } 01831 if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) { 01832 ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s); 01833 close(fd); 01834 return -1; 01835 } 01836 if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) { 01837 ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s); 01838 close(fd); 01839 return -1; 01840 } 01841 if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) { 01842 ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s); 01843 close(fd); 01844 return -1; 01845 } 01846 fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 01847 if (fwh == (void *) -1) { 01848 ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno)); 01849 close(fd); 01850 return -1; 01851 } 01852 MD5Init(&md5); 01853 MD5Update(&md5, fwh->data, ntohl(fwh->datalen)); 01854 MD5Final(sum, &md5); 01855 if (memcmp(sum, fwh->chksum, sizeof(sum))) { 01856 ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s); 01857 munmap((void*)fwh, stbuf.st_size); 01858 close(fd); 01859 return -1; 01860 } 01861 cur = waresl.wares; 01862 while(cur) { 01863 if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) { 01864 /* Found a candidate */ 01865 if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version))) 01866 /* The version we have on loaded is older, load this one instead */ 01867 break; 01868 /* This version is no newer than what we have. Don't worry about it. 01869 We'll consider it a proper load anyhow though */ 01870 munmap((void*)fwh, stbuf.st_size); 01871 close(fd); 01872 return 0; 01873 } 01874 cur = cur->next; 01875 } 01876 if (!cur) { 01877 /* Allocate a new one and link it */ 01878 if ((cur = ast_calloc(1, sizeof(*cur)))) { 01879 cur->fd = -1; 01880 cur->next = waresl.wares; 01881 waresl.wares = cur; 01882 } 01883 } 01884 if (cur) { 01885 if (cur->fwh) { 01886 munmap((void*)cur->fwh, cur->mmaplen); 01887 } 01888 if (cur->fd > -1) 01889 close(cur->fd); 01890 cur->fwh = fwh; 01891 cur->fd = fd; 01892 cur->mmaplen = stbuf.st_size; 01893 cur->dead = 0; 01894 } 01895 return 0; 01896 }
static int try_transfer | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5745 of file chan_iax2.c.
References iax_ies::apparent_addr, AST_FRAME_IAX, ast_log(), iax_ie_data::buf, iax_ies::callno, IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, LOG_WARNING, iax_ie_data::pos, send_command_transfer(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, iax_ies::transferid, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.
Referenced by socket_process().
05746 { 05747 int newcall = 0; 05748 char newip[256]; 05749 struct iax_ie_data ied; 05750 struct sockaddr_in new; 05751 05752 05753 memset(&ied, 0, sizeof(ied)); 05754 if (ies->apparent_addr) 05755 bcopy(ies->apparent_addr, &new, sizeof(new)); 05756 if (ies->callno) 05757 newcall = ies->callno; 05758 if (!newcall || !new.sin_addr.s_addr || !new.sin_port) { 05759 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05760 return -1; 05761 } 05762 pvt->transfercallno = newcall; 05763 memcpy(&pvt->transfer, &new, sizeof(pvt->transfer)); 05764 inet_aton(newip, &pvt->transfer.sin_addr); 05765 pvt->transfer.sin_family = AF_INET; 05766 pvt->transferring = TRANSFER_BEGIN; 05767 pvt->transferid = ies->transferid; 05768 if (ies->transferid) 05769 iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid); 05770 send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); 05771 return 0; 05772 }
static int uncompress_subclass | ( | unsigned char | csub | ) | [static] |
Definition at line 1084 of file chan_iax2.c.
References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.
Referenced by decode_frame(), and socket_process().
01085 { 01086 /* If the SC_LOG flag is set, return 2^csub otherwise csub */ 01087 if (csub & IAX_FLAG_SC_LOG) { 01088 /* special case for 'compressed' -1 */ 01089 if (csub == 0xff) 01090 return -1; 01091 else 01092 return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); 01093 } 01094 else 01095 return csub; 01096 }
static void unlink_peer | ( | struct iax2_peer * | peer | ) | [static] |
Definition at line 6017 of file chan_iax2.c.
References ao2_unlink(), ast_sched_del(), iax2_peer::expire, peer_unref(), peers, and iax2_peer::pokeexpire.
Referenced by __expire_registry(), build_peer(), and prune_peers().
06018 { 06019 if (peer->expire > -1) { 06020 if (!ast_sched_del(sched, peer->expire)) { 06021 peer->expire = -1; 06022 peer_unref(peer); 06023 } 06024 } 06025 06026 if (peer->pokeexpire > -1) { 06027 if (!ast_sched_del(sched, peer->pokeexpire)) { 06028 peer->pokeexpire = -1; 06029 peer_unref(peer); 06030 } 06031 } 06032 06033 ao2_unlink(peers, peer); 06034 }
static int unload_module | ( | void | ) | [static] |
Definition at line 11045 of file chan_iax2.c.
References __unload_module(), ast_custom_function_unregister(), and iaxpeer_function.
11046 { 11047 ast_custom_function_unregister(&iaxpeer_function); 11048 return __unload_module(); 11049 }
static void unlock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3473 of file chan_iax2.c.
References ast_mutex_unlock(), and iaxsl.
Referenced by iax2_bridge().
03474 { 03475 ast_mutex_unlock(&iaxsl[callno1]); 03476 ast_mutex_unlock(&iaxsl[callno0]); 03477 }
static void unwrap_timestamp | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2499 of file chan_iax2.c.
References ast_log(), iax_frame::callno, iaxs, chan_iax2_pvt::last, LOG_DEBUG, option_debug, and iax_frame::ts.
Referenced by schedule_delivery().
02500 { 02501 int x; 02502 02503 if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) { 02504 x = fr->ts - iaxs[fr->callno]->last; 02505 if (x < -50000) { 02506 /* Sudden big jump backwards in timestamp: 02507 What likely happened here is that miniframe timestamp has circled but we haven't 02508 gotten the update from the main packet. We'll just pretend that we did, and 02509 update the timestamp appropriately. */ 02510 fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF); 02511 if (option_debug && iaxdebug) 02512 ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n"); 02513 } 02514 if (x > 50000) { 02515 /* Sudden apparent big jump forwards in timestamp: 02516 What's likely happened is this is an old miniframe belonging to the previous 02517 top-16-bit timestamp that has turned up out of order. 02518 Adjust the timestamp appropriately. */ 02519 fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF); 02520 if (option_debug && iaxdebug) 02521 ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n"); 02522 } 02523 } 02524 }
static void update_jbsched | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 2528 of file chan_iax2.c.
References AST_SCHED_DEL, chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), iax2_sched_add(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, and chan_iax2_pvt::rxcore.
Referenced by __get_from_jb(), and schedule_delivery().
02529 { 02530 int when; 02531 02532 when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore); 02533 02534 when = jb_next(pvt->jb) - when; 02535 02536 AST_SCHED_DEL(sched, pvt->jbid); 02537 02538 if(when <= 0) { 02539 /* XXX should really just empty until when > 0.. */ 02540 when = 1; 02541 } 02542 02543 pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno)); 02544 }
static void update_max_nontrunk | ( | void | ) | [static] |
Definition at line 1452 of file chan_iax2.c.
References ast_log(), iaxs, LOG_DEBUG, maxnontrunkcall, option_debug, and TRUNK_CALL_START.
Referenced by __find_callno(), and make_trunk().
01453 { 01454 int max = 1; 01455 int x; 01456 /* XXX Prolly don't need locks here XXX */ 01457 for (x=1;x<TRUNK_CALL_START - 1; x++) { 01458 if (iaxs[x]) 01459 max = x + 1; 01460 } 01461 maxnontrunkcall = max; 01462 if (option_debug && iaxdebug) 01463 ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max); 01464 }
static void update_max_trunk | ( | void | ) | [static] |
Definition at line 1259 of file chan_iax2.c.
References ARRAY_LEN, ast_log(), iaxs, LOG_DEBUG, maxtrunkcall, option_debug, and TRUNK_CALL_START.
Referenced by iax2_destroy(), and make_trunk().
01260 { 01261 int max = TRUNK_CALL_START; 01262 int x; 01263 01264 /* XXX Prolly don't need locks here XXX */ 01265 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01266 if (iaxs[x]) { 01267 max = x + 1; 01268 } 01269 } 01270 01271 maxtrunkcall = max; 01272 if (option_debug && iaxdebug) 01273 ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max); 01274 }
static int update_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2136 of file chan_iax2.c.
References iax_frame::callno, iax_frame::data, iax_frame::dcallno, ast_iax2_full_hdr::dcallno, IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, and iax_frame::iseqno.
Referenced by __attempt_transmit().
02137 { 02138 /* Called with iaxsl lock held, and iaxs[callno] non-NULL */ 02139 struct ast_iax2_full_hdr *fh = f->data; 02140 /* Mark this as a retransmission */ 02141 fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno); 02142 /* Update iseqno */ 02143 f->iseqno = iaxs[f->callno]->iseqno; 02144 fh->iseqno = f->iseqno; 02145 return 0; 02146 }
static int update_registry | ( | struct sockaddr_in * | sin, | |
int | callno, | |||
char * | devtype, | |||
int | fd, | |||
unsigned short | refresh | |||
) | [static] |
Definition at line 6128 of file chan_iax2.c.
References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), ast_device_state_changed(), AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verbose(), iax_ie_data::buf, EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, iaxs, iaxsl, inaddrcmp(), LOG_NOTICE, LOG_WARNING, manager_event(), option_verbose, peer_ref(), peer_unref(), iax_ie_data::pos, realtime_update_peer(), register_peer_exten(), send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.
Referenced by socket_process().
06129 { 06130 /* Called from IAX thread only, with proper iaxsl lock */ 06131 struct iax_ie_data ied; 06132 struct iax2_peer *p; 06133 int msgcount; 06134 char data[80]; 06135 int version; 06136 const char *peer_name; 06137 int res = -1; 06138 06139 memset(&ied, 0, sizeof(ied)); 06140 06141 peer_name = ast_strdupa(iaxs[callno]->peer); 06142 06143 /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ 06144 ast_mutex_unlock(&iaxsl[callno]); 06145 if (!(p = find_peer(peer_name, 1))) { 06146 ast_mutex_lock(&iaxsl[callno]); 06147 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 06148 return -1; 06149 } 06150 ast_mutex_lock(&iaxsl[callno]); 06151 if (!iaxs[callno]) 06152 goto return_unref; 06153 06154 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { 06155 if (sin->sin_addr.s_addr) { 06156 time_t nowtime; 06157 time(&nowtime); 06158 realtime_update_peer(peer_name, sin, nowtime); 06159 } else { 06160 realtime_update_peer(peer_name, sin, 0); 06161 } 06162 } 06163 if (inaddrcmp(&p->addr, sin)) { 06164 if (iax2_regfunk) 06165 iax2_regfunk(p->name, 1); 06166 /* Stash the IP address from which they registered */ 06167 memcpy(&p->addr, sin, sizeof(p->addr)); 06168 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry); 06169 if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) { 06170 ast_db_put("IAX/Registry", p->name, data); 06171 if (option_verbose > 2) 06172 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 06173 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 06174 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name); 06175 register_peer_exten(p, 1); 06176 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06177 } else if (!ast_test_flag(p, IAX_TEMPONLY)) { 06178 if (option_verbose > 2) 06179 ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 06180 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED"); 06181 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name); 06182 register_peer_exten(p, 0); 06183 ast_db_del("IAX/Registry", p->name); 06184 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06185 } 06186 /* Update the host */ 06187 /* Verify that the host is really there */ 06188 iax2_poke_peer(p, callno); 06189 } 06190 06191 /* Make sure our call still exists, an INVAL at the right point may make it go away */ 06192 if (!iaxs[callno]) { 06193 res = 0; 06194 goto return_unref; 06195 } 06196 06197 /* Store socket fd */ 06198 p->sockfd = fd; 06199 /* Setup the expiry */ 06200 if (p->expire > -1) { 06201 if (!ast_sched_del(sched, p->expire)) { 06202 p->expire = -1; 06203 peer_unref(p); 06204 } 06205 } 06206 /* treat an unspecified refresh interval as the minimum */ 06207 if (!refresh) 06208 refresh = min_reg_expire; 06209 if (refresh > max_reg_expire) { 06210 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 06211 p->name, max_reg_expire, refresh); 06212 p->expiry = max_reg_expire; 06213 } else if (refresh < min_reg_expire) { 06214 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 06215 p->name, min_reg_expire, refresh); 06216 p->expiry = min_reg_expire; 06217 } else { 06218 p->expiry = refresh; 06219 } 06220 if (p->expiry && sin->sin_addr.s_addr) { 06221 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 06222 if (p->expire == -1) 06223 peer_unref(p); 06224 } 06225 iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); 06226 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); 06227 if (sin->sin_addr.s_addr) { 06228 iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); 06229 iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); 06230 if (!ast_strlen_zero(p->mailbox)) { 06231 int new, old; 06232 ast_app_inboxcount(p->mailbox, &new, &old); 06233 if (new > 255) 06234 new = 255; 06235 if (old > 255) 06236 old = 255; 06237 msgcount = (old << 8) | new; 06238 iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount); 06239 } 06240 if (ast_test_flag(p, IAX_HASCALLERID)) { 06241 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num); 06242 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name); 06243 } 06244 } 06245 version = iax_check_version(devtype); 06246 if (version) 06247 iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version); 06248 06249 res = 0; 06250 06251 return_unref: 06252 peer_unref(p); 06253 06254 return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1); 06255 }
static int user_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1131 of file chan_iax2.c.
Referenced by load_module().
01132 { 01133 struct iax2_user *user = obj, *user2 = arg; 01134 01135 return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0; 01136 }
static int user_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 9760 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
09761 { 09762 struct iax2_user *user = obj; 09763 09764 ast_set_flag(user, IAX_DELME); 09765 09766 return 0; 09767 }
static void user_destructor | ( | void * | obj | ) | [static] |
Definition at line 9524 of file chan_iax2.c.
References ast_free_ha(), ast_string_field_free_memory, ast_variables_destroy(), iax2_user::contexts, free_context(), iax2_user::ha, and iax2_user::vars.
Referenced by build_user().
09525 { 09526 struct iax2_user *user = obj; 09527 09528 ast_free_ha(user->ha); 09529 free_context(user->contexts); 09530 if(user->vars) { 09531 ast_variables_destroy(user->vars); 09532 user->vars = NULL; 09533 } 09534 ast_string_field_free_memory(user); 09535 }
static int user_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1121 of file chan_iax2.c.
References ast_str_hash().
Referenced by load_module().
01122 { 01123 const struct iax2_user *user = obj; 01124 01125 return ast_str_hash(user->name); 01126 }
Definition at line 1170 of file chan_iax2.c.
References ao2_ref().
01171 { 01172 ao2_ref(user, +1); 01173 return user; 01174 }
Definition at line 1176 of file chan_iax2.c.
References ao2_ref().
Referenced by authenticate_request(), authenticate_verify(), build_user(), check_access(), iax2_destroy_helper(), iax2_show_users(), prune_users(), and set_config().
01177 { 01178 ao2_ref(user, -1); 01179 return NULL; 01180 }
static void vnak_retransmit | ( | int | callno, | |
int | last | |||
) | [static] |
Definition at line 6444 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::callno, f, iaxq, iaxs, iax_frame::oseqno, iax_frame::retries, and send_packet().
Referenced by socket_process().
06445 { 06446 struct iax_frame *f; 06447 06448 AST_LIST_LOCK(&iaxq.queue); 06449 AST_LIST_TRAVERSE(&iaxq.queue, f, list) { 06450 /* Send a copy immediately */ 06451 if ((f->callno == callno) && iaxs[f->callno] && 06452 ((unsigned char ) (f->oseqno - last) < 128) && 06453 (f->retries >= 0)) { 06454 send_packet(f); 06455 } 06456 } 06457 AST_LIST_UNLOCK(&iaxq.queue); 06458 }
char accountcode[AST_MAX_ACCOUNT_CODE] [static] |
Definition at line 218 of file chan_iax2.c.
Referenced by __oh323_new(), ast_cdr_setaccount(), ast_channel_alloc(), begin_dial(), check_user_full(), disa_exec(), features_call(), gtalk_new(), local_call(), sip_new(), tds_log(), wait_for_answer(), and zt_new().
int adsi = 0 [static] |
Definition at line 222 of file chan_iax2.c.
int amaflags = 0 [static] |
Definition at line 221 of file chan_iax2.c.
int authdebug = 1 [static] |
Definition at line 158 of file chan_iax2.c.
int autokill = 0 [static] |
Definition at line 159 of file chan_iax2.c.
struct ast_cli_entry cli_iax2[] [static] |
struct ast_cli_entry cli_iax2_jb_debug_deprecated [static] |
Initial value:
{ { "iax2", "jb", "debug", NULL }, iax2_do_jb_debug, NULL, NULL }
Definition at line 10841 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_debug_deprecated [static] |
Initial value:
{ { "iax2", "no", "debug", NULL }, iax2_no_debug, NULL, NULL }
Definition at line 10846 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_jb_debug_deprecated [static] |
Initial value:
{ { "iax2", "no", "jb", "debug", NULL }, iax2_no_jb_debug, NULL, NULL }
Definition at line 10856 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_trunk_debug_deprecated [static] |
Initial value:
{ { "iax2", "no", "trunk", "debug", NULL }, iax2_no_trunk_debug, NULL, NULL }
Definition at line 10851 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_trunk_debug_deprecated [static] |
Initial value:
{ { "iax2", "trunk", "debug", NULL }, iax2_do_trunk_debug, NULL, NULL }
Definition at line 10836 of file chan_iax2.c.
char context[80] = "default" [static] |
Definition at line 145 of file chan_iax2.c.
char debug_jb_usage[] [static] |
Initial value:
"Usage: iax2 set debug jb\n" " Enables jitterbuffer debugging information\n"
Definition at line 10810 of file chan_iax2.c.
char debug_trunk_usage[] [static] |
Initial value:
"Usage: iax2 set debug trunk\n" " Requests current status of IAX trunking\n"
Definition at line 10802 of file chan_iax2.c.
char debug_usage[] [static] |
Initial value:
"Usage: iax2 set debug\n" " Enables dumping of IAX packets for debugging purposes\n"
Definition at line 10794 of file chan_iax2.c.
int defaultsockfd = -1 [static] |
Definition at line 175 of file chan_iax2.c.
int delayreject = 0 [static] |
Definition at line 223 of file chan_iax2.c.
struct iax2_dpcache * dpcache [static] |
Referenced by find_cache(), and iax2_show_cache().
int global_rtautoclear = 120 [static] |
Definition at line 277 of file chan_iax2.c.
struct ast_flags globalflags = { 0 } [static] |
Definition at line 226 of file chan_iax2.c.
Referenced by find_or_create(), find_user(), find_user_realtime(), forward_message(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), sendmail(), and vm_execmain().
int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static] |
Definition at line 204 of file chan_iax2.c.
int iax2_encryption = 0 [static] |
Definition at line 224 of file chan_iax2.c.
enum { ... } iax2_flags |
int(* iax2_regfunk)(const char *username, int onoff) = NULL |
Referenced by __expire_registry(), reg_source_db(), and update_registry().
char iax2_reload_usage[] [static] |
Initial value:
"Usage: iax2 reload\n" " Reloads IAX configuration from iax.conf\n"
Definition at line 10752 of file chan_iax2.c.
enum { ... } iax2_state |
struct ast_switch iax2_switch [static] |
struct ast_channel_tech iax2_tech [static] |
Definition at line 866 of file chan_iax2.c.
Referenced by __unload_module(), ast_iax2_new(), function_iaxpeer(), iax2_bridge(), iax2_prov_app(), and load_module().
char iax2_test_losspct_usage[] [static] |
Initial value:
"Usage: iax2 test losspct <percentage>\n" " For testing, throws away <percentage> percent of incoming packets\n"
Definition at line 10818 of file chan_iax2.c.
struct ao2_container* iax_peercallno_pvts [static] |
Another container of iax2_pvt structures.
Active IAX2 pvt structs are also stored in this container, if they are a part of an active call where we know the remote side's call number. The reason for this is that incoming media frames do not contain our call number. So, instead of having to iterate the entire iaxs array, we use this container to look up calls where the remote side is using a given call number.
Definition at line 825 of file chan_iax2.c.
Referenced by __find_callno(), __unload_module(), load_module(), remove_by_peercallno(), and store_by_peercallno().
int iaxactivethreadcount = 0 [static] |
Definition at line 453 of file chan_iax2.c.
Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().
int iaxcompat = 0 [static] |
Definition at line 160 of file chan_iax2.c.
int iaxdebug = 0 [static] |
Definition at line 206 of file chan_iax2.c.
int iaxdefaultdpcache = 10 * 60 [static] |
Definition at line 162 of file chan_iax2.c.
int iaxdefaulttimeout = 5 [static] |
Definition at line 164 of file chan_iax2.c.
int iaxdynamicthreadcount = 0 [static] |
Definition at line 452 of file chan_iax2.c.
Referenced by find_idle_thread(), and iax2_process_thread().
int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static] |
struct ast_iax2_queue iaxq [static] |
struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static] |
Definition at line 812 of file chan_iax2.c.
Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __do_deliver(), __find_callno(), __get_from_jb(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_fail(), auth_reject(), authenticate_reply(), authenticate_request(), auto_hangup(), cache_get_callno_locked(), calc_timestamp(), check_access(), complete_transfer(), decrypt_frame(), delete_users(), dp_lookup(), find_cache(), fix_peerts(), function_iaxpeer(), iax2_ack_registry(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_dprequest(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_predestroy(), iax2_prov_app(), iax2_provision(), iax2_queue_control_data(), iax2_queue_frame(), iax2_queue_hangup(), iax2_request(), iax2_show_channels(), iax2_start_transfer(), iax2_vnak(), iax2_write(), iax_showframe(), load_module(), make_trunk(), network_thread(), register_verify(), registry_authrequest(), registry_rerequest(), save_rr(), schedule_delivery(), send_command_final(), send_command_locked(), send_packet(), socket_process(), stop_stuff(), unwrap_timestamp(), update_max_nontrunk(), update_max_trunk(), update_packet(), update_registry(), and vnak_retransmit().
ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static] |
Definition at line 813 of file chan_iax2.c.
Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __find_callno(), __get_from_jb(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_reject(), authenticate_reply(), auto_hangup(), cache_get_callno_locked(), delete_users(), dp_lookup(), find_cache(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_provision(), iax2_queue_control_data(), iax2_queue_frame(), iax2_queue_hangup(), iax2_request(), iax2_show_channels(), iax2_write(), load_module(), lock_both(), make_trunk(), network_thread(), peer_destructor(), register_verify(), registry_authrequest(), send_command_locked(), socket_process(), unlock_both(), and update_registry().
int iaxthreadcount = DEFAULT_THREAD_COUNT [static] |
Definition at line 450 of file chan_iax2.c.
Referenced by iax2_show_threads(), set_config(), and start_network_thread().
int iaxtrunkdebug = 0 [static] |
Definition at line 208 of file chan_iax2.c.
struct io_context* io [static] |
Definition at line 201 of file chan_iax2.c.
int lagrq_time = 10 [static] |
Definition at line 153 of file chan_iax2.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 147 of file chan_iax2.c.
Definition at line 814 of file chan_iax2.c.
Referenced by __find_callno(), iax2_destroy(), and make_trunk().
int max_reg_expire [static] |
Definition at line 169 of file chan_iax2.c.
int max_retries = 4 [static] |
Definition at line 151 of file chan_iax2.c.
int maxauthreq = 3 [static] |
Definition at line 150 of file chan_iax2.c.
int maxjitterbuffer = 1000 [static] |
Definition at line 154 of file chan_iax2.c.
int maxjitterinterps = 10 [static] |
Definition at line 156 of file chan_iax2.c.
int maxnontrunkcall = 1 [static] |
Definition at line 832 of file chan_iax2.c.
Referenced by __find_callno(), and update_max_nontrunk().
int maxtrunkcall = TRUNK_CALL_START [static] |
int min_reg_expire [static] |
Definition at line 168 of file chan_iax2.c.
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 219 of file chan_iax2.c.
char mohsuggest[MAX_MUSICCLASS] [static] |
Definition at line 220 of file chan_iax2.c.
Referenced by check_user_full(), create_addr_from_peer(), and sip_alloc().
struct ast_netsock_list* netsock [static] |
Definition at line 173 of file chan_iax2.c.
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 228 of file chan_iax2.c.
char no_debug_jb_usage[] [static] |
Initial value:
"Usage: iax2 set debug jb off\n" " Disables jitterbuffer debugging information\n"
Definition at line 10814 of file chan_iax2.c.
char no_debug_trunk_usage[] [static] |
Initial value:
"Usage: iax2 set debug trunk off\n" " Requests current status of IAX trunking\n"
Definition at line 10806 of file chan_iax2.c.
char no_debug_usage[] [static] |
Initial value:
"Usage: iax2 set debug off\n" " Disables dumping of IAX packets for debugging purposes\n"
Definition at line 10798 of file chan_iax2.c.
struct ast_netsock_list* outsock [static] |
used if sourceaddress specified and bindaddr == INADDR_ANY
Definition at line 174 of file chan_iax2.c.
char* papp = "IAX2Provision" [static] |
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 8769 of file chan_iax2.c.
Referenced by load_module().
struct ao2_container* peers [static] |
Definition at line 650 of file chan_iax2.c.
Referenced by __iax2_show_peers(), __unload_module(), abort_request(), authenticate_reply(), build_peer(), build_transactions(), cancel_request(), chanavail_exec(), check_request(), complete_iax2_show_peer(), complete_peer_helper(), delete_users(), destroy_trans(), discover_transactions(), dundi_flush(), dundi_ie_append_eid_appropriately(), dundi_lookup_thread(), dundi_precache_internal(), dundi_precache_thread(), dundi_query_thread(), dundi_rexmit(), dundi_show_entityid(), dundi_show_mappings(), dundi_show_peer(), dundi_show_peers(), dundi_show_requests(), dundi_show_trans(), find_peer(), handle_command_response(), iax2_getpeername(), iax2_getpeertrunk(), load_module(), mark_mappings(), mark_peers(), network_thread(), optimize_transactions(), poke_all_peers(), precache_transactions(), prune_mappings(), prune_peers(), query_transactions(), realtime_peer(), register_request(), set_config(), socket_read(), unlink_peer(), and unregister_request().
int ping_time = 21 [static] |
Definition at line 152 of file chan_iax2.c.
struct ast_codec_pref prefs [static] |
Definition at line 141 of file chan_iax2.c.
Referenced by ast_best_codec(), build_peer(), build_user(), check_access(), create_addr(), new_iax(), and set_config().
char prune_realtime_usage[] [static] |
Initial value:
"Usage: iax2 prune realtime [<peername>|all]\n" " Prunes object(s) from the cache\n"
Definition at line 10748 of file chan_iax2.c.
char* psyn = "Provision a calling IAXy with a given template" [static] |
char regcontext[AST_MAX_CONTEXT] = "" [static] |
Definition at line 148 of file chan_iax2.c.
int resyncthreshold = 1000 [static] |
Definition at line 155 of file chan_iax2.c.
struct sched_context* sched [static] |
Definition at line 202 of file chan_iax2.c.
ast_cond_t sched_cond [static] |
Definition at line 231 of file chan_iax2.c.
pthread_t schedthreadid = AST_PTHREADT_NULL [static] |
Definition at line 229 of file chan_iax2.c.
char show_cache_usage[] [static] |
Initial value:
"Usage: iax2 show cache\n" " Display currently cached IAX Dialplan results.\n"
Definition at line 10740 of file chan_iax2.c.
char show_channels_usage[] [static] |
Initial value:
"Usage: iax2 show channels\n" " Lists all currently active IAX channels.\n"
Definition at line 10768 of file chan_iax2.c.
char show_firmware_usage[] [static] |
Initial value:
"Usage: iax2 show firmware\n" " Lists all known IAX firmware images.\n"
Definition at line 10786 of file chan_iax2.c.
char show_netstats_usage[] [static] |
Initial value:
"Usage: iax2 show netstats\n" " Lists network status for all currently active IAX channels.\n"
Definition at line 10772 of file chan_iax2.c.
char show_peer_usage[] [static] |
Initial value:
"Usage: iax2 show peer <name>\n" " Display details on specific IAX peer\n"
Definition at line 10744 of file chan_iax2.c.
char show_peers_usage[] [static] |
Initial value:
"Usage: iax2 show peers [registered] [like <pattern>]\n" " Lists all known IAX2 peers.\n" " Optional 'registered' argument lists only peers with known addresses.\n" " Optional regular expression pattern is used to filter the peer list.\n"
Definition at line 10780 of file chan_iax2.c.
char show_prov_usage[] [static] |
Definition at line 10756 of file chan_iax2.c.
char show_reg_usage[] [static] |
Initial value:
"Usage: iax2 show registry\n" " Lists all registration requests and status.\n"
Definition at line 10790 of file chan_iax2.c.
char show_stats_usage[] [static] |
Initial value:
"Usage: iax2 show stats\n" " Display statistics on IAX channel driver.\n"
Definition at line 10736 of file chan_iax2.c.
char show_threads_usage[] [static] |
Initial value:
"Usage: iax2 show threads\n" " Lists status of IAX helper threads\n"
Definition at line 10776 of file chan_iax2.c.
char show_users_usage[] [static] |
Initial value:
"Usage: iax2 show users [like <pattern>]\n" " Lists all known IAX2 users.\n" " Optional regular expression pattern is used to filter the user list.\n"
Definition at line 10763 of file chan_iax2.c.
const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static] |
Definition at line 143 of file chan_iax2.c.
int test_losspct = 0 [static] |
Definition at line 210 of file chan_iax2.c.
int timingfd = -1 [static] |
Definition at line 171 of file chan_iax2.c.
unsigned int tos = 0 [static] |
Definition at line 166 of file chan_iax2.c.
struct iax2_trunk_peer * tpeers [static] |
Referenced by find_tpeer(), and timing_read().
int trunkfreq = 20 [static] |
Definition at line 157 of file chan_iax2.c.
struct ao2_container* users [static] |
Definition at line 653 of file chan_iax2.c.
Referenced by __unload_module(), ast_get_manager_by_name_locked(), authenticate_request(), authenticate_verify(), build_user(), check_access(), complete_voicemail_show_users(), delete_users(), find_or_create(), find_user(), handle_showmanager(), handle_showmanagers(), handle_voicemail_show_users(), iax2_destroy_helper(), iax2_show_users(), init_manager(), load_config(), load_module(), prune_users(), realtime_user(), reset_user_pw(), and set_config().
struct ast_firmware_list waresl [static] |
Referenced by __unload_module(), iax2_show_firmware(), iax_check_version(), iax_firmware_append(), load_module(), reload_firmware(), and try_firmware().