#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 | iaxdynamicthreadnum = 0 |
static int | iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT |
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 663 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 659 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 673 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 661 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 665 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 667 of file chan_iax2.c.
Referenced by find_cache(), and iax2_show_cache().
#define CACHE_FLAG_TRANSMITTED (1 << 5) |
Request transmitted
Definition at line 669 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 671 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 123 of file chan_iax2.c.
Referenced by ast_iax2_new(), iax2_call(), and update_jbsched().
#define DEBUG_SCHED_MULTITHREAD |
Definition at line 111 of file chan_iax2.c.
#define DEBUG_SUPPORT |
Definition at line 131 of file chan_iax2.c.
#define DEFAULT_DROP 3 |
Definition at line 129 of file chan_iax2.c.
#define DEFAULT_FREQ_NOTOK 10 * 1000 |
Definition at line 196 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 195 of file chan_iax2.c.
Referenced by build_peer(), and handle_response_peerpoke().
#define DEFAULT_MAX_THREAD_COUNT 100 |
Definition at line 126 of file chan_iax2.c.
#define DEFAULT_MAXMS 2000 |
Definition at line 194 of file chan_iax2.c.
#define DEFAULT_RETRY_TIME 1000 |
#define DEFAULT_THREAD_COUNT 10 |
Definition at line 125 of file chan_iax2.c.
#define DEFAULT_TRUNKDATA 640 * 10 |
40ms, uncompressed linear * 10 channels
Definition at line 439 of file chan_iax2.c.
Referenced by iax2_trunk_queue().
#define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" |
#define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
#define FORMAT "%-15.15s %-15d %-15d\n" |
#define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
#define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
#define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" |
#define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
#define FORMAT2 "%-15.15s %-15.15s %-15.15s\n" |
#define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
#define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
#define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
#define GAMMA (0.01) |
Definition at line 136 of file chan_iax2.c.
#define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF |
Definition at line 177 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 185 of file chan_iax2.c.
Referenced by set_config().
#define IAX_CAPABILITY_LOWFREE |
Value:
Definition at line 190 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 179 of file chan_iax2.c.
Referenced by set_config().
#define IAX_IOSTATE_IDLE 0 |
#define IAX_IOSTATE_PROCESSING 2 |
Definition at line 696 of file chan_iax2.c.
#define IAX_IOSTATE_READY 1 |
#define IAX_IOSTATE_SCHEDREADY 3 |
#define IAX_TYPE_DYNAMIC 2 |
Definition at line 700 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 114 of file chan_iax2.c.
#define MAX_JITTER_BUFFER 50 |
Definition at line 436 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 645 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 442 of file chan_iax2.c.
#define MAX_TRUNKDATA 640 * 200 |
40ms, uncompressed linear * 200 channels
Definition at line 440 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 128 of file chan_iax2.c.
#define MIN_JITTER_BUFFER 10 |
Definition at line 437 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 1440 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 122 of file chan_iax2.c.
Referenced by __auto_congest(), __get_from_jb(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), and iax2_write().
#define SCHED_MULTITHREADED |
Definition at line 107 of file chan_iax2.c.
Definition at line 981 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 827 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 445 of file chan_iax2.c.
anonymous enum |
Definition at line 230 of file chan_iax2.c.
00230 { 00231 IAX_STATE_STARTED = (1 << 0), 00232 IAX_STATE_AUTHENTICATED = (1 << 1), 00233 IAX_STATE_TBD = (1 << 2), 00234 IAX_STATE_UNCHANGED = (1 << 3), 00235 } iax2_state;
anonymous enum |
Definition at line 242 of file chan_iax2.c.
00242 { 00243 IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ 00244 IAX_DELME = (1 << 1), /*!< Needs to be deleted */ 00245 IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ 00246 IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ 00247 IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ 00248 IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ 00249 IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ 00250 IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ 00251 /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ 00252 IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ 00253 IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ 00254 IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ 00255 IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ 00256 IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ 00257 IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ 00258 IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ 00259 IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ 00260 IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ 00261 IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ 00262 IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ 00263 IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 00264 IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ 00265 IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ 00266 IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ 00267 IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ 00268 IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a 00269 response, so that we've achieved a three-way handshake with 00270 them before sending voice or anything else*/ 00271 IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */ 00272 } 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 391 of file chan_iax2.c.
00391 { 00392 REG_STATE_UNREGISTERED = 0, 00393 REG_STATE_REGSENT, 00394 REG_STATE_AUTHSENT, 00395 REG_STATE_REGISTERED, 00396 REG_STATE_REJECTED, 00397 REG_STATE_TIMEOUT, 00398 REG_STATE_NOAUTH 00399 };
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 401 of file chan_iax2.c.
00401 { 00402 TRANSFER_NONE = 0, 00403 TRANSFER_BEGIN, 00404 TRANSFER_READY, 00405 TRANSFER_RELEASED, 00406 TRANSFER_PASSTHROUGH, 00407 TRANSFER_MBEGIN, 00408 TRANSFER_MREADY, 00409 TRANSFER_MRELEASED, 00410 TRANSFER_MPASSTHROUGH, 00411 TRANSFER_MEDIA, 00412 TRANSFER_MEDIAPASS 00413 };
static void __attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2189 of file chan_iax2.c.
References AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, chan_iax2_pvt::error, f, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, ast_format::name, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), send_packet(), ast_frame::subclass, update_packet(), and iax2_registry::us.
Referenced by attempt_transmit().
02190 { 02191 /* Attempt to transmit the frame to the remote peer... 02192 Called without iaxsl held. */ 02193 struct iax_frame *f = (struct iax_frame *)data; 02194 int freeme=0; 02195 int callno = f->callno; 02196 /* Make sure this call is still active */ 02197 if (callno) 02198 ast_mutex_lock(&iaxsl[callno]); 02199 if (callno && iaxs[callno]) { 02200 if ((f->retries < 0) /* Already ACK'd */ || 02201 (f->retries >= max_retries) /* Too many attempts */) { 02202 /* Record an error if we've transmitted too many times */ 02203 if (f->retries >= max_retries) { 02204 if (f->transfer) { 02205 /* Transfer timeout */ 02206 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 02207 } else if (f->final) { 02208 if (f->final) 02209 iax2_destroy(callno); 02210 } else { 02211 if (iaxs[callno]->owner) 02212 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); 02213 iaxs[callno]->error = ETIMEDOUT; 02214 if (iaxs[callno]->owner) { 02215 struct ast_frame fr = { 0, }; 02216 /* Hangup the fd */ 02217 fr.frametype = AST_FRAME_CONTROL; 02218 fr.subclass = AST_CONTROL_HANGUP; 02219 iax2_queue_frame(callno, &fr); // XXX 02220 /* Remember, owner could disappear */ 02221 if (iaxs[callno] && iaxs[callno]->owner) 02222 iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 02223 } else { 02224 if (iaxs[callno]->reg) { 02225 memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us)); 02226 iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT; 02227 iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; 02228 } 02229 iax2_destroy(callno); 02230 } 02231 } 02232 02233 } 02234 freeme++; 02235 } else { 02236 /* Update it if it needs it */ 02237 update_packet(f); 02238 /* Attempt transmission */ 02239 send_packet(f); 02240 f->retries++; 02241 /* Try again later after 10 times as long */ 02242 f->retrytime *= 10; 02243 if (f->retrytime > MAX_RETRY_TIME) 02244 f->retrytime = MAX_RETRY_TIME; 02245 /* Transfer messages max out at one second */ 02246 if (f->transfer && (f->retrytime > 1000)) 02247 f->retrytime = 1000; 02248 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 02249 } 02250 } else { 02251 /* Make sure it gets freed */ 02252 f->retries = -1; 02253 freeme++; 02254 } 02255 if (callno) 02256 ast_mutex_unlock(&iaxsl[callno]); 02257 /* Do not try again */ 02258 if (freeme) { 02259 /* Don't attempt delivery, just remove it from the queue */ 02260 AST_LIST_LOCK(&iaxq.queue); 02261 AST_LIST_REMOVE(&iaxq.queue, f, list); 02262 iaxq.count--; 02263 AST_LIST_UNLOCK(&iaxq.queue); 02264 f->retrans = -1; 02265 /* Free the IAX frame */ 02266 iax2_frame_free(f); 02267 } 02268 }
static void __auth_reject | ( | const void * | nothing | ) | [static] |
Definition at line 6396 of file chan_iax2.c.
References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, and send_command_final().
Referenced by auth_reject().
06397 { 06398 /* Called from IAX thread only, without iaxs lock */ 06399 int callno = (int)(long)(nothing); 06400 struct iax_ie_data ied; 06401 ast_mutex_lock(&iaxsl[callno]); 06402 if (iaxs[callno]) { 06403 memset(&ied, 0, sizeof(ied)); 06404 if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { 06405 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); 06406 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); 06407 } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { 06408 iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); 06409 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 06410 } 06411 send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); 06412 } 06413 ast_mutex_unlock(&iaxsl[callno]); 06414 }
static void __auto_congest | ( | const void * | nothing | ) | [static] |
Definition at line 3150 of file chan_iax2.c.
References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, iax2_queue_frame(), iaxs, iaxsl, chan_iax2_pvt::initid, LOG_NOTICE, and PTR_TO_CALLNO.
Referenced by auto_congest().
03151 { 03152 int callno = PTR_TO_CALLNO(nothing); 03153 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; 03154 ast_mutex_lock(&iaxsl[callno]); 03155 if (iaxs[callno]) { 03156 iaxs[callno]->initid = -1; 03157 iax2_queue_frame(callno, &f); 03158 ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n"); 03159 } 03160 ast_mutex_unlock(&iaxsl[callno]); 03161 }
static void __auto_hangup | ( | const void * | nothing | ) | [static] |
Definition at line 6445 of file chan_iax2.c.
References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, and send_command_final().
Referenced by auto_hangup().
06446 { 06447 /* Called from IAX thread only, without iaxs lock */ 06448 int callno = (int)(long)(nothing); 06449 struct iax_ie_data ied; 06450 ast_mutex_lock(&iaxsl[callno]); 06451 if (iaxs[callno]) { 06452 memset(&ied, 0, sizeof(ied)); 06453 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); 06454 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); 06455 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 06456 } 06457 ast_mutex_unlock(&iaxsl[callno]); 06458 }
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 2056 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().
02057 { 02058 /* Just deliver the packet by using queueing. This is called by 02059 the IAX thread with the iaxsl lock held. */ 02060 struct iax_frame *fr = data; 02061 fr->retrans = -1; 02062 ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO); 02063 if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) 02064 iax2_queue_frame(fr->callno, &fr->af); 02065 /* Free our iax frame */ 02066 iax2_frame_free(fr); 02067 /* And don't run again */ 02068 return 0; 02069 }
static void __expire_registry | ( | const void * | data | ) | [static] |
Definition at line 6084 of file chan_iax2.c.
References iax2_peer::addr, ast_db_del(), ast_device_state_changed(), ast_log(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, globalflags, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, manager_event(), option_debug, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().
Referenced by expire_registry().
06085 { 06086 struct iax2_peer *peer = (struct iax2_peer *) data; 06087 06088 if (!peer) 06089 return; 06090 06091 peer->expire = -1; 06092 06093 if (option_debug) 06094 ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name); 06095 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) 06096 realtime_update_peer(peer->name, &peer->addr, 0); 06097 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 06098 /* Reset the address */ 06099 memset(&peer->addr, 0, sizeof(peer->addr)); 06100 /* Reset expiry value */ 06101 peer->expiry = min_reg_expire; 06102 if (!ast_test_flag(peer, IAX_TEMPONLY)) 06103 ast_db_del("IAX/Registry", peer->name); 06104 register_peer_exten(peer, 0); 06105 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 06106 if (iax2_regfunk) 06107 iax2_regfunk(peer->name, 0); 06108 06109 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) 06110 unlink_peer(peer); 06111 06112 peer_unref(peer); 06113 }
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 1529 of file chan_iax2.c.
References chan_iax2_pvt::addr, ao2_find(), ao2_ref(), ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, globalflags, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxsl, LOG_DEBUG, LOG_WARNING, match(), maxnontrunkcall, maxtrunkcall, MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, sched, send_lagrq(), send_ping(), store_by_peercallno(), TRUNK_CALL_START, and update_max_nontrunk().
Referenced by find_callno(), and find_callno_locked().
01530 { 01531 int res = 0; 01532 int x; 01533 struct timeval now; 01534 char host[80]; 01535 01536 if (new <= NEW_ALLOW) { 01537 if (callno) { 01538 struct chan_iax2_pvt *pvt; 01539 struct chan_iax2_pvt tmp_pvt = { 01540 .callno = dcallno, 01541 .peercallno = callno, 01542 /* hack!! */ 01543 .frames_received = check_dcallno, 01544 }; 01545 01546 memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr)); 01547 01548 if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 01549 if (return_locked) { 01550 ast_mutex_lock(&iaxsl[pvt->callno]); 01551 } 01552 res = pvt->callno; 01553 ao2_ref(pvt, -1); 01554 pvt = NULL; 01555 return res; 01556 } 01557 } 01558 01559 /* This will occur on the first response to a message that we initiated, 01560 * such as a PING. */ 01561 if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) { 01562 iaxs[dcallno]->peercallno = callno; 01563 res = dcallno; 01564 store_by_peercallno(iaxs[dcallno]); 01565 return res; 01566 } 01567 01568 #ifdef IAX_OLD_FIND 01569 /* If we get here, we SHOULD NOT find a call structure for this 01570 callno; if we do, it means that there is a call structure that 01571 has a peer callno but did NOT get entered into the hash table, 01572 which is bad. 01573 01574 If we find a call structure using this old, slow method, output a log 01575 message so we'll know about it. After a few months of leaving this in 01576 place, if we don't hear about people seeing these messages, we can 01577 remove this code for good. 01578 */ 01579 01580 for (x = 1; !res && x < maxnontrunkcall; x++) { 01581 ast_mutex_lock(&iaxsl[x]); 01582 if (iaxs[x]) { 01583 /* Look for an exact match */ 01584 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01585 res = x; 01586 } 01587 } 01588 if (!res || !return_locked) 01589 ast_mutex_unlock(&iaxsl[x]); 01590 } 01591 01592 for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) { 01593 ast_mutex_lock(&iaxsl[x]); 01594 if (iaxs[x]) { 01595 /* Look for an exact match */ 01596 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01597 res = x; 01598 } 01599 } 01600 if (!res || !return_locked) 01601 ast_mutex_unlock(&iaxsl[x]); 01602 } 01603 01604 if (res) { 01605 ast_log(LOG_WARNING, "Old call search code found call number %d that was not in hash table!\n", res); 01606 } 01607 #endif 01608 } 01609 if (!res && (new >= NEW_ALLOW)) { 01610 int start, found = 0; 01611 01612 /* It may seem odd that we look through the peer list for a name for 01613 * this *incoming* call. Well, it is weird. However, users don't 01614 * have an IP address/port number that we can match against. So, 01615 * this is just checking for a peer that has that IP/port and 01616 * assuming that we have a user of the same name. This isn't always 01617 * correct, but it will be changed if needed after authentication. */ 01618 if (!iax2_getpeername(*sin, host, sizeof(host))) 01619 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 01620 01621 now = ast_tvnow(); 01622 start = 2 + (ast_random() % (TRUNK_CALL_START - 1)); 01623 for (x = start; 1; x++) { 01624 if (x == TRUNK_CALL_START) { 01625 x = 1; 01626 continue; 01627 } 01628 01629 /* Find first unused call number that hasn't been used in a while */ 01630 ast_mutex_lock(&iaxsl[x]); 01631 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01632 found = 1; 01633 break; 01634 } 01635 ast_mutex_unlock(&iaxsl[x]); 01636 01637 if (x == start - 1) { 01638 break; 01639 } 01640 } 01641 /* We've still got lock held if we found a spot */ 01642 if (x == start - 1 && !found) { 01643 ast_log(LOG_WARNING, "No more space\n"); 01644 return 0; 01645 } 01646 iaxs[x] = new_iax(sin, host); 01647 update_max_nontrunk(); 01648 if (iaxs[x]) { 01649 if (option_debug && iaxdebug) 01650 ast_log(LOG_DEBUG, "Creating new call structure %d\n", x); 01651 iaxs[x]->sockfd = sockfd; 01652 iaxs[x]->addr.sin_port = sin->sin_port; 01653 iaxs[x]->addr.sin_family = sin->sin_family; 01654 iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr; 01655 iaxs[x]->peercallno = callno; 01656 iaxs[x]->callno = x; 01657 iaxs[x]->pingtime = DEFAULT_RETRY_TIME; 01658 iaxs[x]->expiry = min_reg_expire; 01659 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01660 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01661 iaxs[x]->amaflags = amaflags; 01662 ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 01663 01664 ast_string_field_set(iaxs[x], accountcode, accountcode); 01665 ast_string_field_set(iaxs[x], mohinterpret, mohinterpret); 01666 ast_string_field_set(iaxs[x], mohsuggest, mohsuggest); 01667 01668 if (iaxs[x]->peercallno) { 01669 store_by_peercallno(iaxs[x]); 01670 } 01671 } else { 01672 ast_log(LOG_WARNING, "Out of resources\n"); 01673 ast_mutex_unlock(&iaxsl[x]); 01674 return 0; 01675 } 01676 if (!return_locked) 01677 ast_mutex_unlock(&iaxsl[x]); 01678 res = x; 01679 } 01680 return res; 01681 }
static void __get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 2592 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(), 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().
02593 { 02594 int callno = PTR_TO_CALLNO(p); 02595 struct chan_iax2_pvt *pvt = NULL; 02596 struct iax_frame *fr; 02597 jb_frame frame; 02598 int ret; 02599 long now; 02600 long next; 02601 struct timeval tv; 02602 02603 /* Make sure we have a valid private structure before going on */ 02604 ast_mutex_lock(&iaxsl[callno]); 02605 pvt = iaxs[callno]; 02606 if (!pvt) { 02607 /* No go! */ 02608 ast_mutex_unlock(&iaxsl[callno]); 02609 return; 02610 } 02611 02612 pvt->jbid = -1; 02613 02614 gettimeofday(&tv,NULL); 02615 /* round up a millisecond since ast_sched_runq does; */ 02616 /* prevents us from spinning while waiting for our now */ 02617 /* to catch up with runq's now */ 02618 tv.tv_usec += 1000; 02619 02620 now = ast_tvdiff_ms(tv, pvt->rxcore); 02621 02622 if(now >= (next = jb_next(pvt->jb))) { 02623 ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat)); 02624 switch(ret) { 02625 case JB_OK: 02626 fr = frame.data; 02627 __do_deliver(fr); 02628 /* __do_deliver() can cause the call to disappear */ 02629 pvt = iaxs[callno]; 02630 break; 02631 case JB_INTERP: 02632 { 02633 struct ast_frame af = { 0, }; 02634 02635 /* create an interpolation frame */ 02636 af.frametype = AST_FRAME_VOICE; 02637 af.subclass = pvt->voiceformat; 02638 af.samples = frame.ms * 8; 02639 af.src = "IAX2 JB interpolation"; 02640 af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); 02641 af.offset = AST_FRIENDLY_OFFSET; 02642 02643 /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame, 02644 * which we'd need to malloc, and then it would free it. That seems like a drag */ 02645 if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 02646 iax2_queue_frame(callno, &af); 02647 /* iax2_queue_frame() could cause the call to disappear */ 02648 pvt = iaxs[callno]; 02649 } 02650 } 02651 break; 02652 case JB_DROP: 02653 iax2_frame_free(frame.data); 02654 break; 02655 case JB_NOFRAME: 02656 case JB_EMPTY: 02657 /* do nothing */ 02658 break; 02659 default: 02660 /* shouldn't happen */ 02661 break; 02662 } 02663 } 02664 if (pvt) 02665 update_jbsched(pvt); 02666 ast_mutex_unlock(&iaxsl[callno]); 02667 }
static void __iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 5777 of file chan_iax2.c.
References iax2_registry::expire, and iax2_do_register().
Referenced by iax2_do_register_s().
05778 { 05779 struct iax2_registry *reg = (struct iax2_registry *)data; 05780 reg->expire = -1; 05781 iax2_do_register(reg); 05782 }
static void __iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 8882 of file chan_iax2.c.
References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iax2_sched_add(), iaxsl, iax2_peer::lastms, LOG_NOTICE, manager_event(), peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, and sched.
Referenced by iax2_poke_noanswer().
08883 { 08884 struct iax2_peer *peer = (struct iax2_peer *)data; 08885 int callno; 08886 08887 if (peer->lastms > -1) { 08888 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); 08889 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); 08890 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 08891 } 08892 if ((callno = peer->callno) > 0) { 08893 ast_mutex_lock(&iaxsl[callno]); 08894 iax2_destroy(callno); 08895 ast_mutex_unlock(&iaxsl[callno]); 08896 } 08897 peer->callno = 0; 08898 peer->lastms = -1; 08899 /* Try again quickly */ 08900 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 08901 if (peer->pokeexpire == -1) 08902 peer_unref(peer); 08903 }
static void __iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 6508 of file chan_iax2.c.
References iax2_poke_peer(), and peer_unref().
Referenced by iax2_poke_peer_s().
06509 { 06510 struct iax2_peer *peer = (struct iax2_peer *)data; 06511 iax2_poke_peer(peer, 0); 06512 peer_unref(peer); 06513 }
static int __iax2_show_peers | ( | int | manager, | |
int | fd, | |||
struct mansession * | s, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4570 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, RESULT_SUCCESS, and s.
Referenced by iax2_show_peers(), and manager_iax2_show_peers().
04571 { 04572 regex_t regexbuf; 04573 int havepattern = 0; 04574 int total_peers = 0; 04575 int online_peers = 0; 04576 int offline_peers = 0; 04577 int unmonitored_peers = 0; 04578 struct ao2_iterator i; 04579 04580 #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" 04581 #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" 04582 04583 struct iax2_peer *peer = NULL; 04584 char name[256]; 04585 int registeredonly=0; 04586 char *term = manager ? "\r\n" : "\n"; 04587 04588 switch (argc) { 04589 case 6: 04590 if (!strcasecmp(argv[3], "registered")) 04591 registeredonly = 1; 04592 else 04593 return RESULT_SHOWUSAGE; 04594 if (!strcasecmp(argv[4], "like")) { 04595 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB)) 04596 return RESULT_SHOWUSAGE; 04597 havepattern = 1; 04598 } else 04599 return RESULT_SHOWUSAGE; 04600 break; 04601 case 5: 04602 if (!strcasecmp(argv[3], "like")) { 04603 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04604 return RESULT_SHOWUSAGE; 04605 havepattern = 1; 04606 } else 04607 return RESULT_SHOWUSAGE; 04608 break; 04609 case 4: 04610 if (!strcasecmp(argv[3], "registered")) 04611 registeredonly = 1; 04612 else 04613 return RESULT_SHOWUSAGE; 04614 break; 04615 case 3: 04616 break; 04617 default: 04618 return RESULT_SHOWUSAGE; 04619 } 04620 04621 04622 if (s) 04623 astman_append(s, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04624 else 04625 ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04626 04627 i = ao2_iterator_init(peers, 0); 04628 for (peer = ao2_iterator_next(&i); peer; 04629 peer_unref(peer), peer = ao2_iterator_next(&i)) { 04630 char nm[20]; 04631 char status[20]; 04632 char srch[2000]; 04633 int retstatus; 04634 04635 if (registeredonly && !peer->addr.sin_addr.s_addr) 04636 continue; 04637 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) 04638 continue; 04639 04640 if (!ast_strlen_zero(peer->username)) 04641 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 04642 else 04643 ast_copy_string(name, peer->name, sizeof(name)); 04644 04645 retstatus = peer_status(peer, status, sizeof(status)); 04646 if (retstatus > 0) 04647 online_peers++; 04648 else if (!retstatus) 04649 offline_peers++; 04650 else 04651 unmonitored_peers++; 04652 04653 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 04654 04655 snprintf(srch, sizeof(srch), FORMAT, name, 04656 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04657 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04658 nm, 04659 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04660 peer->encmethods ? "(E)" : " ", status, term); 04661 04662 if (s) 04663 astman_append(s, FORMAT, name, 04664 peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)", 04665 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04666 nm, 04667 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04668 peer->encmethods ? "(E)" : " ", status, term); 04669 else 04670 ast_cli(fd, FORMAT, name, 04671 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04672 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04673 nm, 04674 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04675 peer->encmethods ? "(E)" : " ", status, term); 04676 total_peers++; 04677 } 04678 04679 if (s) 04680 astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04681 else 04682 ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04683 04684 if (havepattern) 04685 regfree(®exbuf); 04686 04687 return RESULT_SUCCESS; 04688 #undef FORMAT 04689 #undef FORMAT2 04690 }
static int __schedule_action | ( | void(*)(const void *data) | func, | |
const void * | data, | |||
const char * | funcname | |||
) | [static] |
Definition at line 956 of file chan_iax2.c.
References ast_log(), find_idle_thread(), IAX_IOSTATE_SCHEDREADY, LOG_DEBUG, option_debug, signal_condition(), t, and thread.
00957 { 00958 struct iax2_thread *thread = NULL; 00959 static time_t lasterror; 00960 static time_t t; 00961 00962 thread = find_idle_thread(); 00963 00964 if (thread != NULL) { 00965 thread->schedfunc = func; 00966 thread->scheddata = data; 00967 thread->iostate = IAX_IOSTATE_SCHEDREADY; 00968 #ifdef DEBUG_SCHED_MULTITHREAD 00969 ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc)); 00970 #endif 00971 signal_condition(&thread->lock, &thread->cond); 00972 return 0; 00973 } 00974 time(&t); 00975 if (t != lasterror && option_debug) 00976 ast_log(LOG_DEBUG, "Out of idle IAX2 threads for scheduling!\n"); 00977 lasterror = t; 00978 00979 return -1; 00980 }
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 5071 of file chan_iax2.c.
References f, and iax2_send().
Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().
05073 { 05074 struct ast_frame f = { 0, }; 05075 05076 f.frametype = type; 05077 f.subclass = command; 05078 f.datalen = datalen; 05079 f.src = __FUNCTION__; 05080 f.data = (void *) data; 05081 05082 return iax2_send(i, &f, ts, seqno, now, transfer, final); 05083 }
static void __send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1041 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, iaxsl, LOG_WARNING, sched, send_command(), and send_lagrq().
Referenced by send_lagrq().
01042 { 01043 int callno = (long) data; 01044 01045 ast_mutex_lock(&iaxsl[callno]); 01046 01047 if (iaxs[callno]) { 01048 if (iaxs[callno]->peercallno) { 01049 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); 01050 iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data); 01051 } else { 01052 /* I am the schedule, so I'm allowed to do this */ 01053 iaxs[callno]->lagid = -1; 01054 } 01055 } else { 01056 ast_log(LOG_WARNING, "I was supposed to send a LAGRQ with callno %d, but no such call exists (and I cannot remove lagid, either).\n", callno); 01057 } 01058 01059 ast_mutex_unlock(&iaxsl[callno]); 01060 }
static void __send_ping | ( | const void * | data | ) | [static] |
Definition at line 996 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_sched_add(), IAX_COMMAND_PING, iaxsl, LOG_DEBUG, option_debug, sched, send_command(), and send_ping().
Referenced by send_ping().
00997 { 00998 int callno = (long) data; 00999 01000 ast_mutex_lock(&iaxsl[callno]); 01001 01002 if (iaxs[callno]) { 01003 if (iaxs[callno]->peercallno) { 01004 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); 01005 iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data); 01006 } else { 01007 /* I am the schedule, so I'm allowed to do this */ 01008 iaxs[callno]->pingid = -1; 01009 } 01010 } else if (option_debug > 0) { 01011 ast_log(LOG_DEBUG, "I was supposed to send a PING with callno %d, but no such call exists (and I cannot remove pingid, either).\n", callno); 01012 } 01013 01014 ast_mutex_unlock(&iaxsl[callno]); 01015 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 11001 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, netsock, outsock, peers, reload_firmware(), sched, sched_context_destroy(), thread, users, and waresl.
11002 { 11003 struct iax2_thread *thread = NULL; 11004 int x; 11005 11006 /* Make sure threads do not hold shared resources when they are canceled */ 11007 11008 /* Grab the sched lock resource to keep it away from threads about to die */ 11009 /* Cancel the network thread, close the net socket */ 11010 if (netthreadid != AST_PTHREADT_NULL) { 11011 AST_LIST_LOCK(&iaxq.queue); 11012 ast_mutex_lock(&sched_lock); 11013 pthread_cancel(netthreadid); 11014 ast_cond_signal(&sched_cond); 11015 ast_mutex_unlock(&sched_lock); /* Release the schedule lock resource */ 11016 AST_LIST_UNLOCK(&iaxq.queue); 11017 pthread_join(netthreadid, NULL); 11018 } 11019 if (schedthreadid != AST_PTHREADT_NULL) { 11020 ast_mutex_lock(&sched_lock); 11021 pthread_cancel(schedthreadid); 11022 ast_cond_signal(&sched_cond); 11023 ast_mutex_unlock(&sched_lock); 11024 pthread_join(schedthreadid, NULL); 11025 } 11026 11027 /* Call for all threads to halt */ 11028 AST_LIST_LOCK(&idle_list); 11029 AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) { 11030 AST_LIST_REMOVE_CURRENT(&idle_list, list); 11031 pthread_cancel(thread->threadid); 11032 } 11033 AST_LIST_TRAVERSE_SAFE_END 11034 AST_LIST_UNLOCK(&idle_list); 11035 11036 AST_LIST_LOCK(&active_list); 11037 AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) { 11038 AST_LIST_REMOVE_CURRENT(&active_list, list); 11039 pthread_cancel(thread->threadid); 11040 } 11041 AST_LIST_TRAVERSE_SAFE_END 11042 AST_LIST_UNLOCK(&active_list); 11043 11044 AST_LIST_LOCK(&dynamic_list); 11045 AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) { 11046 AST_LIST_REMOVE_CURRENT(&dynamic_list, list); 11047 pthread_cancel(thread->threadid); 11048 } 11049 AST_LIST_TRAVERSE_SAFE_END 11050 AST_LIST_UNLOCK(&dynamic_list); 11051 11052 AST_LIST_HEAD_DESTROY(&iaxq.queue); 11053 11054 /* Wait for threads to exit */ 11055 while(0 < iaxactivethreadcount) 11056 usleep(10000); 11057 11058 ast_netsock_release(netsock); 11059 ast_netsock_release(outsock); 11060 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 11061 if (iaxs[x]) { 11062 iax2_destroy(x); 11063 } 11064 } 11065 ast_manager_unregister( "IAXpeers" ); 11066 ast_manager_unregister( "IAXnetstats" ); 11067 ast_unregister_application(papp); 11068 ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 11069 ast_unregister_switch(&iax2_switch); 11070 ast_channel_unregister(&iax2_tech); 11071 delete_users(); 11072 iax_provision_unload(); 11073 sched_context_destroy(sched); 11074 reload_firmware(1); 11075 11076 ast_mutex_destroy(&waresl.lock); 11077 11078 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 11079 ast_mutex_destroy(&iaxsl[x]); 11080 } 11081 11082 ao2_ref(peers, -1); 11083 ao2_ref(users, -1); 11084 ao2_ref(iax_peercallno_pvts, -1); 11085 11086 return 0; 11087 }
static int apply_context | ( | struct iax2_context * | con, | |
const char * | context | |||
) | [static] |
Definition at line 5124 of file chan_iax2.c.
References iax2_context::context, and iax2_context::next.
Referenced by check_access().
05125 { 05126 while(con) { 05127 if (!strcmp(con->context, context) || !strcmp(con->context, "*")) 05128 return -1; 05129 con = con->next; 05130 } 05131 return 0; 05132 }
static int ast_cli_netstats | ( | struct mansession * | s, | |
int | fd, | |||
int | limit_fmt | |||
) | [static] |
Definition at line 4898 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, chan_iax2_pvt::remote_rr, and s.
Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().
04899 { 04900 int x; 04901 int numchans = 0; 04902 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 04903 ast_mutex_lock(&iaxsl[x]); 04904 if (iaxs[x]) { 04905 int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; 04906 char *fmt; 04907 jb_info jbinfo; 04908 04909 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04910 jb_getinfo(iaxs[x]->jb, &jbinfo); 04911 localjitter = jbinfo.jitter; 04912 localdelay = jbinfo.current - jbinfo.min; 04913 locallost = jbinfo.frames_lost; 04914 locallosspct = jbinfo.losspct/1000; 04915 localdropped = jbinfo.frames_dropped; 04916 localooo = jbinfo.frames_ooo; 04917 } else { 04918 localjitter = -1; 04919 localdelay = 0; 04920 locallost = -1; 04921 locallosspct = -1; 04922 localdropped = 0; 04923 localooo = -1; 04924 } 04925 if (limit_fmt) 04926 fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n"; 04927 else 04928 fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"; 04929 if (s) 04930 04931 astman_append(s, fmt, 04932 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04933 iaxs[x]->pingtime, 04934 localjitter, 04935 localdelay, 04936 locallost, 04937 locallosspct, 04938 localdropped, 04939 localooo, 04940 iaxs[x]->frames_received/1000, 04941 iaxs[x]->remote_rr.jitter, 04942 iaxs[x]->remote_rr.delay, 04943 iaxs[x]->remote_rr.losscnt, 04944 iaxs[x]->remote_rr.losspct, 04945 iaxs[x]->remote_rr.dropped, 04946 iaxs[x]->remote_rr.ooo, 04947 iaxs[x]->remote_rr.packets/1000); 04948 else 04949 ast_cli(fd, fmt, 04950 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04951 iaxs[x]->pingtime, 04952 localjitter, 04953 localdelay, 04954 locallost, 04955 locallosspct, 04956 localdropped, 04957 localooo, 04958 iaxs[x]->frames_received/1000, 04959 iaxs[x]->remote_rr.jitter, 04960 iaxs[x]->remote_rr.delay, 04961 iaxs[x]->remote_rr.losscnt, 04962 iaxs[x]->remote_rr.losspct, 04963 iaxs[x]->remote_rr.dropped, 04964 iaxs[x]->remote_rr.ooo, 04965 iaxs[x]->remote_rr.packets/1000 04966 ); 04967 numchans++; 04968 } 04969 ast_mutex_unlock(&iaxsl[x]); 04970 } 04971 return numchans; 04972 }
static struct ast_channel* ast_iax2_new | ( | int | callno, | |
int | state, | |||
int | capability | |||
) | [static] |
Create new call, interface with the PBX core.
Definition at line 3774 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().
03775 { 03776 struct ast_channel *tmp; 03777 struct chan_iax2_pvt *i; 03778 struct ast_variable *v = NULL; 03779 03780 if (!(i = iaxs[callno])) { 03781 ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); 03782 return NULL; 03783 } 03784 03785 /* Don't hold call lock */ 03786 ast_mutex_unlock(&iaxsl[callno]); 03787 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); 03788 ast_mutex_lock(&iaxsl[callno]); 03789 if (i != iaxs[callno]) { 03790 if (tmp) { 03791 /* unlock and relock iaxsl[callno] to preserve locking order */ 03792 ast_mutex_unlock(&iaxsl[callno]); 03793 ast_channel_free(tmp); 03794 ast_mutex_lock(&iaxsl[callno]); 03795 } 03796 return NULL; 03797 } 03798 03799 if (!tmp) 03800 return NULL; 03801 tmp->tech = &iax2_tech; 03802 /* We can support any format by default, until we get restricted */ 03803 tmp->nativeformats = capability; 03804 tmp->readformat = ast_best_codec(capability); 03805 tmp->writeformat = ast_best_codec(capability); 03806 tmp->tech_pvt = CALLNO_TO_PTR(i->callno); 03807 03808 /* Don't use ast_set_callerid() here because it will 03809 * generate a NewCallerID event before the NewChannel event */ 03810 if (!ast_strlen_zero(i->ani)) 03811 tmp->cid.cid_ani = ast_strdup(i->ani); 03812 else 03813 tmp->cid.cid_ani = ast_strdup(i->cid_num); 03814 tmp->cid.cid_dnid = ast_strdup(i->dnid); 03815 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 03816 tmp->cid.cid_pres = i->calling_pres; 03817 tmp->cid.cid_ton = i->calling_ton; 03818 tmp->cid.cid_tns = i->calling_tns; 03819 if (!ast_strlen_zero(i->language)) 03820 ast_string_field_set(tmp, language, i->language); 03821 if (!ast_strlen_zero(i->accountcode)) 03822 ast_string_field_set(tmp, accountcode, i->accountcode); 03823 if (i->amaflags) 03824 tmp->amaflags = i->amaflags; 03825 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 03826 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 03827 if (i->adsi) 03828 tmp->adsicpe = i->peeradsicpe; 03829 else 03830 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 03831 i->owner = tmp; 03832 i->capability = capability; 03833 03834 for (v = i->vars ; v ; v = v->next) 03835 pbx_builtin_setvar_helper(tmp, v->name, v->value); 03836 03837 if (state != AST_STATE_DOWN) { 03838 if (ast_pbx_start(tmp)) { 03839 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 03840 ast_hangup(tmp); 03841 i->owner = NULL; 03842 return NULL; 03843 } 03844 } 03845 03846 ast_module_ref(ast_module_info->self); 03847 03848 return tmp; 03849 }
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 2270 of file chan_iax2.c.
References __attempt_transmit(), and schedule_action.
Referenced by __attempt_transmit(), and network_thread().
02271 { 02272 #ifdef SCHED_MULTITHREADED 02273 if (schedule_action(__attempt_transmit, data)) 02274 #endif 02275 __attempt_transmit(data); 02276 return 0; 02277 }
static int auth_fail | ( | int | callno, | |
int | failcode | |||
) | [static] |
Definition at line 6430 of file chan_iax2.c.
References AST_SCHED_DEL, auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, iax2_sched_add(), iaxs, and sched.
Referenced by socket_process().
06431 { 06432 /* Schedule sending the authentication failure in one second, to prevent 06433 guessing */ 06434 if (iaxs[callno]) { 06435 iaxs[callno]->authfail = failcode; 06436 if (delayreject) { 06437 AST_SCHED_DEL(sched, iaxs[callno]->authid); 06438 iaxs[callno]->authid = iax2_sched_add(sched, 1000, auth_reject, (void *)(long)callno); 06439 } else 06440 auth_reject((void *)(long)callno); 06441 } 06442 return 0; 06443 }
static int auth_reject | ( | const void * | data | ) | [static] |
Definition at line 6416 of file chan_iax2.c.
References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::authid, iaxs, iaxsl, and schedule_action.
Referenced by auth_fail().
06417 { 06418 int callno = (int)(long)(data); 06419 ast_mutex_lock(&iaxsl[callno]); 06420 if (iaxs[callno]) 06421 iaxs[callno]->authid = -1; 06422 ast_mutex_unlock(&iaxsl[callno]); 06423 #ifdef SCHED_MULTITHREADED 06424 if (schedule_action(__auth_reject, data)) 06425 #endif 06426 __auth_reject(data); 06427 return 0; 06428 }
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 5646 of file chan_iax2.c.
References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_enc_keys(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, iax_ie_append_str(), IAX_IE_MD5_RESULT, IAX_IE_PASSWORD, IAX_IE_RSA_RESULT, LOG_NOTICE, md5(), MD5Final(), MD5Init(), and MD5Update().
05647 { 05648 int res = -1; 05649 int x; 05650 if (!ast_strlen_zero(keyn)) { 05651 if (!(authmethods & IAX_AUTH_RSA)) { 05652 if (ast_strlen_zero(secret)) 05653 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)); 05654 } else if (ast_strlen_zero(challenge)) { 05655 ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr)); 05656 } else { 05657 char sig[256]; 05658 struct ast_key *key; 05659 key = ast_key_get(keyn, AST_KEY_PRIVATE); 05660 if (!key) { 05661 ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); 05662 } else { 05663 if (ast_sign(key, (char*)challenge, sig)) { 05664 ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); 05665 res = -1; 05666 } else { 05667 iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); 05668 res = 0; 05669 } 05670 } 05671 } 05672 } 05673 /* Fall back */ 05674 if (res && !ast_strlen_zero(secret)) { 05675 if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) { 05676 struct MD5Context md5; 05677 unsigned char digest[16]; 05678 char digres[128]; 05679 MD5Init(&md5); 05680 MD5Update(&md5, (unsigned char *)challenge, strlen(challenge)); 05681 MD5Update(&md5, (unsigned char *)secret, strlen(secret)); 05682 MD5Final(digest, &md5); 05683 /* If they support md5, authenticate with it. */ 05684 for (x=0;x<16;x++) 05685 sprintf(digres + (x << 1), "%2.2x", digest[x]); /* safe */ 05686 if (ecx && dcx) 05687 build_enc_keys(digest, ecx, dcx); 05688 iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); 05689 res = 0; 05690 } else if (authmethods & IAX_AUTH_PLAINTEXT) { 05691 iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); 05692 res = 0; 05693 } else 05694 ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods); 05695 } 05696 return res; 05697 }
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 5703 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), authenticate(), iax2_peer::authmethods, chan_iax2_pvt::callno, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, iaxs, iaxsl, ies, iax2_peer::mask, merge_encryption(), peer_unref(), peers, realtime_peer(), and send_command().
Referenced by socket_process().
05704 { 05705 struct iax2_peer *peer = NULL; 05706 /* Start pessimistic */ 05707 int res = -1; 05708 int authmethods = 0; 05709 struct iax_ie_data ied; 05710 uint16_t callno = p->callno; 05711 05712 memset(&ied, 0, sizeof(ied)); 05713 05714 if (ies->username) 05715 ast_string_field_set(p, username, ies->username); 05716 if (ies->challenge) 05717 ast_string_field_set(p, challenge, ies->challenge); 05718 if (ies->authmethods) 05719 authmethods = ies->authmethods; 05720 if (authmethods & IAX_AUTH_MD5) 05721 merge_encryption(p, ies->encmethods); 05722 else 05723 p->encmethods = 0; 05724 05725 /* Check for override RSA authentication first */ 05726 if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) { 05727 /* Normal password authentication */ 05728 res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05729 } else { 05730 struct ao2_iterator i = ao2_iterator_init(peers, 0); 05731 while ((peer = ao2_iterator_next(&i))) { 05732 if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 05733 /* No peer specified at our end, or this is the peer */ 05734 && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) 05735 /* No username specified in peer rule, or this is the right username */ 05736 && (!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))) 05737 /* No specified host, or this is our host */ 05738 ) { 05739 res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05740 if (!res) { 05741 peer_unref(peer); 05742 break; 05743 } 05744 } 05745 peer_unref(peer); 05746 } 05747 if (!peer) { 05748 /* We checked our list and didn't find one. It's unlikely, but possible, 05749 that we're trying to authenticate *to* a realtime peer */ 05750 const char *peer_name = ast_strdupa(p->peer); 05751 ast_mutex_unlock(&iaxsl[callno]); 05752 if ((peer = realtime_peer(peer_name, NULL))) { 05753 ast_mutex_lock(&iaxsl[callno]); 05754 if (!(p = iaxs[callno])) { 05755 peer_unref(peer); 05756 return -1; 05757 } 05758 res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05759 peer_unref(peer); 05760 } 05761 if (!peer) { 05762 ast_mutex_lock(&iaxsl[callno]); 05763 if (!(p = iaxs[callno])) 05764 return -1; 05765 } 05766 } 05767 } 05768 if (ies->encmethods) 05769 ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); 05770 if (!res) 05771 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); 05772 return res; 05773 }
static int authenticate_request | ( | int | call_num | ) | [static] |
Definition at line 5381 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, iax2_user::curauthreq, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, iaxs, iax2_user::maxauthreq, send_command(), send_command_final(), user_unref(), and users.
Referenced by socket_process().
05382 { 05383 struct iax_ie_data ied; 05384 int res = -1, authreq_restrict = 0; 05385 char challenge[10]; 05386 struct chan_iax2_pvt *p = iaxs[call_num]; 05387 05388 memset(&ied, 0, sizeof(ied)); 05389 05390 /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */ 05391 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 05392 struct iax2_user *user, tmp_user = { 05393 .name = p->username, 05394 }; 05395 05396 user = ao2_find(users, &tmp_user, OBJ_POINTER); 05397 if (user) { 05398 if (user->curauthreq == user->maxauthreq) 05399 authreq_restrict = 1; 05400 else 05401 user->curauthreq++; 05402 user = user_unref(user); 05403 } 05404 } 05405 05406 /* If the AUTHREQ limit test failed, send back an error */ 05407 if (authreq_restrict) { 05408 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached"); 05409 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED); 05410 send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); 05411 return 0; 05412 } 05413 05414 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 05415 if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) { 05416 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 05417 ast_string_field_set(p, challenge, challenge); 05418 /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */ 05419 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge); 05420 } 05421 if (p->encmethods) 05422 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods); 05423 05424 iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username); 05425 05426 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1); 05427 05428 if (p->encmethods) 05429 ast_set_flag(p, IAX_ENCRYPTED); 05430 05431 return res; 05432 }
static int authenticate_verify | ( | struct chan_iax2_pvt * | p, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5434 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, ies, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), secret, chan_iax2_pvt::state, strsep(), user_unref(), and users.
Referenced by socket_process().
05435 { 05436 char requeststr[256]; 05437 char md5secret[256] = ""; 05438 char secret[256] = ""; 05439 char rsasecret[256] = ""; 05440 int res = -1; 05441 int x; 05442 struct iax2_user *user, tmp_user = { 05443 .name = p->username, 05444 }; 05445 05446 user = ao2_find(users, &tmp_user, OBJ_POINTER); 05447 if (user) { 05448 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 05449 ast_atomic_fetchadd_int(&user->curauthreq, -1); 05450 ast_clear_flag(p, IAX_MAXAUTHREQ); 05451 } 05452 ast_string_field_set(p, host, user->name); 05453 user = user_unref(user); 05454 } 05455 05456 if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) 05457 return res; 05458 if (ies->password) 05459 ast_copy_string(secret, ies->password, sizeof(secret)); 05460 if (ies->md5_result) 05461 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 05462 if (ies->rsa_result) 05463 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 05464 if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) { 05465 struct ast_key *key; 05466 char *keyn; 05467 char tmpkey[256]; 05468 char *stringp=NULL; 05469 ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey)); 05470 stringp=tmpkey; 05471 keyn = strsep(&stringp, ":"); 05472 while(keyn) { 05473 key = ast_key_get(keyn, AST_KEY_PUBLIC); 05474 if (key && !ast_check_signature(key, p->challenge, rsasecret)) { 05475 res = 0; 05476 break; 05477 } else if (!key) 05478 ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); 05479 keyn = strsep(&stringp, ":"); 05480 } 05481 } else if (p->authmethods & IAX_AUTH_MD5) { 05482 struct MD5Context md5; 05483 unsigned char digest[16]; 05484 char *tmppw, *stringp; 05485 05486 tmppw = ast_strdupa(p->secret); 05487 stringp = tmppw; 05488 while((tmppw = strsep(&stringp, ";"))) { 05489 MD5Init(&md5); 05490 MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge)); 05491 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05492 MD5Final(digest, &md5); 05493 /* If they support md5, authenticate with it. */ 05494 for (x=0;x<16;x++) 05495 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05496 if (!strcasecmp(requeststr, md5secret)) { 05497 res = 0; 05498 break; 05499 } 05500 } 05501 } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { 05502 if (!strcmp(secret, p->secret)) 05503 res = 0; 05504 } 05505 return res; 05506 }
static int auto_congest | ( | const void * | data | ) | [static] |
Definition at line 3163 of file chan_iax2.c.
References __auto_congest(), and schedule_action.
Referenced by iax2_call(), and sip_call().
03164 { 03165 #ifdef SCHED_MULTITHREADED 03166 if (schedule_action(__auto_congest, data)) 03167 #endif 03168 __auto_congest(data); 03169 return 0; 03170 }
static int auto_hangup | ( | const void * | data | ) | [static] |
Definition at line 6460 of file chan_iax2.c.
References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::autoid, iaxs, iaxsl, and schedule_action.
Referenced by iax2_dprequest(), and iax2_provision().
06461 { 06462 int callno = (int)(long)(data); 06463 ast_mutex_lock(&iaxsl[callno]); 06464 if (iaxs[callno]) { 06465 iaxs[callno]->autoid = -1; 06466 } 06467 ast_mutex_unlock(&iaxsl[callno]); 06468 #ifdef SCHED_MULTITHREADED 06469 if (schedule_action(__auto_hangup, data)) 06470 #endif 06471 __auto_hangup(data); 06472 return 0; 06473 }
static struct iax2_context* build_context | ( | char * | context | ) | [static] |
Definition at line 9202 of file chan_iax2.c.
References ast_calloc.
Referenced by build_user().
09203 { 09204 struct iax2_context *con; 09205 09206 if ((con = ast_calloc(1, sizeof(*con)))) 09207 ast_copy_string(con->context, context, sizeof(con->context)); 09208 09209 return con; 09210 }
static void build_enc_keys | ( | const unsigned char * | digest, | |
aes_encrypt_ctx * | ecx, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 4156 of file chan_iax2.c.
References aes_decrypt_key128(), and aes_encrypt_key128().
Referenced by authenticate(), and decrypt_frame().
04157 { 04158 aes_encrypt_key128(digest, ecx); 04159 aes_decrypt_key128(digest, dcx); 04160 }
static struct iax2_peer * build_peer | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static] |
Create peer structure based on configuration.
Definition at line 9349 of file chan_iax2.c.
References ao2_alloc(), ao2_find(), ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), AST_SCHED_DEL, ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), cid_name, cid_num, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, get_auth_methods(), get_encrypt_methods(), globalflags, iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, ast_variable::name, ast_variable::next, peer_destructor(), peer_set_srcaddr(), peer_unref(), peers, prefs, S_OR, sched, secret, unlink_peer(), and ast_variable::value.
09350 { 09351 struct iax2_peer *peer = NULL; 09352 struct ast_ha *oldha = NULL; 09353 int maskfound=0; 09354 int found=0; 09355 int firstpass=1; 09356 struct iax2_peer tmp_peer = { 09357 .name = name, 09358 }; 09359 09360 if (!temponly) { 09361 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 09362 if (peer && !ast_test_flag(peer, IAX_DELME)) 09363 firstpass = 0; 09364 } 09365 09366 if (peer) { 09367 found++; 09368 if (firstpass) { 09369 oldha = peer->ha; 09370 peer->ha = NULL; 09371 } 09372 unlink_peer(peer); 09373 } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) { 09374 peer->expire = -1; 09375 peer->pokeexpire = -1; 09376 peer->sockfd = defaultsockfd; 09377 if (ast_string_field_init(peer, 32)) 09378 peer = peer_unref(peer); 09379 } 09380 09381 if (peer) { 09382 if (firstpass) { 09383 ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 09384 peer->encmethods = iax2_encryption; 09385 peer->adsi = adsi; 09386 ast_string_field_set(peer,secret,""); 09387 if (!found) { 09388 ast_string_field_set(peer, name, name); 09389 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 09390 peer->expiry = min_reg_expire; 09391 } 09392 peer->prefs = prefs; 09393 peer->capability = iax2_capability; 09394 peer->smoothing = 0; 09395 peer->pokefreqok = DEFAULT_FREQ_OK; 09396 peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; 09397 ast_string_field_set(peer,context,""); 09398 ast_string_field_set(peer,peercontext,""); 09399 ast_clear_flag(peer, IAX_HASCALLERID); 09400 ast_string_field_set(peer, cid_name, ""); 09401 ast_string_field_set(peer, cid_num, ""); 09402 } 09403 09404 if (!v) { 09405 v = alt; 09406 alt = NULL; 09407 } 09408 while(v) { 09409 if (!strcasecmp(v->name, "secret")) { 09410 ast_string_field_set(peer, secret, v->value); 09411 } else if (!strcasecmp(v->name, "mailbox")) { 09412 ast_string_field_set(peer, mailbox, v->value); 09413 } else if (!strcasecmp(v->name, "hasvoicemail")) { 09414 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) { 09415 ast_string_field_set(peer, mailbox, name); 09416 } 09417 } else if (!strcasecmp(v->name, "mohinterpret")) { 09418 ast_string_field_set(peer, mohinterpret, v->value); 09419 } else if (!strcasecmp(v->name, "mohsuggest")) { 09420 ast_string_field_set(peer, mohsuggest, v->value); 09421 } else if (!strcasecmp(v->name, "dbsecret")) { 09422 ast_string_field_set(peer, dbsecret, v->value); 09423 } else if (!strcasecmp(v->name, "trunk")) { 09424 ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); 09425 if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) { 09426 ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without timing\n", peer->name); 09427 ast_clear_flag(peer, IAX_TRUNK); 09428 } 09429 } else if (!strcasecmp(v->name, "auth")) { 09430 peer->authmethods = get_auth_methods(v->value); 09431 } else if (!strcasecmp(v->name, "encryption")) { 09432 peer->encmethods = get_encrypt_methods(v->value); 09433 } else if (!strcasecmp(v->name, "notransfer")) { 09434 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09435 ast_clear_flag(peer, IAX_TRANSFERMEDIA); 09436 ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 09437 } else if (!strcasecmp(v->name, "transfer")) { 09438 if (!strcasecmp(v->value, "mediaonly")) { 09439 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09440 } else if (ast_true(v->value)) { 09441 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09442 } else 09443 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09444 } else if (!strcasecmp(v->name, "jitterbuffer")) { 09445 ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF); 09446 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 09447 ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF); 09448 } else if (!strcasecmp(v->name, "host")) { 09449 if (!strcasecmp(v->value, "dynamic")) { 09450 /* They'll register with us */ 09451 ast_set_flag(peer, IAX_DYNAMIC); 09452 if (!found) { 09453 /* Initialize stuff iff we're not found, otherwise 09454 we keep going with what we had */ 09455 memset(&peer->addr.sin_addr, 0, 4); 09456 if (peer->addr.sin_port) { 09457 /* If we've already got a port, make it the default rather than absolute */ 09458 peer->defaddr.sin_port = peer->addr.sin_port; 09459 peer->addr.sin_port = 0; 09460 } 09461 } 09462 } else { 09463 /* Non-dynamic. Make sure we become that way if we're not */ 09464 AST_SCHED_DEL(sched, peer->expire); 09465 ast_clear_flag(peer, IAX_DYNAMIC); 09466 if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) 09467 return peer_unref(peer); 09468 if (!peer->addr.sin_port) 09469 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 09470 } 09471 if (!maskfound) 09472 inet_aton("255.255.255.255", &peer->mask); 09473 } else if (!strcasecmp(v->name, "defaultip")) { 09474 if (ast_get_ip(&peer->defaddr, v->value)) 09475 return peer_unref(peer); 09476 } else if (!strcasecmp(v->name, "sourceaddress")) { 09477 peer_set_srcaddr(peer, v->value); 09478 } else if (!strcasecmp(v->name, "permit") || 09479 !strcasecmp(v->name, "deny")) { 09480 peer->ha = ast_append_ha(v->name, v->value, peer->ha); 09481 } else if (!strcasecmp(v->name, "mask")) { 09482 maskfound++; 09483 inet_aton(v->value, &peer->mask); 09484 } else if (!strcasecmp(v->name, "context")) { 09485 ast_string_field_set(peer, context, v->value); 09486 } else if (!strcasecmp(v->name, "regexten")) { 09487 ast_string_field_set(peer, regexten, v->value); 09488 } else if (!strcasecmp(v->name, "peercontext")) { 09489 ast_string_field_set(peer, peercontext, v->value); 09490 } else if (!strcasecmp(v->name, "port")) { 09491 if (ast_test_flag(peer, IAX_DYNAMIC)) 09492 peer->defaddr.sin_port = htons(atoi(v->value)); 09493 else 09494 peer->addr.sin_port = htons(atoi(v->value)); 09495 } else if (!strcasecmp(v->name, "username")) { 09496 ast_string_field_set(peer, username, v->value); 09497 } else if (!strcasecmp(v->name, "allow")) { 09498 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); 09499 } else if (!strcasecmp(v->name, "disallow")) { 09500 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); 09501 } else if (!strcasecmp(v->name, "callerid")) { 09502 if (!ast_strlen_zero(v->value)) { 09503 char name2[80]; 09504 char num2[80]; 09505 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 09506 ast_string_field_set(peer, cid_name, name2); 09507 ast_string_field_set(peer, cid_num, num2); 09508 } else { 09509 ast_string_field_set(peer, cid_name, ""); 09510 ast_string_field_set(peer, cid_num, ""); 09511 } 09512 ast_set_flag(peer, IAX_HASCALLERID); 09513 } else if (!strcasecmp(v->name, "fullname")) { 09514 ast_string_field_set(peer, cid_name, S_OR(v->value, "")); 09515 ast_set_flag(peer, IAX_HASCALLERID); 09516 } else if (!strcasecmp(v->name, "cid_number")) { 09517 ast_string_field_set(peer, cid_num, S_OR(v->value, "")); 09518 ast_set_flag(peer, IAX_HASCALLERID); 09519 } else if (!strcasecmp(v->name, "sendani")) { 09520 ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 09521 } else if (!strcasecmp(v->name, "inkeys")) { 09522 ast_string_field_set(peer, inkeys, v->value); 09523 } else if (!strcasecmp(v->name, "outkey")) { 09524 ast_string_field_set(peer, outkey, v->value); 09525 } else if (!strcasecmp(v->name, "qualify")) { 09526 if (!strcasecmp(v->value, "no")) { 09527 peer->maxms = 0; 09528 } else if (!strcasecmp(v->value, "yes")) { 09529 peer->maxms = DEFAULT_MAXMS; 09530 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 09531 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); 09532 peer->maxms = 0; 09533 } 09534 } else if (!strcasecmp(v->name, "qualifysmoothing")) { 09535 peer->smoothing = ast_true(v->value); 09536 } else if (!strcasecmp(v->name, "qualifyfreqok")) { 09537 if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) { 09538 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); 09539 } 09540 } else if (!strcasecmp(v->name, "qualifyfreqnotok")) { 09541 if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) { 09542 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); 09543 } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok); 09544 } else if (!strcasecmp(v->name, "timezone")) { 09545 ast_string_field_set(peer, zonetag, v->value); 09546 } else if (!strcasecmp(v->name, "adsi")) { 09547 peer->adsi = ast_true(v->value); 09548 }/* else if (strcasecmp(v->name,"type")) */ 09549 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09550 v = v->next; 09551 if (!v) { 09552 v = alt; 09553 alt = NULL; 09554 } 09555 } 09556 if (!peer->authmethods) 09557 peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09558 ast_clear_flag(peer, IAX_DELME); 09559 /* Make sure these are IPv4 addresses */ 09560 peer->addr.sin_family = AF_INET; 09561 } 09562 if (oldha) 09563 ast_free_ha(oldha); 09564 return peer; 09565 }
static struct iax2_user * build_user | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static] |
Create in-memory user structure from configuration.
Definition at line 9581 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(), globalflags, iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_user::prefs, prefs, secret, user_destructor(), user_unref(), users, ast_variable::value, and iax2_user::vars.
09582 { 09583 struct iax2_user *user = NULL; 09584 struct iax2_context *con, *conl = NULL; 09585 struct ast_ha *oldha = NULL; 09586 struct iax2_context *oldcon = NULL; 09587 int format; 09588 int firstpass=1; 09589 int oldcurauthreq = 0; 09590 char *varname = NULL, *varval = NULL; 09591 struct ast_variable *tmpvar = NULL; 09592 struct iax2_user tmp_user = { 09593 .name = name, 09594 }; 09595 09596 if (!temponly) { 09597 user = ao2_find(users, &tmp_user, OBJ_POINTER); 09598 if (user && !ast_test_flag(user, IAX_DELME)) 09599 firstpass = 0; 09600 } 09601 09602 if (user) { 09603 if (firstpass) { 09604 oldcurauthreq = user->curauthreq; 09605 oldha = user->ha; 09606 oldcon = user->contexts; 09607 user->ha = NULL; 09608 user->contexts = NULL; 09609 } 09610 /* Already in the list, remove it and it will be added back (or FREE'd) */ 09611 ao2_unlink(users, user); 09612 } else { 09613 user = ao2_alloc(sizeof(*user), user_destructor); 09614 } 09615 09616 if (user) { 09617 if (firstpass) { 09618 ast_string_field_free_memory(user); 09619 memset(user, 0, sizeof(struct iax2_user)); 09620 if (ast_string_field_init(user, 32)) { 09621 user = user_unref(user); 09622 goto cleanup; 09623 } 09624 user->maxauthreq = maxauthreq; 09625 user->curauthreq = oldcurauthreq; 09626 user->prefs = prefs; 09627 user->capability = iax2_capability; 09628 user->encmethods = iax2_encryption; 09629 user->adsi = adsi; 09630 ast_string_field_set(user, name, name); 09631 ast_string_field_set(user, language, language); 09632 ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); 09633 ast_clear_flag(user, IAX_HASCALLERID); 09634 ast_string_field_set(user, cid_name, ""); 09635 ast_string_field_set(user, cid_num, ""); 09636 } 09637 if (!v) { 09638 v = alt; 09639 alt = NULL; 09640 } 09641 while(v) { 09642 if (!strcasecmp(v->name, "context")) { 09643 con = build_context(v->value); 09644 if (con) { 09645 if (conl) 09646 conl->next = con; 09647 else 09648 user->contexts = con; 09649 conl = con; 09650 } 09651 } else if (!strcasecmp(v->name, "permit") || 09652 !strcasecmp(v->name, "deny")) { 09653 user->ha = ast_append_ha(v->name, v->value, user->ha); 09654 } else if (!strcasecmp(v->name, "setvar")) { 09655 varname = ast_strdupa(v->value); 09656 if (varname && (varval = strchr(varname,'='))) { 09657 *varval = '\0'; 09658 varval++; 09659 if((tmpvar = ast_variable_new(varname, varval))) { 09660 tmpvar->next = user->vars; 09661 user->vars = tmpvar; 09662 } 09663 } 09664 } else if (!strcasecmp(v->name, "allow")) { 09665 ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); 09666 } else if (!strcasecmp(v->name, "disallow")) { 09667 ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); 09668 } else if (!strcasecmp(v->name, "trunk")) { 09669 ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); 09670 if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) { 09671 ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without timing\n", user->name); 09672 ast_clear_flag(user, IAX_TRUNK); 09673 } 09674 } else if (!strcasecmp(v->name, "auth")) { 09675 user->authmethods = get_auth_methods(v->value); 09676 } else if (!strcasecmp(v->name, "encryption")) { 09677 user->encmethods = get_encrypt_methods(v->value); 09678 } else if (!strcasecmp(v->name, "notransfer")) { 09679 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09680 ast_clear_flag(user, IAX_TRANSFERMEDIA); 09681 ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 09682 } else if (!strcasecmp(v->name, "transfer")) { 09683 if (!strcasecmp(v->value, "mediaonly")) { 09684 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09685 } else if (ast_true(v->value)) { 09686 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09687 } else 09688 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09689 } else if (!strcasecmp(v->name, "codecpriority")) { 09690 if(!strcasecmp(v->value, "caller")) 09691 ast_set_flag(user, IAX_CODEC_USER_FIRST); 09692 else if(!strcasecmp(v->value, "disabled")) 09693 ast_set_flag(user, IAX_CODEC_NOPREFS); 09694 else if(!strcasecmp(v->value, "reqonly")) { 09695 ast_set_flag(user, IAX_CODEC_NOCAP); 09696 ast_set_flag(user, IAX_CODEC_NOPREFS); 09697 } 09698 } else if (!strcasecmp(v->name, "jitterbuffer")) { 09699 ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF); 09700 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 09701 ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF); 09702 } else if (!strcasecmp(v->name, "dbsecret")) { 09703 ast_string_field_set(user, dbsecret, v->value); 09704 } else if (!strcasecmp(v->name, "secret")) { 09705 if (!ast_strlen_zero(user->secret)) { 09706 char *old = ast_strdupa(user->secret); 09707 09708 ast_string_field_build(user, secret, "%s;%s", old, v->value); 09709 } else 09710 ast_string_field_set(user, secret, v->value); 09711 } else if (!strcasecmp(v->name, "callerid")) { 09712 if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) { 09713 char name2[80]; 09714 char num2[80]; 09715 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 09716 ast_string_field_set(user, cid_name, name2); 09717 ast_string_field_set(user, cid_num, num2); 09718 ast_set_flag(user, IAX_HASCALLERID); 09719 } else { 09720 ast_clear_flag(user, IAX_HASCALLERID); 09721 ast_string_field_set(user, cid_name, ""); 09722 ast_string_field_set(user, cid_num, ""); 09723 } 09724 } else if (!strcasecmp(v->name, "fullname")) { 09725 if (!ast_strlen_zero(v->value)) { 09726 ast_string_field_set(user, cid_name, v->value); 09727 ast_set_flag(user, IAX_HASCALLERID); 09728 } else { 09729 ast_string_field_set(user, cid_name, ""); 09730 if (ast_strlen_zero(user->cid_num)) 09731 ast_clear_flag(user, IAX_HASCALLERID); 09732 } 09733 } else if (!strcasecmp(v->name, "cid_number")) { 09734 if (!ast_strlen_zero(v->value)) { 09735 ast_string_field_set(user, cid_num, v->value); 09736 ast_set_flag(user, IAX_HASCALLERID); 09737 } else { 09738 ast_string_field_set(user, cid_num, ""); 09739 if (ast_strlen_zero(user->cid_name)) 09740 ast_clear_flag(user, IAX_HASCALLERID); 09741 } 09742 } else if (!strcasecmp(v->name, "accountcode")) { 09743 ast_string_field_set(user, accountcode, v->value); 09744 } else if (!strcasecmp(v->name, "mohinterpret")) { 09745 ast_string_field_set(user, mohinterpret, v->value); 09746 } else if (!strcasecmp(v->name, "mohsuggest")) { 09747 ast_string_field_set(user, mohsuggest, v->value); 09748 } else if (!strcasecmp(v->name, "language")) { 09749 ast_string_field_set(user, language, v->value); 09750 } else if (!strcasecmp(v->name, "amaflags")) { 09751 format = ast_cdr_amaflags2int(v->value); 09752 if (format < 0) { 09753 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 09754 } else { 09755 user->amaflags = format; 09756 } 09757 } else if (!strcasecmp(v->name, "inkeys")) { 09758 ast_string_field_set(user, inkeys, v->value); 09759 } else if (!strcasecmp(v->name, "maxauthreq")) { 09760 user->maxauthreq = atoi(v->value); 09761 if (user->maxauthreq < 0) 09762 user->maxauthreq = 0; 09763 } else if (!strcasecmp(v->name, "adsi")) { 09764 user->adsi = ast_true(v->value); 09765 }/* else if (strcasecmp(v->name,"type")) */ 09766 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09767 v = v->next; 09768 if (!v) { 09769 v = alt; 09770 alt = NULL; 09771 } 09772 } 09773 if (!user->authmethods) { 09774 if (!ast_strlen_zero(user->secret)) { 09775 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09776 if (!ast_strlen_zero(user->inkeys)) 09777 user->authmethods |= IAX_AUTH_RSA; 09778 } else if (!ast_strlen_zero(user->inkeys)) { 09779 user->authmethods = IAX_AUTH_RSA; 09780 } else { 09781 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09782 } 09783 } 09784 ast_clear_flag(user, IAX_DELME); 09785 } 09786 cleanup: 09787 if (oldha) 09788 ast_free_ha(oldha); 09789 if (oldcon) 09790 free_context(oldcon); 09791 return user; 09792 }
static int cache_get_callno_locked | ( | const char * | data | ) | [static] |
Definition at line 10298 of file chan_iax2.c.
References ARRAY_LEN, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), chan_iax2_pvt::capability, create_addr(), find_callno_locked(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, iaxs, iaxsl, LOG_WARNING, NEW_FORCE, option_debug, parse_dial_string(), secret, and send_command().
Referenced by find_cache().
10299 { 10300 struct sockaddr_in sin; 10301 int x; 10302 int callno; 10303 struct iax_ie_data ied; 10304 struct create_addr_info cai; 10305 struct parsed_dial_string pds; 10306 char *tmpstr; 10307 10308 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 10309 /* Look for an *exact match* call. Once a call is negotiated, it can only 10310 look up entries for a single context */ 10311 if (!ast_mutex_trylock(&iaxsl[x])) { 10312 if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) 10313 return x; 10314 ast_mutex_unlock(&iaxsl[x]); 10315 } 10316 } 10317 10318 /* No match found, we need to create a new one */ 10319 10320 memset(&cai, 0, sizeof(cai)); 10321 memset(&ied, 0, sizeof(ied)); 10322 memset(&pds, 0, sizeof(pds)); 10323 10324 tmpstr = ast_strdupa(data); 10325 parse_dial_string(tmpstr, &pds); 10326 10327 if (ast_strlen_zero(pds.peer)) { 10328 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data); 10329 return -1; 10330 } 10331 10332 /* Populate our address from the given */ 10333 if (create_addr(pds.peer, NULL, &sin, &cai)) 10334 return -1; 10335 10336 if (option_debug) 10337 ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n", 10338 pds.peer, pds.username, pds.password, pds.context); 10339 10340 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 10341 if (callno < 1) { 10342 ast_log(LOG_WARNING, "Unable to create call\n"); 10343 return -1; 10344 } 10345 10346 ast_string_field_set(iaxs[callno], dproot, data); 10347 iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; 10348 10349 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 10350 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); 10351 /* the string format is slightly different from a standard dial string, 10352 because the context appears in the 'exten' position 10353 */ 10354 if (pds.exten) 10355 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); 10356 if (pds.username) 10357 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 10358 iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); 10359 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); 10360 /* Keep password handy */ 10361 if (pds.password) 10362 ast_string_field_set(iaxs[callno], secret, pds.password); 10363 if (pds.key) 10364 ast_string_field_set(iaxs[callno], outkey, pds.key); 10365 /* Start the call going */ 10366 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 10367 10368 return callno; 10369 }
static unsigned int calc_rxstamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | offset | |||
) | [static] |
Definition at line 4024 of file chan_iax2.c.
References ast_log(), ast_random(), ast_tvsub(), chan_iax2_pvt::callno, option_debug, and chan_iax2_pvt::rxcore.
04025 { 04026 /* Returns where in "receive time" we are. That is, how many ms 04027 since we received (or would have received) the frame with timestamp 0 */ 04028 int ms; 04029 #ifdef IAXTESTS 04030 int jit; 04031 #endif /* IAXTESTS */ 04032 /* Setup rxcore if necessary */ 04033 if (ast_tvzero(p->rxcore)) { 04034 p->rxcore = ast_tvnow(); 04035 if (option_debug && iaxdebug) 04036 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n", 04037 p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset); 04038 p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000)); 04039 #if 1 04040 if (option_debug && iaxdebug) 04041 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n", 04042 p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec)); 04043 #endif 04044 } 04045 04046 ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore); 04047 #ifdef IAXTESTS 04048 if (test_jit) { 04049 if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) { 04050 jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0)); 04051 if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0))) 04052 jit = -jit; 04053 ms += jit; 04054 } 04055 } 04056 if (test_late) { 04057 ms += test_late; 04058 test_late = 0; 04059 } 04060 #endif /* IAXTESTS */ 04061 return ms; 04062 }
static unsigned int calc_timestamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | ts, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 3895 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, f, iaxs, chan_iax2_pvt::lastsent, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, and option_debug.
Referenced by iax2_send(), and socket_process().
03896 { 03897 int ms; 03898 int voice = 0; 03899 int genuine = 0; 03900 int adjust; 03901 struct timeval *delivery = NULL; 03902 03903 03904 /* What sort of frame do we have?: voice is self-explanatory 03905 "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK 03906 non-genuine frames are CONTROL frames [ringing etc], DTMF 03907 The "genuine" distinction is needed because genuine frames must get a clock-based timestamp, 03908 the others need a timestamp slaved to the voice frames so that they go in sequence 03909 */ 03910 if (f) { 03911 if (f->frametype == AST_FRAME_VOICE) { 03912 voice = 1; 03913 delivery = &f->delivery; 03914 } else if (f->frametype == AST_FRAME_IAX) { 03915 genuine = 1; 03916 } else if (f->frametype == AST_FRAME_CNG) { 03917 p->notsilenttx = 0; 03918 } 03919 } 03920 if (ast_tvzero(p->offset)) { 03921 gettimeofday(&p->offset, NULL); 03922 /* Round to nearest 20ms for nice looking traces */ 03923 p->offset.tv_usec -= p->offset.tv_usec % 20000; 03924 } 03925 /* If the timestamp is specified, just send it as is */ 03926 if (ts) 03927 return ts; 03928 /* If we have a time that the frame arrived, always use it to make our timestamp */ 03929 if (delivery && !ast_tvzero(*delivery)) { 03930 ms = ast_tvdiff_ms(*delivery, p->offset); 03931 if (option_debug > 2 && iaxdebug) 03932 ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno); 03933 } else { 03934 ms = ast_tvdiff_ms(ast_tvnow(), p->offset); 03935 if (ms < 0) 03936 ms = 0; 03937 if (voice) { 03938 /* On a voice frame, use predicted values if appropriate */ 03939 if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) { 03940 /* Adjust our txcore, keeping voice and non-voice synchronized */ 03941 /* AN EXPLANATION: 03942 When we send voice, we usually send "calculated" timestamps worked out 03943 on the basis of the number of samples sent. When we send other frames, 03944 we usually send timestamps worked out from the real clock. 03945 The problem is that they can tend to drift out of step because the 03946 source channel's clock and our clock may not be exactly at the same rate. 03947 We fix this by continuously "tweaking" p->offset. p->offset is "time zero" 03948 for this call. Moving it adjusts timestamps for non-voice frames. 03949 We make the adjustment in the style of a moving average. Each time we 03950 adjust p->offset by 10% of the difference between our clock-derived 03951 timestamp and the predicted timestamp. That's why you see "10000" 03952 below even though IAX2 timestamps are in milliseconds. 03953 The use of a moving average avoids offset moving too radically. 03954 Generally, "adjust" roams back and forth around 0, with offset hardly 03955 changing at all. But if a consistent different starts to develop it 03956 will be eliminated over the course of 10 frames (200-300msecs) 03957 */ 03958 adjust = (ms - p->nextpred); 03959 if (adjust < 0) 03960 p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000)); 03961 else if (adjust > 0) 03962 p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000)); 03963 03964 if (!p->nextpred) { 03965 p->nextpred = ms; /*f->samples / 8;*/ 03966 if (p->nextpred <= p->lastsent) 03967 p->nextpred = p->lastsent + 3; 03968 } 03969 ms = p->nextpred; 03970 } else { 03971 /* in this case, just use the actual 03972 * time, since we're either way off 03973 * (shouldn't happen), or we're ending a 03974 * silent period -- and seed the next 03975 * predicted time. Also, round ms to the 03976 * next multiple of frame size (so our 03977 * silent periods are multiples of 03978 * frame size too) */ 03979 03980 if (option_debug && iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW ) 03981 ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n", 03982 abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW); 03983 03984 if (f->samples >= 8) /* check to make sure we dont core dump */ 03985 { 03986 int diff = ms % (f->samples / 8); 03987 if (diff) 03988 ms += f->samples/8 - diff; 03989 } 03990 03991 p->nextpred = ms; 03992 p->notsilenttx = 1; 03993 } 03994 } else if ( f->frametype == AST_FRAME_VIDEO ) { 03995 /* 03996 * IAX2 draft 03 says that timestamps MUST be in order. 03997 * It does not say anything about several frames having the same timestamp 03998 * When transporting video, we can have a frame that spans multiple iax packets 03999 * (so called slices), so it would make sense to use the same timestamp for all of 04000 * them 04001 * We do want to make sure that frames don't go backwards though 04002 */ 04003 if ( (unsigned int)ms < p->lastsent ) 04004 ms = p->lastsent; 04005 } else { 04006 /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless 04007 it's a genuine frame */ 04008 if (genuine) { 04009 /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */ 04010 if (ms <= p->lastsent) 04011 ms = p->lastsent + 3; 04012 } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) { 04013 /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */ 04014 ms = p->lastsent + 3; 04015 } 04016 } 04017 } 04018 p->lastsent = ms; 04019 if (voice) 04020 p->nextpred = p->nextpred + f->samples / 8; 04021 return ms; 04022 }
static unsigned int calc_txpeerstamp | ( | struct iax2_trunk_peer * | tpeer, | |
int | sampms, | |||
struct timeval * | tv | |||
) | [static] |
Definition at line 3851 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().
03852 { 03853 unsigned long int mssincetx; /* unsigned to handle overflows */ 03854 long int ms, pred; 03855 03856 tpeer->trunkact = *tv; 03857 mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime); 03858 if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) { 03859 /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */ 03860 tpeer->txtrunktime = *tv; 03861 tpeer->lastsent = 999999; 03862 } 03863 /* Update last transmit time now */ 03864 tpeer->lasttxtime = *tv; 03865 03866 /* Calculate ms offset */ 03867 ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime); 03868 /* Predict from last value */ 03869 pred = tpeer->lastsent + sampms; 03870 if (abs(ms - pred) < MAX_TIMESTAMP_SKEW) 03871 ms = pred; 03872 03873 /* We never send the same timestamp twice, so fudge a little if we must */ 03874 if (ms == tpeer->lastsent) 03875 ms = tpeer->lastsent + 1; 03876 tpeer->lastsent = ms; 03877 return ms; 03878 }
static int check_access | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5135 of file chan_iax2.c.
References iax2_user::adsi, chan_iax2_pvt::adsi, chan_iax2_pvt::amaflags, iax2_user::amaflags, ao2_iterator_init(), ao2_iterator_next(), apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), iax2_user::authmethods, chan_iax2_pvt::authmethods, chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, cid_name, cid_num, iax2_context::context, iax2_user::contexts, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax2_user::ha, iax2_getpeertrunk(), IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, ies, 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, realtime_user(), secret, user_unref(), users, ast_variable::value, chan_iax2_pvt::vars, and iax2_user::vars.
Referenced by socket_process().
05136 { 05137 /* Start pessimistic */ 05138 int res = -1; 05139 int version = 2; 05140 struct iax2_user *user = NULL, *best = NULL; 05141 int bestscore = 0; 05142 int gotcapability = 0; 05143 struct ast_variable *v = NULL, *tmpvar = NULL; 05144 struct ao2_iterator i; 05145 05146 if (!iaxs[callno]) 05147 return res; 05148 if (ies->called_number) 05149 ast_string_field_set(iaxs[callno], exten, ies->called_number); 05150 if (ies->calling_number) { 05151 ast_shrink_phone_number(ies->calling_number); 05152 ast_string_field_set(iaxs[callno], cid_num, ies->calling_number); 05153 } 05154 if (ies->calling_name) 05155 ast_string_field_set(iaxs[callno], cid_name, ies->calling_name); 05156 if (ies->calling_ani) 05157 ast_string_field_set(iaxs[callno], ani, ies->calling_ani); 05158 if (ies->dnid) 05159 ast_string_field_set(iaxs[callno], dnid, ies->dnid); 05160 if (ies->rdnis) 05161 ast_string_field_set(iaxs[callno], rdnis, ies->rdnis); 05162 if (ies->called_context) 05163 ast_string_field_set(iaxs[callno], context, ies->called_context); 05164 if (ies->language) 05165 ast_string_field_set(iaxs[callno], language, ies->language); 05166 if (ies->username) 05167 ast_string_field_set(iaxs[callno], username, ies->username); 05168 if (ies->calling_ton > -1) 05169 iaxs[callno]->calling_ton = ies->calling_ton; 05170 if (ies->calling_tns > -1) 05171 iaxs[callno]->calling_tns = ies->calling_tns; 05172 if (ies->calling_pres > -1) 05173 iaxs[callno]->calling_pres = ies->calling_pres; 05174 if (ies->format) 05175 iaxs[callno]->peerformat = ies->format; 05176 if (ies->adsicpe) 05177 iaxs[callno]->peeradsicpe = ies->adsicpe; 05178 if (ies->capability) { 05179 gotcapability = 1; 05180 iaxs[callno]->peercapability = ies->capability; 05181 } 05182 if (ies->version) 05183 version = ies->version; 05184 05185 /* Use provided preferences until told otherwise for actual preferences */ 05186 if(ies->codec_prefs) { 05187 ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); 05188 ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); 05189 } 05190 05191 if (!gotcapability) 05192 iaxs[callno]->peercapability = iaxs[callno]->peerformat; 05193 if (version > IAX_PROTO_VERSION) { 05194 ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 05195 ast_inet_ntoa(sin->sin_addr), version); 05196 return res; 05197 } 05198 /* Search the userlist for a compatible entry, and fill in the rest */ 05199 i = ao2_iterator_init(users, 0); 05200 while ((user = ao2_iterator_next(&i))) { 05201 if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ 05202 !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ 05203 && ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */ 05204 && (ast_strlen_zero(iaxs[callno]->context) || /* No context specified */ 05205 apply_context(user->contexts, iaxs[callno]->context))) { /* Context is permitted */ 05206 if (!ast_strlen_zero(iaxs[callno]->username)) { 05207 /* Exact match, stop right now. */ 05208 if (best) 05209 user_unref(best); 05210 best = user; 05211 break; 05212 } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) { 05213 /* No required authentication */ 05214 if (user->ha) { 05215 /* There was host authentication and we passed, bonus! */ 05216 if (bestscore < 4) { 05217 bestscore = 4; 05218 if (best) 05219 user_unref(best); 05220 best = user; 05221 continue; 05222 } 05223 } else { 05224 /* No host access, but no secret, either, not bad */ 05225 if (bestscore < 3) { 05226 bestscore = 3; 05227 if (best) 05228 user_unref(best); 05229 best = user; 05230 continue; 05231 } 05232 } 05233 } else { 05234 if (user->ha) { 05235 /* Authentication, but host access too, eh, it's something.. */ 05236 if (bestscore < 2) { 05237 bestscore = 2; 05238 if (best) 05239 user_unref(best); 05240 best = user; 05241 continue; 05242 } 05243 } else { 05244 /* Authentication and no host access... This is our baseline */ 05245 if (bestscore < 1) { 05246 bestscore = 1; 05247 if (best) 05248 user_unref(best); 05249 best = user; 05250 continue; 05251 } 05252 } 05253 } 05254 } 05255 user_unref(user); 05256 } 05257 user = best; 05258 if (!user && !ast_strlen_zero(iaxs[callno]->username)) { 05259 user = realtime_user(iaxs[callno]->username, sin); 05260 if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ 05261 !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ 05262 user = user_unref(user); 05263 } 05264 } 05265 if (user) { 05266 /* We found our match (use the first) */ 05267 /* copy vars */ 05268 for (v = user->vars ; v ; v = v->next) { 05269 if((tmpvar = ast_variable_new(v->name, v->value))) { 05270 tmpvar->next = iaxs[callno]->vars; 05271 iaxs[callno]->vars = tmpvar; 05272 } 05273 } 05274 /* If a max AUTHREQ restriction is in place, activate it */ 05275 if (user->maxauthreq > 0) 05276 ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ); 05277 iaxs[callno]->prefs = user->prefs; 05278 ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST); 05279 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS); 05280 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP); 05281 iaxs[callno]->encmethods = user->encmethods; 05282 /* Store the requested username if not specified */ 05283 if (ast_strlen_zero(iaxs[callno]->username)) 05284 ast_string_field_set(iaxs[callno], username, user->name); 05285 /* Store whether this is a trunked call, too, of course, and move if appropriate */ 05286 ast_copy_flags(iaxs[callno], user, IAX_TRUNK); 05287 iaxs[callno]->capability = user->capability; 05288 /* And use the default context */ 05289 if (ast_strlen_zero(iaxs[callno]->context)) { 05290 if (user->contexts) 05291 ast_string_field_set(iaxs[callno], context, user->contexts->context); 05292 else 05293 ast_string_field_set(iaxs[callno], context, context); 05294 } 05295 /* And any input keys */ 05296 ast_string_field_set(iaxs[callno], inkeys, user->inkeys); 05297 /* And the permitted authentication methods */ 05298 iaxs[callno]->authmethods = user->authmethods; 05299 iaxs[callno]->adsi = user->adsi; 05300 /* If the user has callerid, override the remote caller id. */ 05301 if (ast_test_flag(user, IAX_HASCALLERID)) { 05302 iaxs[callno]->calling_tns = 0; 05303 iaxs[callno]->calling_ton = 0; 05304 ast_string_field_set(iaxs[callno], cid_num, user->cid_num); 05305 ast_string_field_set(iaxs[callno], cid_name, user->cid_name); 05306 ast_string_field_set(iaxs[callno], ani, user->cid_num); 05307 iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 05308 } else if (ast_strlen_zero(iaxs[callno]->cid_num) && ast_strlen_zero(iaxs[callno]->cid_name)) { 05309 iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE; 05310 } /* else user is allowed to set their own CID settings */ 05311 if (!ast_strlen_zero(user->accountcode)) 05312 ast_string_field_set(iaxs[callno], accountcode, user->accountcode); 05313 if (!ast_strlen_zero(user->mohinterpret)) 05314 ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret); 05315 if (!ast_strlen_zero(user->mohsuggest)) 05316 ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest); 05317 if (user->amaflags) 05318 iaxs[callno]->amaflags = user->amaflags; 05319 if (!ast_strlen_zero(user->language)) 05320 ast_string_field_set(iaxs[callno], language, user->language); 05321 ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 05322 /* Keep this check last */ 05323 if (!ast_strlen_zero(user->dbsecret)) { 05324 char *family, *key=NULL; 05325 char buf[80]; 05326 family = ast_strdupa(user->dbsecret); 05327 key = strchr(family, '/'); 05328 if (key) { 05329 *key = '\0'; 05330 key++; 05331 } 05332 if (!key || ast_db_get(family, key, buf, sizeof(buf))) 05333 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); 05334 else 05335 ast_string_field_set(iaxs[callno], secret, buf); 05336 } else 05337 ast_string_field_set(iaxs[callno], secret, user->secret); 05338 res = 0; 05339 user = user_unref(user); 05340 } 05341 ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK); 05342 return res; 05343 }
static int check_provisioning | ( | struct sockaddr_in * | sin, | |
int | sockfd, | |||
char * | si, | |||
unsigned int | ver | |||
) | [static] |
Definition at line 6818 of file chan_iax2.c.
References ast_log(), iax2_provision(), iax_provision_version(), and option_debug.
Referenced by socket_process().
06819 { 06820 unsigned int ourver; 06821 char rsi[80]; 06822 snprintf(rsi, sizeof(rsi), "si-%s", si); 06823 if (iax_provision_version(&ourver, rsi, 1)) 06824 return 0; 06825 if (option_debug) 06826 ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver); 06827 if (ourver != ver) 06828 iax2_provision(sin, sockfd, NULL, rsi, 1); 06829 return 0; 06830 }
static int check_srcaddr | ( | struct sockaddr * | sa, | |
socklen_t | salen | |||
) | [static] |
Check if address can be used as packet source.
Definition at line 9228 of file chan_iax2.c.
References ast_log(), errno, LOG_ERROR, and option_debug.
Referenced by peer_set_srcaddr().
09229 { 09230 int sd; 09231 int res; 09232 09233 sd = socket(AF_INET, SOCK_DGRAM, 0); 09234 if (sd < 0) { 09235 ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); 09236 return -1; 09237 } 09238 09239 res = bind(sd, sa, salen); 09240 if (res < 0) { 09241 if (option_debug) 09242 ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno)); 09243 close(sd); 09244 return 1; 09245 } 09246 09247 close(sd); 09248 return 0; 09249 }
static int complete_dpreply | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5822 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, iax2_dpcache::callno, chan_iax2_pvt::dpentries, iax2_dpcache::expiry, expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, ies, iax2_dpcache::orig, iax2_dpcache::peer, and iax2_dpcache::waiters.
Referenced by socket_process().
05823 { 05824 char exten[256] = ""; 05825 int status = CACHE_FLAG_UNKNOWN; 05826 int expiry = iaxdefaultdpcache; 05827 int x; 05828 int matchmore = 0; 05829 struct iax2_dpcache *dp, *prev; 05830 05831 if (ies->called_number) 05832 ast_copy_string(exten, ies->called_number, sizeof(exten)); 05833 05834 if (ies->dpstatus & IAX_DPSTATUS_EXISTS) 05835 status = CACHE_FLAG_EXISTS; 05836 else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST) 05837 status = CACHE_FLAG_CANEXIST; 05838 else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT) 05839 status = CACHE_FLAG_NONEXISTENT; 05840 05841 if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) { 05842 /* Don't really do anything with this */ 05843 } 05844 if (ies->refresh) 05845 expiry = ies->refresh; 05846 if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE) 05847 matchmore = CACHE_FLAG_MATCHMORE; 05848 ast_mutex_lock(&dpcache_lock); 05849 prev = NULL; 05850 dp = pvt->dpentries; 05851 while(dp) { 05852 if (!strcmp(dp->exten, exten)) { 05853 /* Let them go */ 05854 if (prev) 05855 prev->peer = dp->peer; 05856 else 05857 pvt->dpentries = dp->peer; 05858 dp->peer = NULL; 05859 dp->callno = 0; 05860 dp->expiry.tv_sec = dp->orig.tv_sec + expiry; 05861 if (dp->flags & CACHE_FLAG_PENDING) { 05862 dp->flags &= ~CACHE_FLAG_PENDING; 05863 dp->flags |= status; 05864 dp->flags |= matchmore; 05865 } 05866 /* Wake up waiters */ 05867 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 05868 if (dp->waiters[x] > -1) 05869 write(dp->waiters[x], "asdf", 4); 05870 } 05871 prev = dp; 05872 dp = dp->peer; 05873 } 05874 ast_mutex_unlock(&dpcache_lock); 05875 return 0; 05876 }
static char* complete_iax2_show_peer | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 2432 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_strdup, peer_unref(), and peers.
02433 { 02434 int which = 0; 02435 struct iax2_peer *peer; 02436 char *res = NULL; 02437 int wordlen = strlen(word); 02438 struct ao2_iterator i; 02439 02440 /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */ 02441 if (pos != 3) 02442 return NULL; 02443 02444 i = ao2_iterator_init(peers, 0); 02445 while ((peer = ao2_iterator_next(&i))) { 02446 if (!strncasecmp(peer->name, word, wordlen) && ++which > state) { 02447 res = ast_strdup(peer->name); 02448 peer_unref(peer); 02449 break; 02450 } 02451 peer_unref(peer); 02452 } 02453 02454 return res; 02455 }
static int complete_transfer | ( | int | callno, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5878 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), iaxq, iaxs, ies, chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, 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().
05879 { 05880 int peercallno = 0; 05881 struct chan_iax2_pvt *pvt = iaxs[callno]; 05882 struct iax_frame *cur; 05883 jb_frame frame; 05884 05885 if (ies->callno) 05886 peercallno = ies->callno; 05887 05888 if (peercallno < 1) { 05889 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05890 return -1; 05891 } 05892 memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr)); 05893 memset(&pvt->transfer, 0, sizeof(pvt->transfer)); 05894 /* Reset sequence numbers */ 05895 pvt->oseqno = 0; 05896 pvt->rseqno = 0; 05897 pvt->iseqno = 0; 05898 pvt->aseqno = 0; 05899 05900 if (pvt->peercallno) { 05901 remove_by_peercallno(pvt); 05902 } 05903 pvt->peercallno = peercallno; 05904 store_by_peercallno(pvt); 05905 05906 pvt->transferring = TRANSFER_NONE; 05907 pvt->svoiceformat = -1; 05908 pvt->voiceformat = 0; 05909 pvt->svideoformat = -1; 05910 pvt->videoformat = 0; 05911 pvt->transfercallno = -1; 05912 memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); 05913 memset(&pvt->offset, 0, sizeof(pvt->offset)); 05914 /* reset jitterbuffer */ 05915 while(jb_getall(pvt->jb,&frame) == JB_OK) 05916 iax2_frame_free(frame.data); 05917 jb_reset(pvt->jb); 05918 pvt->lag = 0; 05919 pvt->last = 0; 05920 pvt->lastsent = 0; 05921 pvt->nextpred = 0; 05922 pvt->pingtime = DEFAULT_RETRY_TIME; 05923 AST_LIST_LOCK(&iaxq.queue); 05924 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 05925 /* We must cancel any packets that would have been transmitted 05926 because now we're talking to someone new. It's okay, they 05927 were transmitted to someone that didn't care anyway. */ 05928 if (callno == cur->callno) 05929 cur->retries = -1; 05930 } 05931 AST_LIST_UNLOCK(&iaxq.queue); 05932 return 0; 05933 }
static unsigned char compress_subclass | ( | int | subclass | ) | [static] |
Definition at line 1072 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().
01073 { 01074 int x; 01075 int power=-1; 01076 /* If it's 128 or smaller, just return it */ 01077 if (subclass < IAX_FLAG_SC_LOG) 01078 return subclass; 01079 /* Otherwise find its power */ 01080 for (x = 0; x < IAX_MAX_SHIFT; x++) { 01081 if (subclass & (1 << x)) { 01082 if (power > -1) { 01083 ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass); 01084 return 0; 01085 } else 01086 power = x; 01087 } 01088 } 01089 return power | IAX_FLAG_SC_LOG; 01090 }
static void construct_rr | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ie_data * | iep | |||
) | [static] |
Definition at line 6832 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().
06833 { 06834 jb_info stats; 06835 jb_getinfo(pvt->jb, &stats); 06836 06837 memset(iep, 0, sizeof(*iep)); 06838 06839 iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter); 06840 if(stats.frames_in == 0) stats.frames_in = 1; 06841 iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff))); 06842 iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in); 06843 iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min); 06844 iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped); 06845 iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo); 06846 }
static int create_addr | ( | const char * | peername, | |
struct ast_channel * | c, | |||
struct sockaddr_in * | sin, | |||
struct create_addr_info * | cai | |||
) | [static] |
Definition at line 3055 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ahp, ast_clear_flag, ast_codec_pref_convert(), ast_codec_pref_prepend(), ast_copy_flags, ast_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_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.
03056 { 03057 struct ast_hostent ahp; 03058 struct hostent *hp; 03059 struct iax2_peer *peer; 03060 int res = -1; 03061 struct ast_codec_pref ourprefs; 03062 03063 ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); 03064 cai->sockfd = defaultsockfd; 03065 cai->maxtime = 0; 03066 sin->sin_family = AF_INET; 03067 03068 if (!(peer = find_peer(peername, 1))) { 03069 cai->found = 0; 03070 03071 hp = ast_gethostbyname(peername, &ahp); 03072 if (hp) { 03073 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 03074 sin->sin_port = htons(IAX_DEFAULT_PORTNO); 03075 /* use global iax prefs for unknown peer/user */ 03076 /* But move the calling channel's native codec to the top of the preference list */ 03077 memcpy(&ourprefs, &prefs, sizeof(ourprefs)); 03078 if (c) 03079 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03080 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03081 return 0; 03082 } else { 03083 ast_log(LOG_WARNING, "No such host: %s\n", peername); 03084 return -1; 03085 } 03086 } 03087 03088 cai->found = 1; 03089 03090 /* if the peer has no address (current or default), return failure */ 03091 if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) 03092 goto return_unref; 03093 03094 /* if the peer is being monitored and is currently unreachable, return failure */ 03095 if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) 03096 goto return_unref; 03097 03098 ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 03099 cai->maxtime = peer->maxms; 03100 cai->capability = peer->capability; 03101 cai->encmethods = peer->encmethods; 03102 cai->sockfd = peer->sockfd; 03103 cai->adsi = peer->adsi; 03104 memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); 03105 /* Move the calling channel's native codec to the top of the preference list */ 03106 if (c) { 03107 ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats); 03108 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03109 } 03110 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03111 ast_copy_string(cai->context, peer->context, sizeof(cai->context)); 03112 ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); 03113 ast_copy_string(cai->username, peer->username, sizeof(cai->username)); 03114 ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); 03115 ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); 03116 ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret)); 03117 ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest)); 03118 if (ast_strlen_zero(peer->dbsecret)) { 03119 ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); 03120 } else { 03121 char *family; 03122 char *key = NULL; 03123 03124 family = ast_strdupa(peer->dbsecret); 03125 key = strchr(family, '/'); 03126 if (key) 03127 *key++ = '\0'; 03128 if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { 03129 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); 03130 goto return_unref; 03131 } 03132 } 03133 03134 if (peer->addr.sin_addr.s_addr) { 03135 sin->sin_addr = peer->addr.sin_addr; 03136 sin->sin_port = peer->addr.sin_port; 03137 } else { 03138 sin->sin_addr = peer->defaddr.sin_addr; 03139 sin->sin_port = peer->defaddr.sin_port; 03140 } 03141 03142 res = 0; 03143 03144 return_unref: 03145 peer_unref(peer); 03146 03147 return res; 03148 }
static int decode_frame | ( | aes_decrypt_ctx * | dcx, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4210 of file chan_iax2.c.
References AST_FRAME_VIDEO, ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, f, IAX_FLAG_FULL, memcpy_decrypt(), option_debug, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::type, and uncompress_subclass().
Referenced by decrypt_frame().
04211 { 04212 int padding; 04213 unsigned char *workspace; 04214 04215 workspace = alloca(*datalen); 04216 memset(f, 0, sizeof(*f)); 04217 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04218 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04219 if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr)) 04220 return -1; 04221 /* Decrypt */ 04222 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx); 04223 04224 padding = 16 + (workspace[15] & 0xf); 04225 if (option_debug && iaxdebug) 04226 ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]); 04227 if (*datalen < padding + sizeof(struct ast_iax2_full_hdr)) 04228 return -1; 04229 04230 *datalen -= padding; 04231 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04232 f->frametype = fh->type; 04233 if (f->frametype == AST_FRAME_VIDEO) { 04234 f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 04235 } else { 04236 f->subclass = uncompress_subclass(fh->csub); 04237 } 04238 } else { 04239 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04240 if (option_debug && iaxdebug) 04241 ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen); 04242 if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr)) 04243 return -1; 04244 /* Decrypt */ 04245 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx); 04246 padding = 16 + (workspace[15] & 0x0f); 04247 if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr)) 04248 return -1; 04249 *datalen -= padding; 04250 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04251 } 04252 return 0; 04253 }
static int decrypt_frame | ( | int | callno, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4296 of file chan_iax2.c.
References ast_set_flag, ast_strdupa, ast_test_flag, build_enc_keys(), decode_frame(), f, IAX_KEYPOPULATED, iaxs, md5(), MD5Final(), MD5Init(), MD5Update(), secret, and strsep().
Referenced by socket_process().
04297 { 04298 int res=-1; 04299 if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) { 04300 /* Search for possible keys, given secrets */ 04301 struct MD5Context md5; 04302 unsigned char digest[16]; 04303 char *tmppw, *stringp; 04304 04305 tmppw = ast_strdupa(iaxs[callno]->secret); 04306 stringp = tmppw; 04307 while ((tmppw = strsep(&stringp, ";"))) { 04308 MD5Init(&md5); 04309 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 04310 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 04311 MD5Final(digest, &md5); 04312 build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx); 04313 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04314 if (!res) { 04315 ast_set_flag(iaxs[callno], IAX_KEYPOPULATED); 04316 break; 04317 } 04318 } 04319 } else 04320 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04321 return res; 04322 }
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 6894 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().
06895 { 06896 struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf; 06897 struct ast_iax2_full_hdr *fh, *cur_fh; 06898 06899 if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len))) 06900 return; 06901 06902 pkt_buf->len = from_here->buf_len; 06903 memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len); 06904 06905 fh = (struct ast_iax2_full_hdr *) pkt_buf->buf; 06906 ast_mutex_lock(&to_here->lock); 06907 AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) { 06908 cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf; 06909 if (fh->oseqno < cur_fh->oseqno) { 06910 AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry); 06911 break; 06912 } 06913 } 06914 AST_LIST_TRAVERSE_SAFE_END 06915 06916 if (!cur_pkt_buf) 06917 AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry); 06918 06919 ast_mutex_unlock(&to_here->lock); 06920 }
static void delete_users | ( | void | ) | [static] |
Definition at line 9812 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, sched, user_delme_cb(), and users.
09813 { 09814 struct iax2_registry *reg; 09815 09816 ao2_callback(users, 0, user_delme_cb, NULL); 09817 09818 AST_LIST_LOCK(®istrations); 09819 while ((reg = AST_LIST_REMOVE_HEAD(®istrations, entry))) { 09820 ast_sched_del(sched, reg->expire); 09821 if (reg->callno) { 09822 int callno = reg->callno; 09823 ast_mutex_lock(&iaxsl[callno]); 09824 if (iaxs[callno]) { 09825 iaxs[callno]->reg = NULL; 09826 iax2_destroy(callno); 09827 } 09828 ast_mutex_unlock(&iaxsl[callno]); 09829 } 09830 if (reg->dnsmgr) 09831 ast_dnsmgr_release(reg->dnsmgr); 09832 free(reg); 09833 } 09834 AST_LIST_UNLOCK(®istrations); 09835 09836 ao2_callback(peers, 0, peer_delme_cb, NULL); 09837 }
static void destroy_firmware | ( | struct iax_firmware * | cur | ) | [static] |
Definition at line 1783 of file chan_iax2.c.
References ast_iax2_firmware_header::datalen, iax_firmware::fd, free, and iax_firmware::fwh.
Referenced by reload_firmware().
01784 { 01785 /* Close firmware */ 01786 if (cur->fwh) { 01787 munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh))); 01788 } 01789 close(cur->fd); 01790 free(cur); 01791 }
static void dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid, | |||
int | skiplock | |||
) | [static] |
Definition at line 6666 of file chan_iax2.c.
References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_IAX, ast_ignore_pattern(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), IAX_COMMAND_DPREP, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_NUMBER, IAX_IE_DPSTATUS, IAX_IE_REFRESH, iaxs, iaxsl, and send_command().
Referenced by dp_lookup_thread(), and socket_process().
06667 { 06668 unsigned short dpstatus = 0; 06669 struct iax_ie_data ied1; 06670 int mm; 06671 06672 memset(&ied1, 0, sizeof(ied1)); 06673 mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); 06674 /* Must be started */ 06675 if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) { 06676 dpstatus = IAX_DPSTATUS_EXISTS; 06677 } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { 06678 dpstatus = IAX_DPSTATUS_CANEXIST; 06679 } else { 06680 dpstatus = IAX_DPSTATUS_NONEXISTENT; 06681 } 06682 if (ast_ignore_pattern(context, callednum)) 06683 dpstatus |= IAX_DPSTATUS_IGNOREPAT; 06684 if (mm) 06685 dpstatus |= IAX_DPSTATUS_MATCHMORE; 06686 if (!skiplock) 06687 ast_mutex_lock(&iaxsl[callno]); 06688 if (iaxs[callno]) { 06689 iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); 06690 iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); 06691 iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); 06692 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); 06693 } 06694 if (!skiplock) 06695 ast_mutex_unlock(&iaxsl[callno]); 06696 }
static void* dp_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 6698 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().
06699 { 06700 /* Look up for dpreq */ 06701 struct dpreq_data *dpr = data; 06702 dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0); 06703 if (dpr->callerid) 06704 free(dpr->callerid); 06705 free(dpr); 06706 return NULL; 06707 }
static int encrypt_frame | ( | aes_encrypt_ctx * | ecx, | |
struct ast_iax2_full_hdr * | fh, | |||
unsigned char * | poo, | |||
int * | datalen | |||
) | [static] |
Definition at line 4255 of file chan_iax2.c.
References ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, memcpy_encrypt(), option_debug, ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.
Referenced by iax2_send().
04256 { 04257 int padding; 04258 unsigned char *workspace; 04259 workspace = alloca(*datalen + 32); 04260 if (!workspace) 04261 return -1; 04262 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04263 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04264 if (option_debug && iaxdebug) 04265 ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen); 04266 padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16); 04267 padding = 16 + (padding & 0xf); 04268 memcpy(workspace, poo, padding); 04269 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04270 workspace[15] &= 0xf0; 04271 workspace[15] |= (padding & 0xf); 04272 if (option_debug && iaxdebug) 04273 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]); 04274 *datalen += padding; 04275 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx); 04276 if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr)) 04277 memcpy(poo, workspace + *datalen - 32, 32); 04278 } else { 04279 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04280 if (option_debug && iaxdebug) 04281 ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen); 04282 padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16); 04283 padding = 16 + (padding & 0xf); 04284 memcpy(workspace, poo, padding); 04285 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04286 workspace[15] &= 0xf0; 04287 workspace[15] |= (padding & 0x0f); 04288 *datalen += padding; 04289 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx); 04290 if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr)) 04291 memcpy(poo, workspace + *datalen - 32, 32); 04292 } 04293 return 0; 04294 }
static int expire_registry | ( | const void * | data | ) | [static] |
Definition at line 6115 of file chan_iax2.c.
References __expire_registry(), and schedule_action.
Referenced by iax2_prune_realtime(), reg_source_db(), and update_registry().
06116 { 06117 #ifdef SCHED_MULTITHREADED 06118 if (schedule_action(__expire_registry, data)) 06119 #endif 06120 __expire_registry(data); 06121 return 0; 06122 }
static struct iax2_dpcache* find_cache | ( | struct ast_channel * | chan, | |
const char * | data, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) | [static] |
Definition at line 10371 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, 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().
10372 { 10373 struct iax2_dpcache *dp, *prev = NULL, *next; 10374 struct timeval tv; 10375 int x; 10376 int com[2]; 10377 int timeout; 10378 int old=0; 10379 int outfd; 10380 int abort; 10381 int callno; 10382 struct ast_channel *c; 10383 struct ast_frame *f; 10384 gettimeofday(&tv, NULL); 10385 dp = dpcache; 10386 while(dp) { 10387 next = dp->next; 10388 /* Expire old caches */ 10389 if (ast_tvcmp(tv, dp->expiry) > 0) { 10390 /* It's expired, let it disappear */ 10391 if (prev) 10392 prev->next = dp->next; 10393 else 10394 dpcache = dp->next; 10395 if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) { 10396 /* Free memory and go again */ 10397 free(dp); 10398 } else { 10399 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); 10400 } 10401 dp = next; 10402 continue; 10403 } 10404 /* We found an entry that matches us! */ 10405 if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 10406 break; 10407 prev = dp; 10408 dp = next; 10409 } 10410 if (!dp) { 10411 /* No matching entry. Create a new one. */ 10412 /* First, can we make a callno? */ 10413 callno = cache_get_callno_locked(data); 10414 if (callno < 0) { 10415 ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data); 10416 return NULL; 10417 } 10418 if (!(dp = ast_calloc(1, sizeof(*dp)))) { 10419 ast_mutex_unlock(&iaxsl[callno]); 10420 return NULL; 10421 } 10422 ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext)); 10423 ast_copy_string(dp->exten, exten, sizeof(dp->exten)); 10424 gettimeofday(&dp->expiry, NULL); 10425 dp->orig = dp->expiry; 10426 /* Expires in 30 mins by default */ 10427 dp->expiry.tv_sec += iaxdefaultdpcache; 10428 dp->next = dpcache; 10429 dp->flags = CACHE_FLAG_PENDING; 10430 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 10431 dp->waiters[x] = -1; 10432 dpcache = dp; 10433 dp->peer = iaxs[callno]->dpentries; 10434 iaxs[callno]->dpentries = dp; 10435 /* Send the request if we're already up */ 10436 if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 10437 iax2_dprequest(dp, callno); 10438 ast_mutex_unlock(&iaxsl[callno]); 10439 } 10440 /* By here we must have a dp */ 10441 if (dp->flags & CACHE_FLAG_PENDING) { 10442 /* Okay, here it starts to get nasty. We need a pipe now to wait 10443 for a reply to come back so long as it's pending */ 10444 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) { 10445 /* Find an empty slot */ 10446 if (dp->waiters[x] < 0) 10447 break; 10448 } 10449 if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) { 10450 ast_log(LOG_WARNING, "No more waiter positions available\n"); 10451 return NULL; 10452 } 10453 if (pipe(com)) { 10454 ast_log(LOG_WARNING, "Unable to create pipe for comm\n"); 10455 return NULL; 10456 } 10457 dp->waiters[x] = com[1]; 10458 /* Okay, now we wait */ 10459 timeout = iaxdefaulttimeout * 1000; 10460 /* Temporarily unlock */ 10461 ast_mutex_unlock(&dpcache_lock); 10462 /* Defer any dtmf */ 10463 if (chan) 10464 old = ast_channel_defer_dtmf(chan); 10465 abort = 0; 10466 while(timeout) { 10467 c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout); 10468 if (outfd > -1) { 10469 break; 10470 } 10471 if (c) { 10472 f = ast_read(c); 10473 if (f) 10474 ast_frfree(f); 10475 else { 10476 /* Got hung up on, abort! */ 10477 break; 10478 abort = 1; 10479 } 10480 } 10481 } 10482 if (!timeout) { 10483 ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten); 10484 } 10485 ast_mutex_lock(&dpcache_lock); 10486 dp->waiters[x] = -1; 10487 close(com[1]); 10488 close(com[0]); 10489 if (abort) { 10490 /* Don't interpret anything, just abort. Not sure what th epoint 10491 of undeferring dtmf on a hung up channel is but hey whatever */ 10492 if (!old && chan) 10493 ast_channel_undefer_dtmf(chan); 10494 return NULL; 10495 } 10496 if (!(dp->flags & CACHE_FLAG_TIMEOUT)) { 10497 /* Now to do non-independent analysis the results of our wait */ 10498 if (dp->flags & CACHE_FLAG_PENDING) { 10499 /* Still pending... It's a timeout. Wake everybody up. Consider it no longer 10500 pending. Don't let it take as long to timeout. */ 10501 dp->flags &= ~CACHE_FLAG_PENDING; 10502 dp->flags |= CACHE_FLAG_TIMEOUT; 10503 /* Expire after only 60 seconds now. This is designed to help reduce backlog in heavily loaded 10504 systems without leaving it unavailable once the server comes back online */ 10505 dp->expiry.tv_sec = dp->orig.tv_sec + 60; 10506 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 10507 if (dp->waiters[x] > -1) 10508 write(dp->waiters[x], "asdf", 4); 10509 } 10510 } 10511 /* Our caller will obtain the rest */ 10512 if (!old && chan) 10513 ast_channel_undefer_dtmf(chan); 10514 } 10515 return dp; 10516 }
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 1683 of file chan_iax2.c.
References __find_callno().
Referenced by iax2_poke_peer(), and socket_process().
01683 { 01684 01685 return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame); 01686 }
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 1688 of file chan_iax2.c.
References __find_callno().
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_provision(), iax2_request(), and socket_process().
01688 { 01689 01690 return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame); 01691 }
static struct iax2_thread* find_idle_thread | ( | void | ) | [static] |
Definition at line 907 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_init(), ast_pthread_create, free, iax2_process_thread(), IAX_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxdynamicthreadnum, iaxmaxthreadcount, and thread.
Referenced by __schedule_action(), and socket_read().
00908 { 00909 pthread_attr_t attr; 00910 struct iax2_thread *thread = NULL; 00911 00912 /* Pop the head of the list off */ 00913 AST_LIST_LOCK(&idle_list); 00914 thread = AST_LIST_REMOVE_HEAD(&idle_list, list); 00915 AST_LIST_UNLOCK(&idle_list); 00916 00917 /* If no idle thread is available from the regular list, try dynamic */ 00918 if (thread == NULL) { 00919 AST_LIST_LOCK(&dynamic_list); 00920 thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list); 00921 /* Make sure we absolutely have a thread... if not, try to make one if allowed */ 00922 if (thread == NULL && iaxmaxthreadcount > iaxdynamicthreadcount) { 00923 /* We need to MAKE a thread! */ 00924 if ((thread = ast_calloc(1, sizeof(*thread)))) { 00925 thread->threadnum = iaxdynamicthreadnum++; 00926 thread->type = IAX_TYPE_DYNAMIC; 00927 ast_mutex_init(&thread->lock); 00928 ast_cond_init(&thread->cond, NULL); 00929 pthread_attr_init(&attr); 00930 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00931 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 00932 free(thread); 00933 thread = NULL; 00934 } else { 00935 /* All went well and the thread is up, so increment our count */ 00936 iaxdynamicthreadcount++; 00937 00938 /* Wait for the thread to be ready before returning it to the caller */ 00939 while (!thread->ready_for_signal) 00940 usleep(1); 00941 } 00942 } 00943 } 00944 AST_LIST_UNLOCK(&dynamic_list); 00945 } 00946 00947 /* this thread is not processing a full frame (since it is idle), 00948 so ensure that the field for the full frame call number is empty */ 00949 if (thread) 00950 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 00951 00952 return thread; 00953 }
static struct iax2_peer* find_peer | ( | const char * | name, | |
int | realtime | |||
) | [static] |
Definition at line 1150 of file chan_iax2.c.
References ao2_find(), peers, and realtime_peer().
01151 { 01152 struct iax2_peer *peer = NULL; 01153 struct iax2_peer tmp_peer = { 01154 .name = name, 01155 }; 01156 01157 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 01158 01159 /* Now go for realtime if applicable */ 01160 if(!peer && realtime) 01161 peer = realtime_peer(name, NULL); 01162 01163 return peer; 01164 }
static struct iax2_trunk_peer* find_tpeer | ( | struct sockaddr_in * | sin, | |
int | fd | |||
) | [static] |
Definition at line 4064 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_mutex_lock(), inaddrcmp(), iax2_trunk_peer::lock, iax2_trunk_peer::next, and tpeers.
Referenced by iax2_trunk_queue(), and socket_process().
04065 { 04066 struct iax2_trunk_peer *tpeer; 04067 04068 /* Finds and locks trunk peer */ 04069 ast_mutex_lock(&tpeerlock); 04070 for (tpeer = tpeers; tpeer; tpeer = tpeer->next) { 04071 /* We don't lock here because tpeer->addr *never* changes */ 04072 if (!inaddrcmp(&tpeer->addr, sin)) { 04073 ast_mutex_lock(&tpeer->lock); 04074 break; 04075 } 04076 } 04077 if (!tpeer) { 04078 if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) { 04079 ast_mutex_init(&tpeer->lock); 04080 tpeer->lastsent = 9999; 04081 memcpy(&tpeer->addr, sin, sizeof(tpeer->addr)); 04082 tpeer->trunkact = ast_tvnow(); 04083 ast_mutex_lock(&tpeer->lock); 04084 tpeer->next = tpeers; 04085 tpeer->sockfd = fd; 04086 tpeers = tpeer; 04087 #ifdef SO_NO_CHECK 04088 setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 04089 #endif 04090 if (option_debug) 04091 ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 04092 } 04093 } 04094 ast_mutex_unlock(&tpeerlock); 04095 return tpeer; 04096 }
static unsigned int fix_peerts | ( | struct timeval * | tv, | |
int | callno, | |||
unsigned int | ts | |||
) | [static] |
Definition at line 3880 of file chan_iax2.c.
References iaxs, and chan_iax2_pvt::rxcore.
Referenced by socket_process().
03881 { 03882 long ms; /* NOT unsigned */ 03883 if (ast_tvzero(iaxs[callno]->rxcore)) { 03884 /* Initialize rxcore time if appropriate */ 03885 gettimeofday(&iaxs[callno]->rxcore, NULL); 03886 /* Round to nearest 20ms so traces look pretty */ 03887 iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000; 03888 } 03889 /* Calculate difference between trunk and channel */ 03890 ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore); 03891 /* Return as the sum of trunk time and the difference between trunk and real time */ 03892 return ms + ts; 03893 }
static void free_context | ( | struct iax2_context * | con | ) | [static] |
Definition at line 8988 of file chan_iax2.c.
References free, and iax2_context::next.
Referenced by build_user(), and user_destructor().
08989 { 08990 struct iax2_context *conl; 08991 while(con) { 08992 conl = con; 08993 con = con->next; 08994 free(conl); 08995 } 08996 }
static int function_iaxpeer | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 10640 of file chan_iax2.c.
References iax2_peer::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_peer::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.
10641 { 10642 struct iax2_peer *peer; 10643 char *peername, *colname; 10644 10645 peername = ast_strdupa(data); 10646 10647 /* if our channel, return the IP address of the endpoint of current channel */ 10648 if (!strcmp(peername,"CURRENTCHANNEL")) { 10649 unsigned short callno; 10650 if (chan->tech != &iax2_tech) 10651 return -1; 10652 callno = PTR_TO_CALLNO(chan->tech_pvt); 10653 ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len); 10654 return 0; 10655 } 10656 10657 if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */ 10658 *colname++ = '\0'; 10659 else if ((colname = strchr(peername, '|'))) 10660 *colname++ = '\0'; 10661 else 10662 colname = "ip"; 10663 10664 if (!(peer = find_peer(peername, 1))) 10665 return -1; 10666 10667 if (!strcasecmp(colname, "ip")) { 10668 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 10669 } else if (!strcasecmp(colname, "status")) { 10670 peer_status(peer, buf, len); 10671 } else if (!strcasecmp(colname, "mailbox")) { 10672 ast_copy_string(buf, peer->mailbox, len); 10673 } else if (!strcasecmp(colname, "context")) { 10674 ast_copy_string(buf, peer->context, len); 10675 } else if (!strcasecmp(colname, "expire")) { 10676 snprintf(buf, len, "%d", peer->expire); 10677 } else if (!strcasecmp(colname, "dynamic")) { 10678 ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len); 10679 } else if (!strcasecmp(colname, "callerid_name")) { 10680 ast_copy_string(buf, peer->cid_name, len); 10681 } else if (!strcasecmp(colname, "callerid_num")) { 10682 ast_copy_string(buf, peer->cid_num, len); 10683 } else if (!strcasecmp(colname, "codecs")) { 10684 ast_getformatname_multiple(buf, len -1, peer->capability); 10685 } else if (!strncasecmp(colname, "codec[", 6)) { 10686 char *codecnum, *ptr; 10687 int index = 0, codec = 0; 10688 10689 codecnum = strchr(colname, '['); 10690 *codecnum = '\0'; 10691 codecnum++; 10692 if ((ptr = strchr(codecnum, ']'))) { 10693 *ptr = '\0'; 10694 } 10695 index = atoi(codecnum); 10696 if((codec = ast_codec_pref_index(&peer->prefs, index))) { 10697 ast_copy_string(buf, ast_getformatname(codec), len); 10698 } 10699 } 10700 10701 peer_unref(peer); 10702 10703 return 0; 10704 }
static int get_auth_methods | ( | char * | value | ) | [static] |
Definition at line 9212 of file chan_iax2.c.
References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.
Referenced by build_peer(), and build_user().
09213 { 09214 int methods = 0; 09215 if (strstr(value, "rsa")) 09216 methods |= IAX_AUTH_RSA; 09217 if (strstr(value, "md5")) 09218 methods |= IAX_AUTH_MD5; 09219 if (strstr(value, "plaintext")) 09220 methods |= IAX_AUTH_PLAINTEXT; 09221 return methods; 09222 }
static int get_encrypt_methods | ( | const char * | s | ) | [static] |
Definition at line 1027 of file chan_iax2.c.
References ast_true(), and IAX_ENCRYPT_AES128.
Referenced by build_peer(), build_user(), and set_config().
01028 { 01029 int e; 01030 if (!strcasecmp(s, "aes128")) 01031 e = IAX_ENCRYPT_AES128; 01032 else if (ast_true(s)) 01033 e = IAX_ENCRYPT_AES128; 01034 else 01035 e = 0; 01036 return e; 01037 }
static int get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 2669 of file chan_iax2.c.
References __get_from_jb(), and schedule_action.
Referenced by update_jbsched().
02670 { 02671 #ifdef SCHED_MULTITHREADED 02672 if (schedule_action(__get_from_jb, data)) 02673 #endif 02674 __get_from_jb(data); 02675 return 0; 02676 }
static void handle_deferred_full_frames | ( | struct iax2_thread * | thread | ) | [static] |
Handle any deferred full frames for this thread.
Definition at line 6864 of file chan_iax2.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), socket_process(), and thread.
06865 { 06866 struct iax2_pkt_buf *pkt_buf; 06867 06868 ast_mutex_lock(&thread->lock); 06869 06870 while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) { 06871 ast_mutex_unlock(&thread->lock); 06872 06873 thread->buf = pkt_buf->buf; 06874 thread->buf_len = pkt_buf->len; 06875 thread->buf_size = pkt_buf->len + 1; 06876 06877 socket_process(thread); 06878 06879 thread->buf = NULL; 06880 ast_free(pkt_buf); 06881 06882 ast_mutex_lock(&thread->lock); 06883 } 06884 06885 ast_mutex_unlock(&thread->lock); 06886 }
static int handle_error | ( | void | ) | [static] |
Definition at line 2071 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().
02072 { 02073 /* XXX Ideally we should figure out why an error occured and then abort those 02074 rather than continuing to try. Unfortunately, the published interface does 02075 not seem to work XXX */ 02076 #if 0 02077 struct sockaddr_in *sin; 02078 int res; 02079 struct msghdr m; 02080 struct sock_extended_err e; 02081 m.msg_name = NULL; 02082 m.msg_namelen = 0; 02083 m.msg_iov = NULL; 02084 m.msg_control = &e; 02085 m.msg_controllen = sizeof(e); 02086 m.msg_flags = 0; 02087 res = recvmsg(netsocket, &m, MSG_ERRQUEUE); 02088 if (res < 0) 02089 ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno)); 02090 else { 02091 if (m.msg_controllen) { 02092 sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e); 02093 if (sin) 02094 ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr)); 02095 else 02096 ast_log(LOG_WARNING, "No address detected??\n"); 02097 } else { 02098 ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno)); 02099 } 02100 } 02101 #endif 02102 return 0; 02103 }
static int iax2_ack_registry | ( | struct iax_ies * | ies, | |
struct sockaddr_in * | sin, | |||
int | callno | |||
) | [static] |
Acknowledgment received for OUR registration.
Definition at line 5936 of file chan_iax2.c.
References iax2_registry::addr, ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, ast_verbose(), EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_add(), iaxs, ies, inaddrcmp(), LOG_WARNING, manager_event(), iax2_registry::messages, option_verbose, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGISTERED, iax2_registry::regstate, sched, iax2_registry::us, and VERBOSE_PREFIX_3.
Referenced by socket_process().
05937 { 05938 struct iax2_registry *reg; 05939 /* Start pessimistic */ 05940 char peer[256] = ""; 05941 char msgstatus[60]; 05942 int refresh = 60; 05943 char ourip[256] = "<Unspecified>"; 05944 struct sockaddr_in oldus; 05945 struct sockaddr_in us; 05946 int oldmsgs; 05947 05948 memset(&us, 0, sizeof(us)); 05949 if (ies->apparent_addr) 05950 bcopy(ies->apparent_addr, &us, sizeof(us)); 05951 if (ies->username) 05952 ast_copy_string(peer, ies->username, sizeof(peer)); 05953 if (ies->refresh) 05954 refresh = ies->refresh; 05955 if (ies->calling_number) { 05956 /* We don't do anything with it really, but maybe we should */ 05957 } 05958 reg = iaxs[callno]->reg; 05959 if (!reg) { 05960 ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer); 05961 return -1; 05962 } 05963 memcpy(&oldus, ®->us, sizeof(oldus)); 05964 oldmsgs = reg->messages; 05965 if (inaddrcmp(®->addr, sin)) { 05966 ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 05967 return -1; 05968 } 05969 memcpy(®->us, &us, sizeof(reg->us)); 05970 if (ies->msgcount >= 0) 05971 reg->messages = ies->msgcount & 0xffff; /* only low 16 bits are used in the transmission of the IE */ 05972 /* always refresh the registration at the interval requested by the server 05973 we are registering to 05974 */ 05975 reg->refresh = refresh; 05976 AST_SCHED_DEL(sched, reg->expire); 05977 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 05978 if (inaddrcmp(&oldus, ®->us) || (reg->messages != oldmsgs)) { 05979 if (option_verbose > 2) { 05980 if (reg->messages > 255) 05981 snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8); 05982 else if (reg->messages > 1) 05983 snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages); 05984 else if (reg->messages > 0) 05985 snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n"); 05986 else 05987 snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n"); 05988 snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 05989 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); 05990 } 05991 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); 05992 } 05993 reg->regstate = REG_STATE_REGISTERED; 05994 return 0; 05995 }
static int iax2_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3678 of file chan_iax2.c.
References AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_log(), option_debug, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03679 { 03680 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03681 if (option_debug) 03682 ast_log(LOG_DEBUG, "Answering IAX2 call\n"); 03683 return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); 03684 }
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 3528 of file chan_iax2.c.
References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), chan_iax2_pvt::bridgecallno, f, iax2_tech, iaxs, iaxsl, lock_both(), option_verbose, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, tv, unlock_both(), and VERBOSE_PREFIX_3.
03529 { 03530 struct ast_channel *cs[3]; 03531 struct ast_channel *who, *other; 03532 int to = -1; 03533 int res = -1; 03534 int transferstarted=0; 03535 struct ast_frame *f; 03536 unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt); 03537 unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt); 03538 struct timeval waittimer = {0, 0}, tv; 03539 03540 lock_both(callno0, callno1); 03541 if (!iaxs[callno0] || !iaxs[callno1]) { 03542 unlock_both(callno0, callno1); 03543 return AST_BRIDGE_FAILED; 03544 } 03545 /* Put them in native bridge mode */ 03546 if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) { 03547 iaxs[callno0]->bridgecallno = callno1; 03548 iaxs[callno1]->bridgecallno = callno0; 03549 } 03550 unlock_both(callno0, callno1); 03551 03552 /* If not, try to bridge until we can execute a transfer, if we can */ 03553 cs[0] = c0; 03554 cs[1] = c1; 03555 for (/* ever */;;) { 03556 /* Check in case we got masqueraded into */ 03557 if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) { 03558 if (option_verbose > 2) 03559 ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n"); 03560 /* Remove from native mode */ 03561 if (c0->tech == &iax2_tech) { 03562 ast_mutex_lock(&iaxsl[callno0]); 03563 iaxs[callno0]->bridgecallno = 0; 03564 ast_mutex_unlock(&iaxsl[callno0]); 03565 } 03566 if (c1->tech == &iax2_tech) { 03567 ast_mutex_lock(&iaxsl[callno1]); 03568 iaxs[callno1]->bridgecallno = 0; 03569 ast_mutex_unlock(&iaxsl[callno1]); 03570 } 03571 return AST_BRIDGE_FAILED_NOWARN; 03572 } 03573 if (c0->nativeformats != c1->nativeformats) { 03574 if (option_verbose > 2) { 03575 char buf0[255]; 03576 char buf1[255]; 03577 ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats); 03578 ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats); 03579 ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1); 03580 } 03581 /* Remove from native mode */ 03582 lock_both(callno0, callno1); 03583 if (iaxs[callno0]) 03584 iaxs[callno0]->bridgecallno = 0; 03585 if (iaxs[callno1]) 03586 iaxs[callno1]->bridgecallno = 0; 03587 unlock_both(callno0, callno1); 03588 return AST_BRIDGE_FAILED_NOWARN; 03589 } 03590 /* check if transfered and if we really want native bridging */ 03591 if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) { 03592 /* Try the transfer */ 03593 if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) || 03594 ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA))) 03595 ast_log(LOG_WARNING, "Unable to start the transfer\n"); 03596 transferstarted = 1; 03597 } 03598 if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) { 03599 /* Call has been transferred. We're no longer involved */ 03600 gettimeofday(&tv, NULL); 03601 if (ast_tvzero(waittimer)) { 03602 waittimer = tv; 03603 } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { 03604 c0->_softhangup |= AST_SOFTHANGUP_DEV; 03605 c1->_softhangup |= AST_SOFTHANGUP_DEV; 03606 *fo = NULL; 03607 *rc = c0; 03608 res = AST_BRIDGE_COMPLETE; 03609 break; 03610 } 03611 } 03612 to = 1000; 03613 who = ast_waitfor_n(cs, 2, &to); 03614 if (timeoutms > -1) { 03615 timeoutms -= (1000 - to); 03616 if (timeoutms < 0) 03617 timeoutms = 0; 03618 } 03619 if (!who) { 03620 if (!timeoutms) { 03621 res = AST_BRIDGE_RETRY; 03622 break; 03623 } 03624 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03625 res = AST_BRIDGE_FAILED; 03626 break; 03627 } 03628 continue; 03629 } 03630 f = ast_read(who); 03631 if (!f) { 03632 *fo = NULL; 03633 *rc = who; 03634 res = AST_BRIDGE_COMPLETE; 03635 break; 03636 } 03637 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03638 *fo = f; 03639 *rc = who; 03640 res = AST_BRIDGE_COMPLETE; 03641 break; 03642 } 03643 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 03644 if ((f->frametype == AST_FRAME_VOICE) || 03645 (f->frametype == AST_FRAME_TEXT) || 03646 (f->frametype == AST_FRAME_VIDEO) || 03647 (f->frametype == AST_FRAME_IMAGE) || 03648 (f->frametype == AST_FRAME_DTMF)) { 03649 /* monitored dtmf take out of the bridge. 03650 * check if we monitor the specific source. 03651 */ 03652 int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1; 03653 if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) { 03654 *rc = who; 03655 *fo = f; 03656 res = AST_BRIDGE_COMPLETE; 03657 /* Remove from native mode */ 03658 break; 03659 } 03660 /* everything else goes to the other side */ 03661 ast_write(other, f); 03662 } 03663 ast_frfree(f); 03664 /* Swap who gets priority */ 03665 cs[2] = cs[0]; 03666 cs[0] = cs[1]; 03667 cs[1] = cs[2]; 03668 } 03669 lock_both(callno0, callno1); 03670 if(iaxs[callno0]) 03671 iaxs[callno0]->bridgecallno = 0; 03672 if(iaxs[callno1]) 03673 iaxs[callno1]->bridgecallno = 0; 03674 unlock_both(callno0, callno1); 03675 return res; 03676 }
static int iax2_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 3269 of file chan_iax2.c.
References ast_channel::_state, 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(), CALLNO_TO_PTR, capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, create_addr(), chan_iax2_pvt::encmethods, iax2_datetime(), iax2_sched_add(), IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, IAX_SENDANI, iaxs, iaxsl, chan_iax2_pvt::initid, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::maxtime, ast_channel::nativeformats, create_addr_info::outkey, parse_dial_string(), chan_iax2_pvt::pingtime, PTR_TO_CALLNO, sched, secret, send_command(), chan_iax2_pvt::sockfd, and ast_channel::tech_pvt.
03270 { 03271 struct sockaddr_in sin; 03272 char *l=NULL, *n=NULL, *tmpstr; 03273 struct iax_ie_data ied; 03274 char *defaultrdest = "s"; 03275 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03276 struct parsed_dial_string pds; 03277 struct create_addr_info cai; 03278 03279 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 03280 ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); 03281 return -1; 03282 } 03283 03284 memset(&cai, 0, sizeof(cai)); 03285 cai.encmethods = iax2_encryption; 03286 03287 memset(&pds, 0, sizeof(pds)); 03288 tmpstr = ast_strdupa(dest); 03289 parse_dial_string(tmpstr, &pds); 03290 03291 if (ast_strlen_zero(pds.peer)) { 03292 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest); 03293 return -1; 03294 } 03295 03296 if (!pds.exten) { 03297 pds.exten = defaultrdest; 03298 } 03299 03300 if (create_addr(pds.peer, c, &sin, &cai)) { 03301 ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); 03302 return -1; 03303 } 03304 03305 if (!pds.username && !ast_strlen_zero(cai.username)) 03306 pds.username = cai.username; 03307 if (!pds.password && !ast_strlen_zero(cai.secret)) 03308 pds.password = cai.secret; 03309 if (!pds.key && !ast_strlen_zero(cai.outkey)) 03310 pds.key = cai.outkey; 03311 if (!pds.context && !ast_strlen_zero(cai.peercontext)) 03312 pds.context = cai.peercontext; 03313 03314 /* Keep track of the context for outgoing calls too */ 03315 ast_copy_string(c->context, cai.context, sizeof(c->context)); 03316 03317 if (pds.port) 03318 sin.sin_port = htons(atoi(pds.port)); 03319 03320 l = c->cid.cid_num; 03321 n = c->cid.cid_name; 03322 03323 /* Now build request */ 03324 memset(&ied, 0, sizeof(ied)); 03325 03326 /* On new call, first IE MUST be IAX version of caller */ 03327 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 03328 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); 03329 if (pds.options && strchr(pds.options, 'a')) { 03330 /* Request auto answer */ 03331 iax_ie_append(&ied, IAX_IE_AUTOANSWER); 03332 } 03333 03334 iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); 03335 03336 if (l) { 03337 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); 03338 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03339 } else { 03340 if (n) 03341 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03342 else 03343 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); 03344 } 03345 03346 iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); 03347 iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); 03348 03349 if (n) 03350 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); 03351 if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) 03352 iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); 03353 03354 if (!ast_strlen_zero(c->language)) 03355 iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); 03356 if (!ast_strlen_zero(c->cid.cid_dnid)) 03357 iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); 03358 if (!ast_strlen_zero(c->cid.cid_rdnis)) 03359 iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis); 03360 03361 if (pds.context) 03362 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); 03363 03364 if (pds.username) 03365 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 03366 03367 if (cai.encmethods) 03368 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); 03369 03370 ast_mutex_lock(&iaxsl[callno]); 03371 03372 if (!ast_strlen_zero(c->context)) 03373 ast_string_field_set(iaxs[callno], context, c->context); 03374 03375 if (pds.username) 03376 ast_string_field_set(iaxs[callno], username, pds.username); 03377 03378 iaxs[callno]->encmethods = cai.encmethods; 03379 03380 iaxs[callno]->adsi = cai.adsi; 03381 03382 ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret); 03383 ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest); 03384 03385 if (pds.key) 03386 ast_string_field_set(iaxs[callno], outkey, pds.key); 03387 if (pds.password) 03388 ast_string_field_set(iaxs[callno], secret, pds.password); 03389 03390 iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); 03391 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); 03392 iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); 03393 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); 03394 03395 if (iaxs[callno]->maxtime) { 03396 /* Initialize pingtime and auto-congest time */ 03397 iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; 03398 iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno)); 03399 } else if (autokill) { 03400 iaxs[callno]->pingtime = autokill / 2; 03401 iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); 03402 } 03403 03404 /* send the command using the appropriate socket for this peer */ 03405 iaxs[callno]->sockfd = cai.sockfd; 03406 03407 /* Transmit the string in a "NEW" request */ 03408 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 03409 03410 ast_mutex_unlock(&iaxsl[callno]); 03411 ast_setstate(c, AST_STATE_RINGING); 03412 03413 return 0; 03414 }
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 10542 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.
10543 { 10544 int res = 0; 10545 struct iax2_dpcache *dp; 10546 #if 0 10547 ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10548 #endif 10549 if ((priority != 1) && (priority != 2)) 10550 return 0; 10551 ast_mutex_lock(&dpcache_lock); 10552 dp = find_cache(chan, data, context, exten, priority); 10553 if (dp) { 10554 if (dp->flags & CACHE_FLAG_CANEXIST) 10555 res= 1; 10556 } 10557 ast_mutex_unlock(&dpcache_lock); 10558 if (!dp) { 10559 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10560 } 10561 return res; 10562 }
static unsigned int iax2_datetime | ( | const char * | tz | ) | [static] |
Definition at line 3172 of file chan_iax2.c.
References ast_localtime(), ast_strlen_zero(), and t.
Referenced by iax2_call(), and update_registry().
03173 { 03174 time_t t; 03175 struct tm tm; 03176 unsigned int tmp; 03177 time(&t); 03178 if (!ast_strlen_zero(tz)) 03179 ast_localtime(&t, &tm, tz); 03180 else 03181 ast_localtime(&t, &tm, NULL); 03182 tmp = (tm.tm_sec >> 1) & 0x1f; /* 5 bits of seconds */ 03183 tmp |= (tm.tm_min & 0x3f) << 5; /* 6 bits of minutes */ 03184 tmp |= (tm.tm_hour & 0x1f) << 11; /* 5 bits of hours */ 03185 tmp |= (tm.tm_mday & 0x1f) << 16; /* 5 bits of day of month */ 03186 tmp |= ((tm.tm_mon + 1) & 0xf) << 21; /* 4 bits of month */ 03187 tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */ 03188 return tmp; 03189 }
static void iax2_destroy | ( | int | callno | ) | [static] |
Definition at line 1290 of file chan_iax2.c.
References ao2_ref(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), AST_SCHED_DEL_SPINLOCK, DEADLOCK_AVOIDANCE, iaxsl, ast_channel::lock, LOG_DEBUG, option_debug, chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), sched, and update_max_trunk().
Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __unload_module(), delete_users(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), peer_destructor(), and socket_process().
01291 { 01292 struct chan_iax2_pvt *pvt; 01293 struct ast_channel *owner; 01294 01295 retry: 01296 pvt = iaxs[callno]; 01297 gettimeofday(&lastused[callno], NULL); 01298 01299 owner = pvt ? pvt->owner : NULL; 01300 01301 if (owner) { 01302 if (ast_mutex_trylock(&owner->lock)) { 01303 if (option_debug > 2) 01304 ast_log(LOG_DEBUG, "Avoiding IAX destroy deadlock\n"); 01305 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01306 goto retry; 01307 } 01308 } 01309 if (!owner && iaxs[callno]) { 01310 AST_SCHED_DEL_SPINLOCK(sched, iaxs[callno]->lagid, &iaxsl[callno]); 01311 AST_SCHED_DEL_SPINLOCK(sched, iaxs[callno]->pingid, &iaxsl[callno]); 01312 iaxs[callno] = NULL; 01313 } 01314 01315 if (pvt) { 01316 if (!owner) { 01317 pvt->owner = NULL; 01318 } else { 01319 /* If there's an owner, prod it to give up */ 01320 /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup() 01321 * because we already hold the owner channel lock. */ 01322 ast_queue_hangup(owner); 01323 } 01324 01325 if (pvt->peercallno) { 01326 remove_by_peercallno(pvt); 01327 } 01328 01329 if (!owner) { 01330 ao2_ref(pvt, -1); 01331 pvt = NULL; 01332 } 01333 } 01334 01335 if (owner) { 01336 ast_mutex_unlock(&owner->lock); 01337 } 01338 01339 if (callno & 0x4000) { 01340 update_max_trunk(); 01341 } 01342 }
static void iax2_destroy_helper | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1220 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, sched, user_unref(), and users.
Referenced by iax2_predestroy(), pvt_destructor(), and stop_stuff().
01221 { 01222 /* Decrement AUTHREQ count if needed */ 01223 if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) { 01224 struct iax2_user *user; 01225 struct iax2_user tmp_user = { 01226 .name = pvt->username, 01227 }; 01228 01229 user = ao2_find(users, &tmp_user, OBJ_POINTER); 01230 if (user) { 01231 ast_atomic_fetchadd_int(&user->curauthreq, -1); 01232 user = user_unref(user); 01233 } 01234 01235 ast_clear_flag(pvt, IAX_MAXAUTHREQ); 01236 } 01237 01238 /* No more pings or lagrq's */ 01239 AST_SCHED_DEL(sched, pvt->pingid); 01240 AST_SCHED_DEL(sched, pvt->lagid); 01241 AST_SCHED_DEL(sched, pvt->autoid); 01242 AST_SCHED_DEL(sched, pvt->authid); 01243 AST_SCHED_DEL(sched, pvt->initid); 01244 AST_SCHED_DEL(sched, pvt->jbid); 01245 }
static int iax2_devicestate | ( | void * | data | ) | [static] |
Part of the device state notification system ---.
Definition at line 10729 of file chan_iax2.c.
References iax2_peer::addr, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::defaddr, find_peer(), iax2_peer::historicms, iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, option_debug, parse_dial_string(), and peer_unref().
10730 { 10731 struct parsed_dial_string pds; 10732 char *tmp = ast_strdupa(data); 10733 struct iax2_peer *p; 10734 int res = AST_DEVICE_INVALID; 10735 10736 memset(&pds, 0, sizeof(pds)); 10737 parse_dial_string(tmp, &pds); 10738 10739 if (ast_strlen_zero(pds.peer)) { 10740 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 10741 return res; 10742 } 10743 10744 if (option_debug > 2) 10745 ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer); 10746 10747 /* SLD: FIXME: second call to find_peer during registration */ 10748 if (!(p = find_peer(pds.peer, 1))) 10749 return res; 10750 10751 res = AST_DEVICE_UNAVAILABLE; 10752 if (option_debug > 2) 10753 ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", 10754 pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); 10755 10756 if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && 10757 (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { 10758 /* Peer is registered, or have default IP address 10759 and a valid registration */ 10760 if (p->historicms == 0 || p->historicms <= p->maxms) 10761 /* let the core figure out whether it is in use or not */ 10762 res = AST_DEVICE_UNKNOWN; 10763 } 10764 10765 peer_unref(p); 10766 10767 return res; 10768 }
static int iax2_digit_begin | ( | struct ast_channel * | c, | |
char | digit | |||
) | [static] |
Definition at line 2788 of file chan_iax2.c.
References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02789 { 02790 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); 02791 }
static int iax2_digit_end | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 2793 of file chan_iax2.c.
References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02794 { 02795 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); 02796 }
static int iax2_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4986 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04987 { 04988 if (argc < 2 || argc > 3) 04989 return RESULT_SHOWUSAGE; 04990 iaxdebug = 1; 04991 ast_cli(fd, "IAX2 Debugging Enabled\n"); 04992 return RESULT_SUCCESS; 04993 }
static int iax2_do_jb_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 5004 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
05005 { 05006 if (argc < 3 || argc > 4) 05007 return RESULT_SHOWUSAGE; 05008 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 05009 ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 05010 return RESULT_SUCCESS; 05011 }
static int iax2_do_register | ( | struct iax2_registry * | reg | ) | [static] |
Definition at line 8706 of file chan_iax2.c.
References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_add(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_WARNING, NEW_FORCE, option_debug, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), and iax2_registry::username.
Referenced by __iax2_do_register_s(), load_module(), and reload_config().
08707 { 08708 struct iax_ie_data ied; 08709 if (option_debug && iaxdebug) 08710 ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username); 08711 08712 if (reg->dnsmgr && 08713 ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { 08714 /* Maybe the IP has changed, force DNS refresh */ 08715 ast_dnsmgr_refresh(reg->dnsmgr); 08716 } 08717 08718 /* 08719 * if IP has Changed, free allocated call to create a new one with new IP 08720 * call has the pointer to IP and must be updated to the new one 08721 */ 08722 if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) { 08723 int callno = reg->callno; 08724 ast_mutex_lock(&iaxsl[callno]); 08725 iax2_destroy(callno); 08726 ast_mutex_unlock(&iaxsl[callno]); 08727 reg->callno = 0; 08728 } 08729 if (!reg->addr.sin_addr.s_addr) { 08730 if (option_debug && iaxdebug) 08731 ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username); 08732 /* Setup the next registration attempt */ 08733 AST_SCHED_DEL(sched, reg->expire); 08734 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 08735 return -1; 08736 } 08737 08738 if (!reg->callno) { 08739 if (option_debug) 08740 ast_log(LOG_DEBUG, "Allocate call number\n"); 08741 reg->callno = find_callno_locked(0, 0, ®->addr, NEW_FORCE, defaultsockfd, 0); 08742 if (reg->callno < 1) { 08743 ast_log(LOG_WARNING, "Unable to create call for registration\n"); 08744 return -1; 08745 } else if (option_debug) 08746 ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno); 08747 iaxs[reg->callno]->reg = reg; 08748 ast_mutex_unlock(&iaxsl[reg->callno]); 08749 } 08750 /* Schedule the next registration attempt */ 08751 AST_SCHED_DEL(sched, reg->expire); 08752 /* Setup the next registration a little early */ 08753 reg->expire = iax2_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 08754 /* Send the request */ 08755 memset(&ied, 0, sizeof(ied)); 08756 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 08757 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 08758 send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 08759 reg->regstate = REG_STATE_REGSENT; 08760 return 0; 08761 }
static int iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 5784 of file chan_iax2.c.
References __iax2_do_register_s(), and schedule_action.
Referenced by iax2_ack_registry(), and iax2_do_register().
05785 { 05786 #ifdef SCHED_MULTITHREADED 05787 if (schedule_action(__iax2_do_register_s, data)) 05788 #endif 05789 __iax2_do_register_s(data); 05790 return 0; 05791 }
static int iax2_do_trunk_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4995 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04996 { 04997 if (argc < 3 || argc > 4) 04998 return RESULT_SHOWUSAGE; 04999 iaxtrunkdebug = 1; 05000 ast_cli(fd, "IAX2 Trunk Debug Requested\n"); 05001 return RESULT_SUCCESS; 05002 }
static void iax2_dprequest | ( | struct iax2_dpcache * | dp, | |
int | callno | |||
) | [static] |
Definition at line 6475 of file chan_iax2.c.
References AST_FRAME_IAX, AST_SCHED_DEL, auto_hangup(), chan_iax2_pvt::autoid, CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_add(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, iaxs, sched, and send_command().
Referenced by find_cache(), and socket_process().
06476 { 06477 struct iax_ie_data ied; 06478 /* Auto-hangup with 30 seconds of inactivity */ 06479 AST_SCHED_DEL(sched, iaxs[callno]->autoid); 06480 iaxs[callno]->autoid = iax2_sched_add(sched, 30000, auto_hangup, (void *)(long)callno); 06481 memset(&ied, 0, sizeof(ied)); 06482 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten); 06483 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); 06484 dp->flags |= CACHE_FLAG_TRANSMITTED; 06485 }
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 10588 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.
10589 { 10590 char odata[256]; 10591 char req[256]; 10592 char *ncontext; 10593 struct iax2_dpcache *dp; 10594 struct ast_app *dial; 10595 #if 0 10596 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); 10597 #endif 10598 if (priority == 2) { 10599 /* Indicate status, can be overridden in dialplan */ 10600 const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS"); 10601 if (dialstatus) { 10602 dial = pbx_findapp(dialstatus); 10603 if (dial) 10604 pbx_exec(chan, dial, ""); 10605 } 10606 return -1; 10607 } else if (priority != 1) 10608 return -1; 10609 ast_mutex_lock(&dpcache_lock); 10610 dp = find_cache(chan, data, context, exten, priority); 10611 if (dp) { 10612 if (dp->flags & CACHE_FLAG_EXISTS) { 10613 ast_copy_string(odata, data, sizeof(odata)); 10614 ncontext = strchr(odata, '/'); 10615 if (ncontext) { 10616 *ncontext = '\0'; 10617 ncontext++; 10618 snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext); 10619 } else { 10620 snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten); 10621 } 10622 if (option_verbose > 2) 10623 ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req); 10624 } else { 10625 ast_mutex_unlock(&dpcache_lock); 10626 ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data); 10627 return -1; 10628 } 10629 } 10630 ast_mutex_unlock(&dpcache_lock); 10631 dial = pbx_findapp("Dial"); 10632 if (dial) { 10633 return pbx_exec(chan, dial, req); 10634 } else { 10635 ast_log(LOG_WARNING, "No dial application registered\n"); 10636 } 10637 return -1; 10638 }
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 10519 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.
10520 { 10521 struct iax2_dpcache *dp; 10522 int res = 0; 10523 #if 0 10524 ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10525 #endif 10526 if ((priority != 1) && (priority != 2)) 10527 return 0; 10528 ast_mutex_lock(&dpcache_lock); 10529 dp = find_cache(chan, data, context, exten, priority); 10530 if (dp) { 10531 if (dp->flags & CACHE_FLAG_EXISTS) 10532 res= 1; 10533 } 10534 ast_mutex_unlock(&dpcache_lock); 10535 if (!dp) { 10536 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10537 } 10538 return res; 10539 }
static int iax2_fixup | ( | struct ast_channel * | oldchannel, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 2815 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, LOG_WARNING, chan_iax2_pvt::owner, PTR_TO_CALLNO, and ast_channel::tech_pvt.
02816 { 02817 unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt); 02818 ast_mutex_lock(&iaxsl[callno]); 02819 if (iaxs[callno]) 02820 iaxs[callno]->owner = newchan; 02821 else 02822 ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n"); 02823 ast_mutex_unlock(&iaxsl[callno]); 02824 return 0; 02825 }
static void iax2_frame_free | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 1284 of file chan_iax2.c.
References AST_SCHED_DEL, iax_frame_free(), iax_frame::retrans, and sched.
Referenced by __attempt_transmit(), __do_deliver(), __get_from_jb(), complete_transfer(), pvt_destructor(), and schedule_delivery().
01285 { 01286 AST_SCHED_DEL(sched, fr->retrans); 01287 iax_frame_free(fr); 01288 }
static int iax2_getpeername | ( | struct sockaddr_in | sin, | |
char * | host, | |||
int | len | |||
) | [static] |
Definition at line 1190 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().
01191 { 01192 struct iax2_peer *peer = NULL; 01193 int res = 0; 01194 struct ao2_iterator i; 01195 01196 i = ao2_iterator_init(peers, 0); 01197 while ((peer = ao2_iterator_next(&i))) { 01198 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 01199 (peer->addr.sin_port == sin.sin_port)) { 01200 ast_copy_string(host, peer->name, len); 01201 peer_unref(peer); 01202 res = 1; 01203 break; 01204 } 01205 peer_unref(peer); 01206 } 01207 01208 if (!peer) { 01209 peer = realtime_peer(NULL, &sin); 01210 if (peer) { 01211 ast_copy_string(host, peer->name, len); 01212 peer_unref(peer); 01213 res = 1; 01214 } 01215 } 01216 01217 return res; 01218 }
static int iax2_getpeertrunk | ( | struct sockaddr_in | sin | ) | [static] |
Definition at line 3753 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().
03754 { 03755 struct iax2_peer *peer; 03756 int res = 0; 03757 struct ao2_iterator i; 03758 03759 i = ao2_iterator_init(peers, 0); 03760 while ((peer = ao2_iterator_next(&i))) { 03761 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 03762 (peer->addr.sin_port == sin.sin_port)) { 03763 res = ast_test_flag(peer, IAX_TRUNK); 03764 peer_unref(peer); 03765 break; 03766 } 03767 peer_unref(peer); 03768 } 03769 03770 return res; 03771 }
static int iax2_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3416 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_verbose(), ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, iaxs, iaxsl, option_debug, option_verbose, PTR_TO_CALLNO, send_command_final(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03417 { 03418 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03419 struct iax_ie_data ied; 03420 memset(&ied, 0, sizeof(ied)); 03421 ast_mutex_lock(&iaxsl[callno]); 03422 if (callno && iaxs[callno]) { 03423 if (option_debug) 03424 ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name); 03425 /* Send the hangup unless we have had a transmission error or are already gone */ 03426 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); 03427 if (!iaxs[callno]->error && !ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 03428 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 03429 if (!iaxs[callno]) { 03430 ast_mutex_unlock(&iaxsl[callno]); 03431 return 0; 03432 } 03433 } 03434 /* Explicitly predestroy it */ 03435 iax2_predestroy(callno); 03436 /* If we were already gone to begin with, destroy us now */ 03437 if (iaxs[callno]) { 03438 if (option_debug) 03439 ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name); 03440 iax2_destroy(callno); 03441 } 03442 } else if (c->tech_pvt) { 03443 /* If this call no longer exists, but the channel still 03444 * references it we need to set the channel's tech_pvt to null 03445 * to avoid ast_channel_free() trying to free it. 03446 */ 03447 c->tech_pvt = NULL; 03448 } 03449 ast_mutex_unlock(&iaxsl[callno]); 03450 if (option_verbose > 2) 03451 ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name); 03452 return 0; 03453 }
static int iax2_indicate | ( | struct ast_channel * | c, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 3686 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(), DEADLOCK_AVOIDANCE, iaxs, iaxsl, option_debug, chan_iax2_pvt::peercallno, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.
03687 { 03688 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03689 struct chan_iax2_pvt *pvt; 03690 int res = 0; 03691 03692 if (option_debug && iaxdebug) 03693 ast_log(LOG_DEBUG, "Indicating condition %d\n", condition); 03694 03695 ast_mutex_lock(&iaxsl[callno]); 03696 pvt = iaxs[callno]; 03697 03698 if (!pvt->peercallno) { 03699 /* We don't know the remote side's call number, yet. :( */ 03700 int count = 10; 03701 while (count-- && pvt && !pvt->peercallno) { 03702 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 03703 pvt = iaxs[callno]; 03704 } 03705 if (!pvt->peercallno) { 03706 res = -1; 03707 goto done; 03708 } 03709 } 03710 03711 switch (condition) { 03712 case AST_CONTROL_HOLD: 03713 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03714 ast_moh_start(c, data, pvt->mohinterpret); 03715 goto done; 03716 } 03717 break; 03718 case AST_CONTROL_UNHOLD: 03719 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03720 ast_moh_stop(c); 03721 goto done; 03722 } 03723 } 03724 03725 res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); 03726 03727 done: 03728 ast_mutex_unlock(&iaxsl[callno]); 03729 03730 return res; 03731 }
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 10565 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.
10566 { 10567 int res = 0; 10568 struct iax2_dpcache *dp; 10569 #if 0 10570 ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 10571 #endif 10572 if ((priority != 1) && (priority != 2)) 10573 return 0; 10574 ast_mutex_lock(&dpcache_lock); 10575 dp = find_cache(chan, data, context, exten, priority); 10576 if (dp) { 10577 if (dp->flags & CACHE_FLAG_MATCHMORE) 10578 res= 1; 10579 } 10580 ast_mutex_unlock(&dpcache_lock); 10581 if (!dp) { 10582 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 10583 } 10584 return res; 10585 }
static int iax2_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 5013 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
05014 { 05015 if (argc < 3 || argc > 4) 05016 return RESULT_SHOWUSAGE; 05017 iaxdebug = 0; 05018 ast_cli(fd, "IAX2 Debugging Disabled\n"); 05019 return RESULT_SUCCESS; 05020 }
static int iax2_no_jb_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 5031 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
05032 { 05033 if (argc < 4 || argc > 5) 05034 return RESULT_SHOWUSAGE; 05035 jb_setoutput(jb_error_output, jb_warning_output, NULL); 05036 jb_debug_output("\n"); 05037 ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 05038 return RESULT_SUCCESS; 05039 }
static int iax2_no_trunk_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 5022 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
05023 { 05024 if (argc < 4 || argc > 5) 05025 return RESULT_SHOWUSAGE; 05026 iaxtrunkdebug = 0; 05027 ast_cli(fd, "IAX2 Trunk Debugging Disabled\n"); 05028 return RESULT_SUCCESS; 05029 }
static int iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 8905 of file chan_iax2.c.
References __iax2_poke_noanswer(), peer_unref(), iax2_peer::pokeexpire, and schedule_action.
Referenced by iax2_poke_peer().
08906 { 08907 struct iax2_peer *peer = (struct iax2_peer *)data; 08908 peer->pokeexpire = -1; 08909 #ifdef SCHED_MULTITHREADED 08910 if (schedule_action(__iax2_poke_noanswer, data)) 08911 #endif 08912 __iax2_poke_noanswer(data); 08913 peer_unref(peer); 08914 return 0; 08915 }
static int iax2_poke_peer | ( | struct iax2_peer * | peer, | |
int | heldcall | |||
) | [static] |
Definition at line 8926 of file chan_iax2.c.
References iax2_peer::addr, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax2_peer::callno, DEFAULT_MAXMS, iax2_peer::dnsmgr, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), iax2_sched_add(), IAX_COMMAND_POKE, iaxs, iaxsl, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, NEW_FORCE, peer_ref(), peer_unref(), chan_iax2_pvt::peerpoke, chan_iax2_pvt::pingtime, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, sched, send_command(), and iax2_peer::sockfd.
Referenced by __iax2_poke_peer_s(), iax2_poke_peer_cb(), poke_all_peers(), reg_source_db(), and update_registry().
08927 { 08928 int callno; 08929 if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) { 08930 /* IF we have no IP without dnsmgr, or this isn't to be monitored, return 08931 immediately after clearing things out */ 08932 peer->lastms = 0; 08933 peer->historicms = 0; 08934 peer->pokeexpire = -1; 08935 peer->callno = 0; 08936 return 0; 08937 } 08938 08939 /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */ 08940 if ((callno = peer->callno) > 0) { 08941 ast_log(LOG_NOTICE, "Still have a callno...\n"); 08942 ast_mutex_lock(&iaxsl[callno]); 08943 iax2_destroy(callno); 08944 ast_mutex_unlock(&iaxsl[callno]); 08945 } 08946 if (heldcall) 08947 ast_mutex_unlock(&iaxsl[heldcall]); 08948 callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0); 08949 if (heldcall) 08950 ast_mutex_lock(&iaxsl[heldcall]); 08951 if (peer->callno < 1) { 08952 ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); 08953 return -1; 08954 } 08955 08956 /* Speed up retransmission times for this qualify call */ 08957 iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1; 08958 iaxs[peer->callno]->peerpoke = peer; 08959 08960 /* Remove any pending pokeexpire task */ 08961 if (peer->pokeexpire > -1) { 08962 if (!ast_sched_del(sched, peer->pokeexpire)) { 08963 peer->pokeexpire = -1; 08964 peer_unref(peer); 08965 } 08966 } 08967 08968 /* Queue up a new task to handle no reply */ 08969 /* If the host is already unreachable then use the unreachable interval instead */ 08970 if (peer->lastms < 0) { 08971 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer)); 08972 } else 08973 peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer)); 08974 08975 if (peer->pokeexpire == -1) 08976 peer_unref(peer); 08977 08978 /* And send the poke */ 08979 ast_mutex_lock(&iaxsl[callno]); 08980 if (iaxs[callno]) { 08981 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1); 08982 } 08983 ast_mutex_unlock(&iaxsl[callno]); 08984 08985 return 0; 08986 }
static int iax2_poke_peer_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 8917 of file chan_iax2.c.
References iax2_poke_peer().
Referenced by load_module().
08918 { 08919 struct iax2_peer *peer = obj; 08920 08921 iax2_poke_peer(peer, 0); 08922 08923 return 0; 08924 }
static int iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 6515 of file chan_iax2.c.
References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.
Referenced by __iax2_poke_noanswer(), and socket_process().
06516 { 06517 struct iax2_peer *peer = (struct iax2_peer *)data; 06518 peer->pokeexpire = -1; 06519 #ifdef SCHED_MULTITHREADED 06520 if (schedule_action(__iax2_poke_peer_s, data)) 06521 #endif 06522 __iax2_poke_peer_s(data); 06523 return 0; 06524 }
static int iax2_predestroy | ( | int | callno | ) | [static] |
Definition at line 2155 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().
02156 { 02157 struct ast_channel *c; 02158 struct chan_iax2_pvt *pvt = iaxs[callno]; 02159 02160 if (!pvt) 02161 return -1; 02162 if (!ast_test_flag(pvt, IAX_ALREADYGONE)) { 02163 iax2_destroy_helper(pvt); 02164 ast_set_flag(pvt, IAX_ALREADYGONE); 02165 } 02166 c = pvt->owner; 02167 if (c) { 02168 c->tech_pvt = NULL; 02169 iax2_queue_hangup(callno); 02170 pvt->owner = NULL; 02171 ast_module_unref(ast_module_info->self); 02172 } 02173 return 0; 02174 }
static void * iax2_process_thread | ( | void * | data | ) | [static] |
Definition at line 8581 of file chan_iax2.c.
References ast_cond_timedwait(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_tvadd(), iax2_process_thread_cleanup(), IAX_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), t, and thread.
Referenced by find_idle_thread(), and start_network_thread().
08582 { 08583 struct iax2_thread *thread = data; 08584 struct timeval tv; 08585 struct timespec ts; 08586 int put_into_idle = 0; 08587 08588 ast_atomic_fetchadd_int(&iaxactivethreadcount,1); 08589 pthread_cleanup_push(iax2_process_thread_cleanup, data); 08590 for(;;) { 08591 /* Wait for something to signal us to be awake */ 08592 ast_mutex_lock(&thread->lock); 08593 08594 /* Flag that we're ready to accept signals */ 08595 thread->ready_for_signal = 1; 08596 08597 /* Put into idle list if applicable */ 08598 if (put_into_idle) 08599 insert_idle_thread(thread); 08600 08601 if (thread->type == IAX_TYPE_DYNAMIC) { 08602 struct iax2_thread *t = NULL; 08603 /* Wait to be signalled or time out */ 08604 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 08605 ts.tv_sec = tv.tv_sec; 08606 ts.tv_nsec = tv.tv_usec * 1000; 08607 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) { 08608 /* This thread was never put back into the available dynamic 08609 * thread list, so just go away. */ 08610 if (!put_into_idle) { 08611 ast_mutex_unlock(&thread->lock); 08612 break; 08613 } 08614 AST_LIST_LOCK(&dynamic_list); 08615 /* Account for the case where this thread is acquired *right* after a timeout */ 08616 if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list))) 08617 iaxdynamicthreadcount--; 08618 AST_LIST_UNLOCK(&dynamic_list); 08619 if (t) { 08620 /* This dynamic thread timed out waiting for a task and was 08621 * not acquired immediately after the timeout, 08622 * so it's time to go away. */ 08623 ast_mutex_unlock(&thread->lock); 08624 break; 08625 } 08626 /* Someone grabbed our thread *right* after we timed out. 08627 * Wait for them to set us up with something to do and signal 08628 * us to continue. */ 08629 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 08630 ts.tv_sec = tv.tv_sec; 08631 ts.tv_nsec = tv.tv_usec * 1000; 08632 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) 08633 { 08634 ast_mutex_unlock(&thread->lock); 08635 break; 08636 } 08637 } 08638 } else { 08639 ast_cond_wait(&thread->cond, &thread->lock); 08640 } 08641 08642 /* Go back into our respective list */ 08643 put_into_idle = 1; 08644 08645 ast_mutex_unlock(&thread->lock); 08646 08647 if (thread->iostate == IAX_IOSTATE_IDLE) 08648 continue; 08649 08650 /* Add ourselves to the active list now */ 08651 AST_LIST_LOCK(&active_list); 08652 AST_LIST_INSERT_HEAD(&active_list, thread, list); 08653 AST_LIST_UNLOCK(&active_list); 08654 08655 /* See what we need to do */ 08656 switch(thread->iostate) { 08657 case IAX_IOSTATE_READY: 08658 thread->actions++; 08659 thread->iostate = IAX_IOSTATE_PROCESSING; 08660 socket_process(thread); 08661 handle_deferred_full_frames(thread); 08662 break; 08663 case IAX_IOSTATE_SCHEDREADY: 08664 thread->actions++; 08665 thread->iostate = IAX_IOSTATE_PROCESSING; 08666 #ifdef SCHED_MULTITHREADED 08667 thread->schedfunc(thread->scheddata); 08668 #endif 08669 break; 08670 } 08671 time(&thread->checktime); 08672 thread->iostate = IAX_IOSTATE_IDLE; 08673 #ifdef DEBUG_SCHED_MULTITHREAD 08674 thread->curfunc[0]='\0'; 08675 #endif 08676 08677 /* Now... remove ourselves from the active list, and return to the idle list */ 08678 AST_LIST_LOCK(&active_list); 08679 AST_LIST_REMOVE(&active_list, thread, list); 08680 AST_LIST_UNLOCK(&active_list); 08681 08682 /* Make sure another frame didn't sneak in there after we thought we were done. */ 08683 handle_deferred_full_frames(thread); 08684 } 08685 08686 /*!\note For some reason, idle threads are exiting without being removed 08687 * from an idle list, which is causing memory corruption. Forcibly remove 08688 * it from the list, if it's there. 08689 */ 08690 AST_LIST_LOCK(&idle_list); 08691 AST_LIST_REMOVE(&idle_list, thread, list); 08692 AST_LIST_UNLOCK(&idle_list); 08693 08694 AST_LIST_LOCK(&dynamic_list); 08695 AST_LIST_REMOVE(&dynamic_list, thread, list); 08696 AST_LIST_UNLOCK(&dynamic_list); 08697 08698 /* I am exiting here on my own volition, I need to clean up my own data structures 08699 * Assume that I am no longer in any of the lists (idle, active, or dynamic) 08700 */ 08701 pthread_cleanup_pop(1); 08702 08703 return NULL; 08704 }
static void iax2_process_thread_cleanup | ( | void * | data | ) | [static] |
Definition at line 8572 of file chan_iax2.c.
References ast_cond_destroy(), ast_mutex_destroy(), free, iaxactivethreadcount, and thread.
Referenced by iax2_process_thread().
08573 { 08574 struct iax2_thread *thread = data; 08575 ast_mutex_destroy(&thread->lock); 08576 ast_cond_destroy(&thread->cond); 08577 free(thread); 08578 ast_atomic_dec_and_test(&iaxactivethreadcount); 08579 }
static int iax2_prov_cmd | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 8860 of file chan_iax2.c.
References ast_cli(), iax2_provision(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
08861 { 08862 int force = 0; 08863 int res; 08864 if (argc < 4) 08865 return RESULT_SHOWUSAGE; 08866 if ((argc > 4)) { 08867 if (!strcasecmp(argv[4], "forced")) 08868 force = 1; 08869 else 08870 return RESULT_SHOWUSAGE; 08871 } 08872 res = iax2_provision(NULL, -1, argv[2], argv[3], force); 08873 if (res < 0) 08874 ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]); 08875 else if (res < 1) 08876 ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]); 08877 else 08878 ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : ""); 08879 return RESULT_SUCCESS; 08880 }
static char* iax2_prov_complete_template_3rd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 8763 of file chan_iax2.c.
References iax_prov_complete_template().
08764 { 08765 if (pos != 3) 08766 return NULL; 08767 return iax_prov_complete_template(line, word, pos, state); 08768 }
static int iax2_provision | ( | struct sockaddr_in * | end, | |
int | sockfd, | |||
char * | dest, | |||
const char * | template, | |||
int | force | |||
) | [static] |
Definition at line 8770 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_unlock(), AST_SCHED_DEL, ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, create_addr(), find_callno_locked(), iax2_sched_add(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), iaxs, iaxsl, NEW_FORCE, option_debug, iax_ie_data::pos, sched, and send_command().
Referenced by check_provisioning(), iax2_prov_app(), and iax2_prov_cmd().
08771 { 08772 /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning 08773 is found for template */ 08774 struct iax_ie_data provdata; 08775 struct iax_ie_data ied; 08776 unsigned int sig; 08777 struct sockaddr_in sin; 08778 int callno; 08779 struct create_addr_info cai; 08780 08781 memset(&cai, 0, sizeof(cai)); 08782 08783 if (option_debug) 08784 ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template); 08785 08786 if (iax_provision_build(&provdata, &sig, template, force)) { 08787 if (option_debug) 08788 ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template); 08789 return 0; 08790 } 08791 08792 if (end) { 08793 memcpy(&sin, end, sizeof(sin)); 08794 cai.sockfd = sockfd; 08795 } else if (create_addr(dest, NULL, &sin, &cai)) 08796 return -1; 08797 08798 /* Build the rest of the message */ 08799 memset(&ied, 0, sizeof(ied)); 08800 iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); 08801 08802 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 08803 if (!callno) 08804 return -1; 08805 08806 if (iaxs[callno]) { 08807 /* Schedule autodestruct in case they don't ever give us anything back */ 08808 AST_SCHED_DEL(sched, iaxs[callno]->autoid); 08809 iaxs[callno]->autoid = iax2_sched_add(sched, 15000, auto_hangup, (void *)(long)callno); 08810 ast_set_flag(iaxs[callno], IAX_PROVISION); 08811 /* Got a call number now, so go ahead and send the provisioning information */ 08812 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); 08813 } 08814 ast_mutex_unlock(&iaxsl[callno]); 08815 08816 return 1; 08817 }
static int iax2_prune_realtime | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2279 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.
02280 { 02281 struct iax2_peer *peer; 02282 02283 if (argc != 4) 02284 return RESULT_SHOWUSAGE; 02285 if (!strcmp(argv[3],"all")) { 02286 reload_config(); 02287 ast_cli(fd, "OK cache is flushed.\n"); 02288 } else if ((peer = find_peer(argv[3], 0))) { 02289 if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 02290 ast_set_flag(peer, IAX_RTAUTOCLEAR); 02291 expire_registry(peer_ref(peer)); 02292 ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]); 02293 } else { 02294 ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]); 02295 } 02296 peer_unref(peer); 02297 } else { 02298 ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]); 02299 } 02300 02301 return RESULT_SUCCESS; 02302 }
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 1765 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_control_data(), DEADLOCK_AVOIDANCE, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by socket_process().
01767 { 01768 for (;;) { 01769 if (iaxs[callno] && iaxs[callno]->owner) { 01770 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01771 /* Avoid deadlock by pausing and trying again */ 01772 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01773 } else { 01774 ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); 01775 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01776 break; 01777 } 01778 } else 01779 break; 01780 } 01781 return 0; 01782 }
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 1703 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, f, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), __get_from_jb(), and socket_process().
01704 { 01705 for (;;) { 01706 if (iaxs[callno] && iaxs[callno]->owner) { 01707 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01708 /* Avoid deadlock by pausing and trying again */ 01709 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01710 } else { 01711 ast_queue_frame(iaxs[callno]->owner, f); 01712 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01713 break; 01714 } 01715 } else 01716 break; 01717 } 01718 return 0; 01719 }
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 1734 of file chan_iax2.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, iaxsl, ast_channel::lock, and chan_iax2_pvt::owner.
Referenced by iax2_predestroy().
01735 { 01736 for (;;) { 01737 if (iaxs[callno] && iaxs[callno]->owner) { 01738 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01739 /* Avoid deadlock by pausing and trying again */ 01740 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01741 } else { 01742 ast_queue_hangup(iaxs[callno]->owner); 01743 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01744 break; 01745 } 01746 } else 01747 break; 01748 } 01749 return 0; 01750 }
static struct ast_frame * iax2_read | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3481 of file chan_iax2.c.
References ast_log(), and LOG_NOTICE.
03482 { 03483 ast_log(LOG_NOTICE, "I should never be called! Hanging up.\n"); 03484 return NULL; 03485 }
static int iax2_register | ( | char * | value, | |
int | lineno | |||
) | [static] |
Definition at line 5997 of file chan_iax2.c.
References ast_calloc, ast_dnsmgr_lookup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), copy(), free, hostname, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, secret, and strsep().
Referenced by set_config().
05998 { 05999 struct iax2_registry *reg; 06000 char copy[256]; 06001 char *username, *hostname, *secret; 06002 char *porta; 06003 char *stringp=NULL; 06004 06005 if (!value) 06006 return -1; 06007 ast_copy_string(copy, value, sizeof(copy)); 06008 stringp=copy; 06009 username = strsep(&stringp, "@"); 06010 hostname = strsep(&stringp, "@"); 06011 if (!hostname) { 06012 ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno); 06013 return -1; 06014 } 06015 stringp=username; 06016 username = strsep(&stringp, ":"); 06017 secret = strsep(&stringp, ":"); 06018 stringp=hostname; 06019 hostname = strsep(&stringp, ":"); 06020 porta = strsep(&stringp, ":"); 06021 06022 if (porta && !atoi(porta)) { 06023 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 06024 return -1; 06025 } 06026 if (!(reg = ast_calloc(1, sizeof(*reg)))) 06027 return -1; 06028 if (ast_dnsmgr_lookup(hostname, ®->addr.sin_addr, ®->dnsmgr) < 0) { 06029 free(reg); 06030 return -1; 06031 } 06032 ast_copy_string(reg->username, username, sizeof(reg->username)); 06033 if (secret) 06034 ast_copy_string(reg->secret, secret, sizeof(reg->secret)); 06035 reg->expire = -1; 06036 reg->refresh = IAX_DEFAULT_REG_EXPIRE; 06037 reg->addr.sin_family = AF_INET; 06038 reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); 06039 AST_LIST_LOCK(®istrations); 06040 AST_LIST_INSERT_HEAD(®istrations, reg, entry); 06041 AST_LIST_UNLOCK(®istrations); 06042 06043 return 0; 06044 }
static int iax2_reload | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10288 of file chan_iax2.c.
References reload_config().
10289 { 10290 return reload_config(); 10291 }
static struct ast_channel * iax2_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 8998 of file chan_iax2.c.
References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_translator_best_choice(), create_addr(), find_callno_locked(), fmt, globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), ast_channel::readformat, and ast_channel::writeformat.
08999 { 09000 int callno; 09001 int res; 09002 int fmt, native; 09003 struct sockaddr_in sin; 09004 struct ast_channel *c; 09005 struct parsed_dial_string pds; 09006 struct create_addr_info cai; 09007 char *tmpstr; 09008 09009 memset(&pds, 0, sizeof(pds)); 09010 tmpstr = ast_strdupa(data); 09011 parse_dial_string(tmpstr, &pds); 09012 09013 if (ast_strlen_zero(pds.peer)) { 09014 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 09015 return NULL; 09016 } 09017 09018 memset(&cai, 0, sizeof(cai)); 09019 cai.capability = iax2_capability; 09020 09021 ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 09022 09023 /* Populate our address from the given */ 09024 if (create_addr(pds.peer, NULL, &sin, &cai)) { 09025 *cause = AST_CAUSE_UNREGISTERED; 09026 return NULL; 09027 } 09028 09029 if (pds.port) 09030 sin.sin_port = htons(atoi(pds.port)); 09031 09032 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 09033 if (callno < 1) { 09034 ast_log(LOG_WARNING, "Unable to create call\n"); 09035 *cause = AST_CAUSE_CONGESTION; 09036 return NULL; 09037 } 09038 09039 /* If this is a trunk, update it now */ 09040 ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 09041 if (ast_test_flag(&cai, IAX_TRUNK)) { 09042 int new_callno; 09043 if ((new_callno = make_trunk(callno, 1)) != -1) 09044 callno = new_callno; 09045 } 09046 iaxs[callno]->maxtime = cai.maxtime; 09047 if (cai.found) 09048 ast_string_field_set(iaxs[callno], host, pds.peer); 09049 09050 c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability); 09051 09052 ast_mutex_unlock(&iaxsl[callno]); 09053 09054 if (c) { 09055 /* Choose a format we can live with */ 09056 if (c->nativeformats & format) 09057 c->nativeformats &= format; 09058 else { 09059 native = c->nativeformats; 09060 fmt = format; 09061 res = ast_translator_best_choice(&fmt, &native); 09062 if (res < 0) { 09063 ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", 09064 ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); 09065 ast_hangup(c); 09066 return NULL; 09067 } 09068 c->nativeformats = native; 09069 } 09070 c->readformat = ast_best_codec(c->nativeformats); 09071 c->writeformat = c->readformat; 09072 } 09073 09074 return c; 09075 }
static int iax2_sched_add | ( | struct sched_context * | con, | |
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) | [static] |
Definition at line 984 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(), reg_source_db(), socket_process(), update_jbsched(), and update_registry().
00985 { 00986 int res; 00987 00988 res = ast_sched_add(con, when, callback, data); 00989 signal_condition(&sched_lock, &sched_cond); 00990 00991 return res; 00992 }
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 4324 of file chan_iax2.c.
References iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, ast_frame::datalen, iax_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, encrypt_frame(), f, iax_frame::final, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, LOG_WARNING, MAX_RETRY_TIME, MIN_RETRY_TIME, ast_iax2_full_hdr::oseqno, chan_iax2_pvt::oseqno, iax_frame::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, iax_frame::retrytime, ast_iax2_full_hdr::scallno, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, iax_frame::transfer, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, ast_iax2_mini_hdr::ts, ast_iax2_video_hdr::ts, ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_full_hdr::type, and ast_iax2_video_hdr::zeros.
Referenced by __send_command(), iax2_write(), and socket_process().
04325 { 04326 /* Queue a packet for delivery on a given private structure. Use "ts" for 04327 timestamp, or calculate if ts is 0. Send immediately without retransmission 04328 or delayed, with retransmission */ 04329 struct ast_iax2_full_hdr *fh; 04330 struct ast_iax2_mini_hdr *mh; 04331 struct ast_iax2_video_hdr *vh; 04332 struct { 04333 struct iax_frame fr2; 04334 unsigned char buffer[4096]; 04335 } frb; 04336 struct iax_frame *fr; 04337 int res; 04338 int sendmini=0; 04339 unsigned int lastsent; 04340 unsigned int fts; 04341 04342 frb.fr2.afdatalen = sizeof(frb.buffer); 04343 04344 if (!pvt) { 04345 ast_log(LOG_WARNING, "No private structure for packet?\n"); 04346 return -1; 04347 } 04348 04349 lastsent = pvt->lastsent; 04350 04351 /* Calculate actual timestamp */ 04352 fts = calc_timestamp(pvt, ts, f); 04353 04354 /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out 04355 * (the endpoint should detect the lost packet itself). But, we want to do this here, so that we 04356 * increment the "predicted timestamps" for voice, if we're predecting */ 04357 if(f->frametype == AST_FRAME_VOICE && f->datalen == 0) 04358 return 0; 04359 04360 04361 if ((ast_test_flag(pvt, IAX_TRUNK) || 04362 (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) || 04363 ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L)))) 04364 /* High two bytes are the same on timestamp, or sending on a trunk */ && 04365 (f->frametype == AST_FRAME_VOICE) 04366 /* is a voice frame */ && 04367 (f->subclass == pvt->svoiceformat) 04368 /* is the same type */ ) { 04369 /* Force immediate rather than delayed transmission */ 04370 now = 1; 04371 /* Mark that mini-style frame is appropriate */ 04372 sendmini = 1; 04373 } 04374 if ( f->frametype == AST_FRAME_VIDEO ) { 04375 /* 04376 * If the lower 15 bits of the timestamp roll over, or if 04377 * the video format changed then send a full frame. 04378 * Otherwise send a mini video frame 04379 */ 04380 if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) && 04381 ((f->subclass & ~0x1) == pvt->svideoformat) 04382 ) { 04383 now = 1; 04384 sendmini = 1; 04385 } else { 04386 now = 0; 04387 sendmini = 0; 04388 } 04389 pvt->lastvsent = fts; 04390 } 04391 /* Allocate an iax_frame */ 04392 if (now) { 04393 fr = &frb.fr2; 04394 } else 04395 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)); 04396 if (!fr) { 04397 ast_log(LOG_WARNING, "Out of memory\n"); 04398 return -1; 04399 } 04400 /* Copy our prospective frame into our immediate or retransmitted wrapper */ 04401 iax_frame_wrap(fr, f); 04402 04403 fr->ts = fts; 04404 fr->callno = pvt->callno; 04405 fr->transfer = transfer; 04406 fr->final = final; 04407 if (!sendmini) { 04408 /* We need a full frame */ 04409 if (seqno > -1) 04410 fr->oseqno = seqno; 04411 else 04412 fr->oseqno = pvt->oseqno++; 04413 fr->iseqno = pvt->iseqno; 04414 fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr)); 04415 fh->scallno = htons(fr->callno | IAX_FLAG_FULL); 04416 fh->ts = htonl(fr->ts); 04417 fh->oseqno = fr->oseqno; 04418 if (transfer) { 04419 fh->iseqno = 0; 04420 } else 04421 fh->iseqno = fr->iseqno; 04422 /* Keep track of the last thing we've acknowledged */ 04423 if (!transfer) 04424 pvt->aseqno = fr->iseqno; 04425 fh->type = fr->af.frametype & 0xFF; 04426 if (fr->af.frametype == AST_FRAME_VIDEO) 04427 fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6); 04428 else 04429 fh->csub = compress_subclass(fr->af.subclass); 04430 if (transfer) { 04431 fr->dcallno = pvt->transfercallno; 04432 } else 04433 fr->dcallno = pvt->peercallno; 04434 fh->dcallno = htons(fr->dcallno); 04435 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); 04436 fr->data = fh; 04437 fr->retries = 0; 04438 /* Retry after 2x the ping time has passed */ 04439 fr->retrytime = pvt->pingtime * 2; 04440 if (fr->retrytime < MIN_RETRY_TIME) 04441 fr->retrytime = MIN_RETRY_TIME; 04442 if (fr->retrytime > MAX_RETRY_TIME) 04443 fr->retrytime = MAX_RETRY_TIME; 04444 /* Acks' don't get retried */ 04445 if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) 04446 fr->retries = -1; 04447 else if (f->frametype == AST_FRAME_VOICE) 04448 pvt->svoiceformat = f->subclass; 04449 else if (f->frametype == AST_FRAME_VIDEO) 04450 pvt->svideoformat = f->subclass & ~0x1; 04451 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 04452 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 04453 if (iaxdebug) { 04454 if (fr->transfer) 04455 iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 04456 else 04457 iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 04458 } 04459 encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen); 04460 } else 04461 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04462 } 04463 04464 if (now) { 04465 res = send_packet(fr); 04466 } else 04467 res = iax2_transmit(fr); 04468 } else { 04469 if (ast_test_flag(pvt, IAX_TRUNK)) { 04470 iax2_trunk_queue(pvt, fr); 04471 res = 0; 04472 } else if (fr->af.frametype == AST_FRAME_VIDEO) { 04473 /* Video frame have no sequence number */ 04474 fr->oseqno = -1; 04475 fr->iseqno = -1; 04476 vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr)); 04477 vh->zeros = 0; 04478 vh->callno = htons(0x8000 | fr->callno); 04479 vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); 04480 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); 04481 fr->data = vh; 04482 fr->retries = -1; 04483 res = send_packet(fr); 04484 } else { 04485 /* Mini-frames have no sequence number */ 04486 fr->oseqno = -1; 04487 fr->iseqno = -1; 04488 /* Mini frame will do */ 04489 mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr)); 04490 mh->callno = htons(fr->callno); 04491 mh->ts = htons(fr->ts & 0xFFFF); 04492 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); 04493 fr->data = mh; 04494 fr->retries = -1; 04495 if (pvt->transferring == TRANSFER_MEDIAPASS) 04496 fr->transfer = 1; 04497 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 04498 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 04499 encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen); 04500 } else 04501 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04502 } 04503 res = send_packet(fr); 04504 } 04505 } 04506 return res; 04507 }
static int iax2_sendhtml | ( | struct ast_channel * | c, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 2810 of file chan_iax2.c.
References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02811 { 02812 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1); 02813 }
static int iax2_sendimage | ( | struct ast_channel * | c, | |
struct ast_frame * | img | |||
) | [static] |
Definition at line 2805 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.
02806 { 02807 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1); 02808 }
static int iax2_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 2798 of file chan_iax2.c.
References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02799 { 02800 02801 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT, 02802 0, 0, (unsigned char *)text, strlen(text) + 1, -1); 02803 }
static int iax2_setoption | ( | struct ast_channel * | c, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3455 of file chan_iax2.c.
References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_malloc, AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, errno, free, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03456 { 03457 struct ast_option_header *h; 03458 int res; 03459 03460 switch (option) { 03461 case AST_OPTION_TXGAIN: 03462 case AST_OPTION_RXGAIN: 03463 /* these two cannot be sent, because they require a result */ 03464 errno = ENOSYS; 03465 return -1; 03466 default: 03467 if (!(h = ast_malloc(datalen + sizeof(*h)))) 03468 return -1; 03469 03470 h->flag = AST_OPTION_FLAG_REQUEST; 03471 h->option = htons(option); 03472 memcpy(h->data, data, datalen); 03473 res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL, 03474 AST_CONTROL_OPTION, 0, (unsigned char *) h, 03475 datalen + sizeof(*h), -1); 03476 free(h); 03477 return res; 03478 } 03479 }
static int iax2_show_cache | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2483 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.
02484 { 02485 struct iax2_dpcache *dp; 02486 char tmp[1024], *pc; 02487 int s; 02488 int x,y; 02489 struct timeval tv; 02490 gettimeofday(&tv, NULL); 02491 ast_mutex_lock(&dpcache_lock); 02492 dp = dpcache; 02493 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags"); 02494 while(dp) { 02495 s = dp->expiry.tv_sec - tv.tv_sec; 02496 tmp[0] = '\0'; 02497 if (dp->flags & CACHE_FLAG_EXISTS) 02498 strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1); 02499 if (dp->flags & CACHE_FLAG_NONEXISTENT) 02500 strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1); 02501 if (dp->flags & CACHE_FLAG_CANEXIST) 02502 strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1); 02503 if (dp->flags & CACHE_FLAG_PENDING) 02504 strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1); 02505 if (dp->flags & CACHE_FLAG_TIMEOUT) 02506 strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1); 02507 if (dp->flags & CACHE_FLAG_TRANSMITTED) 02508 strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1); 02509 if (dp->flags & CACHE_FLAG_MATCHMORE) 02510 strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1); 02511 if (dp->flags & CACHE_FLAG_UNKNOWN) 02512 strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1); 02513 /* Trim trailing pipe */ 02514 if (!ast_strlen_zero(tmp)) 02515 tmp[strlen(tmp) - 1] = '\0'; 02516 else 02517 ast_copy_string(tmp, "(none)", sizeof(tmp)); 02518 y=0; 02519 pc = strchr(dp->peercontext, '@'); 02520 if (!pc) 02521 pc = dp->peercontext; 02522 else 02523 pc++; 02524 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 02525 if (dp->waiters[x] > -1) 02526 y++; 02527 if (s > 0) 02528 ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp); 02529 else 02530 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp); 02531 dp = dp->next; 02532 } 02533 ast_mutex_unlock(&dpcache_lock); 02534 return RESULT_SUCCESS; 02535 }
static int iax2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4851 of file chan_iax2.c.
References ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, jb_info::current, iax_rr::delay, FORMAT, FORMAT2, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), jb_info::jitter, jb_info::min, chan_iax2_pvt::remote_rr, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_OR.
04852 { 04853 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" 04854 #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" 04855 #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" 04856 int x; 04857 int numchans = 0; 04858 04859 if (argc != 3) 04860 return RESULT_SHOWUSAGE; 04861 ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format"); 04862 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 04863 ast_mutex_lock(&iaxsl[x]); 04864 if (iaxs[x]) { 04865 int lag, jitter, localdelay; 04866 jb_info jbinfo; 04867 04868 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04869 jb_getinfo(iaxs[x]->jb, &jbinfo); 04870 jitter = jbinfo.jitter; 04871 localdelay = jbinfo.current - jbinfo.min; 04872 } else { 04873 jitter = -1; 04874 localdelay = 0; 04875 } 04876 lag = iaxs[x]->remote_rr.delay; 04877 ast_cli(fd, FORMAT, 04878 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04879 ast_inet_ntoa(iaxs[x]->addr.sin_addr), 04880 S_OR(iaxs[x]->username, "(None)"), 04881 iaxs[x]->callno, iaxs[x]->peercallno, 04882 iaxs[x]->oseqno, iaxs[x]->iseqno, 04883 lag, 04884 jitter, 04885 localdelay, 04886 ast_getformatname(iaxs[x]->voiceformat) ); 04887 numchans++; 04888 } 04889 ast_mutex_unlock(&iaxsl[x]); 04890 } 04891 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04892 return RESULT_SUCCESS; 04893 #undef FORMAT 04894 #undef FORMAT2 04895 #undef FORMATB 04896 }
static int iax2_show_firmware | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4762 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.
04763 { 04764 #define FORMAT2 "%-15.15s %-15.15s %-15.15s\n" 04765 #if !defined(__FreeBSD__) 04766 #define FORMAT "%-15.15s %-15d %-15d\n" 04767 #else /* __FreeBSD__ */ 04768 #define FORMAT "%-15.15s %-15d %-15d\n" /* XXX 2.95 ? */ 04769 #endif /* __FreeBSD__ */ 04770 struct iax_firmware *cur; 04771 if ((argc != 3) && (argc != 4)) 04772 return RESULT_SHOWUSAGE; 04773 ast_mutex_lock(&waresl.lock); 04774 04775 ast_cli(fd, FORMAT2, "Device", "Version", "Size"); 04776 for (cur = waresl.wares;cur;cur = cur->next) { 04777 if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 04778 ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version), 04779 (int)ntohl(cur->fwh->datalen)); 04780 } 04781 ast_mutex_unlock(&waresl.lock); 04782 return RESULT_SUCCESS; 04783 #undef FORMAT 04784 #undef FORMAT2 04785 }
static int iax2_show_netstats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4974 of file chan_iax2.c.
References ast_cli(), ast_cli_netstats(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04975 { 04976 int numchans = 0; 04977 if (argc != 3) 04978 return RESULT_SHOWUSAGE; 04979 ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); 04980 ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n"); 04981 numchans = ast_cli_netstats(NULL, fd, 1); 04982 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04983 return RESULT_SUCCESS; 04984 }
static int iax2_show_peer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Show one peer in detail.
Definition at line 2373 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.
02374 { 02375 char status[30]; 02376 char cbuf[256]; 02377 struct iax2_peer *peer; 02378 char codec_buf[512]; 02379 int x = 0, codec = 0, load_realtime = 0; 02380 02381 if (argc < 4) 02382 return RESULT_SHOWUSAGE; 02383 02384 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0; 02385 02386 peer = find_peer(argv[3], load_realtime); 02387 if (peer) { 02388 ast_cli(fd,"\n\n"); 02389 ast_cli(fd, " * Name : %s\n", peer->name); 02390 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 02391 ast_cli(fd, " Context : %s\n", peer->context); 02392 ast_cli(fd, " Mailbox : %s\n", peer->mailbox); 02393 ast_cli(fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No"); 02394 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 02395 ast_cli(fd, " Expire : %d\n", peer->expire); 02396 ast_cli(fd, " ACL : %s\n", (peer->ha?"Yes":"No")); 02397 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)); 02398 ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 02399 ast_cli(fd, " Username : %s\n", peer->username); 02400 ast_cli(fd, " Codecs : "); 02401 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 02402 ast_cli(fd, "%s\n", codec_buf); 02403 02404 ast_cli(fd, " Codec Order : ("); 02405 for(x = 0; x < 32 ; x++) { 02406 codec = ast_codec_pref_index(&peer->prefs,x); 02407 if(!codec) 02408 break; 02409 ast_cli(fd, "%s", ast_getformatname(codec)); 02410 if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) 02411 ast_cli(fd, "|"); 02412 } 02413 02414 if (!x) 02415 ast_cli(fd, "none"); 02416 ast_cli(fd, ")\n"); 02417 02418 ast_cli(fd, " Status : "); 02419 peer_status(peer, status, sizeof(status)); 02420 ast_cli(fd, "%s\n",status); 02421 ast_cli(fd, " Qualify : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off"); 02422 ast_cli(fd,"\n"); 02423 peer_unref(peer); 02424 } else { 02425 ast_cli(fd,"Peer %s not found.\n", argv[3]); 02426 ast_cli(fd,"\n"); 02427 } 02428 02429 return RESULT_SUCCESS; 02430 }
static int iax2_show_peers | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4751 of file chan_iax2.c.
References __iax2_show_peers().
04752 { 04753 return __iax2_show_peers(0, fd, NULL, argc, argv); 04754 }
static int iax2_show_registry | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4823 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.
04824 { 04825 #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" 04826 #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" 04827 struct iax2_registry *reg = NULL; 04828 04829 char host[80]; 04830 char perceived[80]; 04831 if (argc != 3) 04832 return RESULT_SHOWUSAGE; 04833 ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); 04834 AST_LIST_LOCK(®istrations); 04835 AST_LIST_TRAVERSE(®istrations, reg, entry) { 04836 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); 04837 if (reg->us.sin_addr.s_addr) 04838 snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 04839 else 04840 ast_copy_string(perceived, "<Unregistered>", sizeof(perceived)); 04841 ast_cli(fd, FORMAT, host, 04842 (reg->dnsmgr) ? "Y" : "N", 04843 reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); 04844 } 04845 AST_LIST_UNLOCK(®istrations); 04846 return RESULT_SUCCESS; 04847 #undef FORMAT 04848 #undef FORMAT2 04849 }
static int iax2_show_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2457 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.
02458 { 02459 struct iax_frame *cur; 02460 int cnt = 0, dead=0, final=0; 02461 02462 if (argc != 3) 02463 return RESULT_SHOWUSAGE; 02464 02465 AST_LIST_LOCK(&iaxq.queue); 02466 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 02467 if (cur->retries < 0) 02468 dead++; 02469 if (cur->final) 02470 final++; 02471 cnt++; 02472 } 02473 AST_LIST_UNLOCK(&iaxq.queue); 02474 02475 ast_cli(fd, " IAX Statistics\n"); 02476 ast_cli(fd, "---------------------\n"); 02477 ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); 02478 ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); 02479 02480 return RESULT_SUCCESS; 02481 }
static int iax2_show_threads | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4692 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, thread, and type.
04693 { 04694 struct iax2_thread *thread = NULL; 04695 time_t t; 04696 int threadcount = 0, dynamiccount = 0; 04697 char type; 04698 04699 if (argc != 3) 04700 return RESULT_SHOWUSAGE; 04701 04702 ast_cli(fd, "IAX2 Thread Information\n"); 04703 time(&t); 04704 ast_cli(fd, "Idle Threads:\n"); 04705 AST_LIST_LOCK(&idle_list); 04706 AST_LIST_TRAVERSE(&idle_list, thread, list) { 04707 #ifdef DEBUG_SCHED_MULTITHREAD 04708 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04709 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04710 #else 04711 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04712 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04713 #endif 04714 threadcount++; 04715 } 04716 AST_LIST_UNLOCK(&idle_list); 04717 ast_cli(fd, "Active Threads:\n"); 04718 AST_LIST_LOCK(&active_list); 04719 AST_LIST_TRAVERSE(&active_list, thread, list) { 04720 if (thread->type == IAX_TYPE_DYNAMIC) 04721 type = 'D'; 04722 else 04723 type = 'P'; 04724 #ifdef DEBUG_SCHED_MULTITHREAD 04725 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 04726 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04727 #else 04728 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 04729 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04730 #endif 04731 threadcount++; 04732 } 04733 AST_LIST_UNLOCK(&active_list); 04734 ast_cli(fd, "Dynamic Threads:\n"); 04735 AST_LIST_LOCK(&dynamic_list); 04736 AST_LIST_TRAVERSE(&dynamic_list, thread, list) { 04737 #ifdef DEBUG_SCHED_MULTITHREAD 04738 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04739 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04740 #else 04741 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04742 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04743 #endif 04744 dynamiccount++; 04745 } 04746 AST_LIST_UNLOCK(&dynamic_list); 04747 ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount); 04748 return RESULT_SUCCESS; 04749 }
static int iax2_show_users | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4509 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.
04510 { 04511 regex_t regexbuf; 04512 int havepattern = 0; 04513 04514 #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" 04515 #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" 04516 04517 struct iax2_user *user = NULL; 04518 char auth[90]; 04519 char *pstr = ""; 04520 struct ao2_iterator i; 04521 04522 switch (argc) { 04523 case 5: 04524 if (!strcasecmp(argv[3], "like")) { 04525 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04526 return RESULT_SHOWUSAGE; 04527 havepattern = 1; 04528 } else 04529 return RESULT_SHOWUSAGE; 04530 case 3: 04531 break; 04532 default: 04533 return RESULT_SHOWUSAGE; 04534 } 04535 04536 ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); 04537 i = ao2_iterator_init(users, 0); 04538 for (user = ao2_iterator_next(&i); user; 04539 user_unref(user), user = ao2_iterator_next(&i)) { 04540 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) 04541 continue; 04542 04543 if (!ast_strlen_zero(user->secret)) { 04544 ast_copy_string(auth,user->secret,sizeof(auth)); 04545 } else if (!ast_strlen_zero(user->inkeys)) { 04546 snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys); 04547 } else 04548 ast_copy_string(auth, "-no secret-", sizeof(auth)); 04549 04550 if(ast_test_flag(user,IAX_CODEC_NOCAP)) 04551 pstr = "REQ Only"; 04552 else if(ast_test_flag(user,IAX_CODEC_NOPREFS)) 04553 pstr = "Disabled"; 04554 else 04555 pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host"; 04556 04557 ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 04558 user->contexts ? user->contexts->context : context, 04559 user->ha ? "Yes" : "No", pstr); 04560 } 04561 04562 if (havepattern) 04563 regfree(®exbuf); 04564 04565 return RESULT_SUCCESS; 04566 #undef FORMAT 04567 #undef FORMAT2 04568 }
static int iax2_start_transfer | ( | unsigned short | callno0, | |
unsigned short | callno1, | |||
int | mediaonly | |||
) | [static] |
Definition at line 3487 of file chan_iax2.c.
References AST_FRAME_IAX, ast_random(), IAX_COMMAND_TXREQ, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), IAX_IE_CALLNO, IAX_IE_TRANSFERID, iaxs, send_command(), TRANSFER_BEGIN, TRANSFER_MBEGIN, and chan_iax2_pvt::transferring.
03488 { 03489 int res; 03490 struct iax_ie_data ied0; 03491 struct iax_ie_data ied1; 03492 unsigned int transferid = (unsigned int)ast_random(); 03493 memset(&ied0, 0, sizeof(ied0)); 03494 iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr); 03495 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno); 03496 iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); 03497 03498 memset(&ied1, 0, sizeof(ied1)); 03499 iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr); 03500 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno); 03501 iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); 03502 03503 res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); 03504 if (res) 03505 return -1; 03506 res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); 03507 if (res) 03508 return -1; 03509 iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03510 iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03511 return 0; 03512 }
static int iax2_test_losspct | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2304 of file chan_iax2.c.
References RESULT_SHOWUSAGE, and RESULT_SUCCESS.
02305 { 02306 if (argc != 4) 02307 return RESULT_SHOWUSAGE; 02308 02309 test_losspct = atoi(argv[3]); 02310 02311 return RESULT_SUCCESS; 02312 }
static int iax2_transfer | ( | struct ast_channel * | c, | |
const char * | dest | |||
) | [static] |
Definition at line 3733 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), chan_iax2_pvt::callno, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, option_debug, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03734 { 03735 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03736 struct iax_ie_data ied; 03737 char tmp[256], *context; 03738 ast_copy_string(tmp, dest, sizeof(tmp)); 03739 context = strchr(tmp, '@'); 03740 if (context) { 03741 *context = '\0'; 03742 context++; 03743 } 03744 memset(&ied, 0, sizeof(ied)); 03745 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp); 03746 if (context) 03747 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); 03748 if (option_debug) 03749 ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest); 03750 return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); 03751 }
static int iax2_transmit | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2769 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().
02770 { 02771 /* Lock the queue and place this packet at the end */ 02772 /* By setting this to 0, the network thread will send it for us, and 02773 queue retransmission if necessary */ 02774 fr->sentyet = 0; 02775 AST_LIST_LOCK(&iaxq.queue); 02776 AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list); 02777 iaxq.count++; 02778 AST_LIST_UNLOCK(&iaxq.queue); 02779 /* Wake up the network and scheduler thread */ 02780 if (netthreadid != AST_PTHREADT_NULL) 02781 pthread_kill(netthreadid, SIGURG); 02782 signal_condition(&sched_lock, &sched_cond); 02783 return 0; 02784 }
static int iax2_trunk_expired | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [inline, static] |
Definition at line 6570 of file chan_iax2.c.
References iax2_trunk_peer::trunkact.
Referenced by timing_read().
06571 { 06572 /* Drop when trunk is about 5 seconds idle */ 06573 if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 06574 return 1; 06575 return 0; 06576 }
static int iax2_trunk_queue | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_frame * | fr | |||
) | [static] |
Definition at line 4098 of file chan_iax2.c.
References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, DEFAULT_TRUNKDATA, f, find_tpeer(), globalflags, IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, MAX_TRUNKDATA, ast_iax2_meta_trunk_mini::mini, option_debug, chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.
Referenced by iax2_send().
04099 { 04100 struct ast_frame *f; 04101 struct iax2_trunk_peer *tpeer; 04102 void *tmp, *ptr; 04103 struct ast_iax2_meta_trunk_entry *met; 04104 struct ast_iax2_meta_trunk_mini *mtm; 04105 04106 f = &fr->af; 04107 tpeer = find_tpeer(&pvt->addr, pvt->sockfd); 04108 if (tpeer) { 04109 if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) { 04110 /* Need to reallocate space */ 04111 if (tpeer->trunkdataalloc < MAX_TRUNKDATA) { 04112 if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) { 04113 ast_mutex_unlock(&tpeer->lock); 04114 return -1; 04115 } 04116 04117 tpeer->trunkdataalloc += DEFAULT_TRUNKDATA; 04118 tpeer->trunkdata = tmp; 04119 if (option_debug) 04120 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); 04121 } else { 04122 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)); 04123 ast_mutex_unlock(&tpeer->lock); 04124 return -1; 04125 } 04126 } 04127 04128 /* Append to meta frame */ 04129 ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen; 04130 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) { 04131 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 04132 mtm->len = htons(f->datalen); 04133 mtm->mini.callno = htons(pvt->callno); 04134 mtm->mini.ts = htons(0xffff & fr->ts); 04135 ptr += sizeof(struct ast_iax2_meta_trunk_mini); 04136 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini); 04137 } else { 04138 met = (struct ast_iax2_meta_trunk_entry *)ptr; 04139 /* Store call number and length in meta header */ 04140 met->callno = htons(pvt->callno); 04141 met->len = htons(f->datalen); 04142 /* Advance pointers/decrease length past trunk entry header */ 04143 ptr += sizeof(struct ast_iax2_meta_trunk_entry); 04144 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry); 04145 } 04146 /* Copy actual trunk data */ 04147 memcpy(ptr, f->data, f->datalen); 04148 tpeer->trunkdatalen += f->datalen; 04149 04150 tpeer->calls++; 04151 ast_mutex_unlock(&tpeer->lock); 04152 } 04153 return 0; 04154 }
static int iax2_vnak | ( | int | callno | ) | [static] |
Definition at line 6487 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_VNAK, iaxs, and send_command_immediate().
Referenced by socket_process().
06488 { 06489 return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno); 06490 }
static int iax2_write | ( | struct ast_channel * | c, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 5041 of file chan_iax2.c.
References AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, errno, f, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, option_debug, PTR_TO_CALLNO, and ast_channel::tech_pvt.
05042 { 05043 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 05044 int res = -1; 05045 ast_mutex_lock(&iaxsl[callno]); 05046 if (iaxs[callno]) { 05047 /* If there's an outstanding error, return failure now */ 05048 if (!iaxs[callno]->error) { 05049 if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) 05050 res = 0; 05051 /* Don't waste bandwidth sending null frames */ 05052 else if (f->frametype == AST_FRAME_NULL) 05053 res = 0; 05054 else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH)) 05055 res = 0; 05056 else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 05057 res = 0; 05058 else 05059 /* Simple, just queue for transmission */ 05060 res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0); 05061 } else { 05062 if (option_debug) 05063 ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno)); 05064 } 05065 } 05066 /* If it's already gone, just return */ 05067 ast_mutex_unlock(&iaxsl[callno]); 05068 return res; 05069 }
static int iax_check_version | ( | char * | dev | ) | [static] |
Definition at line 1938 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().
01939 { 01940 int res = 0; 01941 struct iax_firmware *cur; 01942 if (!ast_strlen_zero(dev)) { 01943 ast_mutex_lock(&waresl.lock); 01944 cur = waresl.wares; 01945 while(cur) { 01946 if (!strcmp(dev, (char *)cur->fwh->devname)) { 01947 res = ntohs(cur->fwh->version); 01948 break; 01949 } 01950 cur = cur->next; 01951 } 01952 ast_mutex_unlock(&waresl.lock); 01953 } 01954 return res; 01955 }
static void iax_debug_output | ( | const char * | data | ) | [static] |
Definition at line 762 of file chan_iax2.c.
References ast_verbose().
Referenced by load_module().
00763 { 00764 if (iaxdebug) 00765 ast_verbose("%s", data); 00766 }
static void iax_error_output | ( | const char * | data | ) | [static] |
Definition at line 768 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00769 { 00770 ast_log(LOG_WARNING, "%s", data); 00771 }
static int iax_firmware_append | ( | struct iax_ie_data * | ied, | |
const unsigned char * | dev, | |||
unsigned int | desc | |||
) | [static] |
Definition at line 1957 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().
01958 { 01959 int res = -1; 01960 unsigned int bs = desc & 0xff; 01961 unsigned int start = (desc >> 8) & 0xffffff; 01962 unsigned int bytes; 01963 struct iax_firmware *cur; 01964 if (!ast_strlen_zero((char *)dev) && bs) { 01965 start *= bs; 01966 ast_mutex_lock(&waresl.lock); 01967 cur = waresl.wares; 01968 while(cur) { 01969 if (!strcmp((char *)dev, (char *)cur->fwh->devname)) { 01970 iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc); 01971 if (start < ntohl(cur->fwh->datalen)) { 01972 bytes = ntohl(cur->fwh->datalen) - start; 01973 if (bytes > bs) 01974 bytes = bs; 01975 iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes); 01976 } else { 01977 bytes = 0; 01978 iax_ie_append(ied, IAX_IE_FWBLOCKDATA); 01979 } 01980 if (bytes == bs) 01981 res = 0; 01982 else 01983 res = 1; 01984 break; 01985 } 01986 cur = cur->next; 01987 } 01988 ast_mutex_unlock(&waresl.lock); 01989 } 01990 return res; 01991 }
static int iax_park | ( | struct ast_channel * | chan1, | |
struct ast_channel * | chan2 | |||
) | [static] |
Definition at line 6758 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, 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().
06759 { 06760 struct iax_dual *d; 06761 struct ast_channel *chan1m, *chan2m; 06762 pthread_t th; 06763 chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 06764 chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name); 06765 if (chan2m && chan1m) { 06766 /* Make formats okay */ 06767 chan1m->readformat = chan1->readformat; 06768 chan1m->writeformat = chan1->writeformat; 06769 ast_channel_masquerade(chan1m, chan1); 06770 /* Setup the extensions and such */ 06771 ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context)); 06772 ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten)); 06773 chan1m->priority = chan1->priority; 06774 06775 /* We make a clone of the peer channel too, so we can play 06776 back the announcement */ 06777 /* Make formats okay */ 06778 chan2m->readformat = chan2->readformat; 06779 chan2m->writeformat = chan2->writeformat; 06780 ast_channel_masquerade(chan2m, chan2); 06781 /* Setup the extensions and such */ 06782 ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context)); 06783 ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten)); 06784 chan2m->priority = chan2->priority; 06785 if (ast_do_masquerade(chan2m)) { 06786 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 06787 ast_hangup(chan2m); 06788 return -1; 06789 } 06790 } else { 06791 if (chan1m) 06792 ast_hangup(chan1m); 06793 if (chan2m) 06794 ast_hangup(chan2m); 06795 return -1; 06796 } 06797 if ((d = ast_calloc(1, sizeof(*d)))) { 06798 pthread_attr_t attr; 06799 06800 pthread_attr_init(&attr); 06801 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06802 06803 d->chan1 = chan1m; 06804 d->chan2 = chan2m; 06805 if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) { 06806 pthread_attr_destroy(&attr); 06807 return 0; 06808 } 06809 pthread_attr_destroy(&attr); 06810 free(d); 06811 } 06812 return -1; 06813 }
static void* iax_park_thread | ( | void * | stuff | ) | [static] |
Definition at line 6738 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().
06739 { 06740 struct ast_channel *chan1, *chan2; 06741 struct iax_dual *d; 06742 struct ast_frame *f; 06743 int ext; 06744 int res; 06745 d = stuff; 06746 chan1 = d->chan1; 06747 chan2 = d->chan2; 06748 free(d); 06749 f = ast_read(chan1); 06750 if (f) 06751 ast_frfree(f); 06752 res = ast_park_call(chan1, chan2, 0, &ext); 06753 ast_hangup(chan2); 06754 ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext); 06755 return NULL; 06756 }
Definition at line 1422 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().
01423 { 01424 struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable); 01425 if (new) { 01426 size_t afdatalen = new->afdatalen; 01427 memcpy(new, fr, sizeof(*new)); 01428 iax_frame_wrap(new, &fr->af); 01429 new->afdatalen = afdatalen; 01430 new->data = NULL; 01431 new->datalen = 0; 01432 new->direction = DIRECTION_INGRESS; 01433 new->retrans = -1; 01434 } 01435 return new; 01436 }
static void insert_idle_thread | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 892 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, IAX_TYPE_DYNAMIC, and thread.
Referenced by iax2_process_thread().
00893 { 00894 if (thread->type == IAX_TYPE_DYNAMIC) { 00895 AST_LIST_LOCK(&dynamic_list); 00896 AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); 00897 AST_LIST_UNLOCK(&dynamic_list); 00898 } else { 00899 AST_LIST_LOCK(&idle_list); 00900 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 00901 AST_LIST_UNLOCK(&idle_list); 00902 } 00903 00904 return; 00905 }
static void jb_debug_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 797 of file chan_iax2.c.
References ast_verbose().
Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().
00798 { 00799 va_list args; 00800 char buf[1024]; 00801 00802 va_start(args, fmt); 00803 vsnprintf(buf, 1024, fmt, args); 00804 va_end(args); 00805 00806 ast_verbose(buf); 00807 }
static void jb_error_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 773 of file chan_iax2.c.
References ast_log(), and LOG_ERROR.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00774 { 00775 va_list args; 00776 char buf[1024]; 00777 00778 va_start(args, fmt); 00779 vsnprintf(buf, 1024, fmt, args); 00780 va_end(args); 00781 00782 ast_log(LOG_ERROR, buf); 00783 }
static void jb_warning_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 785 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00786 { 00787 va_list args; 00788 char buf[1024]; 00789 00790 va_start(args, fmt); 00791 vsnprintf(buf, 1024, fmt, args); 00792 va_end(args); 00793 00794 ast_log(LOG_WARNING, buf); 00795 }
static int load_module | ( | void | ) | [static] |
Load IAX2 module, load configuraiton ---.
Definition at line 11124 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, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, netsock, option_verbose, outsock, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), peers, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched, sched_context_create(), set_config(), start_network_thread(), user_cmp_cb(), user_hash_cb(), users, VERBOSE_PREFIX_2, and waresl.
11125 { 11126 char *config = "iax.conf"; 11127 int res = 0; 11128 int x; 11129 struct iax2_registry *reg = NULL; 11130 11131 peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb); 11132 if (!peers) 11133 return AST_MODULE_LOAD_FAILURE; 11134 users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb); 11135 if (!users) { 11136 ao2_ref(peers, -1); 11137 return AST_MODULE_LOAD_FAILURE; 11138 } 11139 iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb); 11140 if (!iax_peercallno_pvts) { 11141 ao2_ref(peers, -1); 11142 ao2_ref(users, -1); 11143 return AST_MODULE_LOAD_FAILURE; 11144 } 11145 11146 ast_custom_function_register(&iaxpeer_function); 11147 11148 iax_set_output(iax_debug_output); 11149 iax_set_error(iax_error_output); 11150 jb_setoutput(jb_error_output, jb_warning_output, NULL); 11151 11152 #ifdef HAVE_ZAPTEL 11153 #ifdef ZAPTEL_TIMERACK 11154 timingfd = open("/dev/zap/timer", O_RDWR); 11155 if (timingfd < 0) 11156 #endif 11157 timingfd = open("/dev/zap/pseudo", O_RDWR); 11158 if (timingfd < 0) 11159 ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno)); 11160 #elif defined(HAVE_DAHDI) 11161 #ifdef DAHDI_TIMERACK 11162 timingfd = open("/dev/dahdi/timer", O_RDWR); 11163 if (timingfd < 0) 11164 #endif 11165 timingfd = open("/dev/dahdi/pseudo", O_RDWR); 11166 if (timingfd < 0) 11167 ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno)); 11168 #endif 11169 11170 memset(iaxs, 0, sizeof(iaxs)); 11171 11172 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 11173 ast_mutex_init(&iaxsl[x]); 11174 } 11175 11176 ast_cond_init(&sched_cond, NULL); 11177 11178 io = io_context_create(); 11179 sched = sched_context_create(); 11180 11181 if (!io || !sched) { 11182 ast_log(LOG_ERROR, "Out of memory\n"); 11183 return -1; 11184 } 11185 11186 netsock = ast_netsock_list_alloc(); 11187 if (!netsock) { 11188 ast_log(LOG_ERROR, "Could not allocate netsock list.\n"); 11189 return -1; 11190 } 11191 ast_netsock_init(netsock); 11192 11193 outsock = ast_netsock_list_alloc(); 11194 if (!outsock) { 11195 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 11196 return -1; 11197 } 11198 ast_netsock_init(outsock); 11199 11200 ast_mutex_init(&waresl.lock); 11201 11202 AST_LIST_HEAD_INIT(&iaxq.queue); 11203 11204 ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 11205 11206 ast_register_application(papp, iax2_prov_app, psyn, pdescrip); 11207 11208 ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" ); 11209 ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" ); 11210 11211 if(set_config(config, 0) == -1) 11212 return AST_MODULE_LOAD_DECLINE; 11213 11214 if (ast_channel_register(&iax2_tech)) { 11215 ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2"); 11216 __unload_module(); 11217 return -1; 11218 } 11219 11220 if (ast_register_switch(&iax2_switch)) 11221 ast_log(LOG_ERROR, "Unable to register IAX switch\n"); 11222 11223 res = start_network_thread(); 11224 if (!res) { 11225 if (option_verbose > 1) 11226 ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n"); 11227 } else { 11228 ast_log(LOG_ERROR, "Unable to start network thread\n"); 11229 ast_netsock_release(netsock); 11230 ast_netsock_release(outsock); 11231 } 11232 11233 AST_LIST_LOCK(®istrations); 11234 AST_LIST_TRAVERSE(®istrations, reg, entry) 11235 iax2_do_register(reg); 11236 AST_LIST_UNLOCK(®istrations); 11237 11238 ao2_callback(peers, 0, peer_set_sock_cb, NULL); 11239 ao2_callback(peers, 0, iax2_poke_peer_cb, NULL); 11240 11241 reload_firmware(0); 11242 iax_provision_reload(); 11243 return res; 11244 }
static void lock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3514 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), DEADLOCK_AVOIDANCE, and iaxsl.
Referenced by iax2_bridge().
03515 { 03516 ast_mutex_lock(&iaxsl[callno0]); 03517 while (ast_mutex_trylock(&iaxsl[callno1])) { 03518 DEADLOCK_AVOIDANCE(&iaxsl[callno0]); 03519 } 03520 }
static int make_trunk | ( | unsigned short | callno, | |
int | locked | |||
) | [static] |
Definition at line 1476 of file chan_iax2.c.
References ARRAY_LEN, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_sched_add(), iaxsl, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, option_debug, sched, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().
Referenced by iax2_request(), and socket_process().
01477 { 01478 int x; 01479 int res= 0; 01480 struct timeval now; 01481 if (iaxs[callno]->oseqno) { 01482 ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n"); 01483 return -1; 01484 } 01485 if (callno & TRUNK_CALL_START) { 01486 ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno); 01487 return -1; 01488 } 01489 gettimeofday(&now, NULL); 01490 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01491 ast_mutex_lock(&iaxsl[x]); 01492 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01493 /* Update the two timers that should have been started */ 01494 /*! 01495 * \note We delete these before switching the slot, because if 01496 * they fire in the meantime, they will generate a warning. 01497 */ 01498 AST_SCHED_DEL(sched, iaxs[callno]->pingid); 01499 AST_SCHED_DEL(sched, iaxs[callno]->lagid); 01500 iaxs[x] = iaxs[callno]; 01501 iaxs[x]->callno = x; 01502 iaxs[callno] = NULL; 01503 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01504 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01505 if (locked) 01506 ast_mutex_unlock(&iaxsl[callno]); 01507 res = x; 01508 if (!locked) 01509 ast_mutex_unlock(&iaxsl[x]); 01510 break; 01511 } 01512 ast_mutex_unlock(&iaxsl[x]); 01513 } 01514 if (x >= ARRAY_LEN(iaxs) - 1) { 01515 ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n"); 01516 return -1; 01517 } 01518 if (option_debug) 01519 ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x); 01520 /* We move this call from a non-trunked to a trunked call */ 01521 update_max_trunk(); 01522 update_max_nontrunk(); 01523 return res; 01524 }
static int manager_iax2_show_netstats | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4755 of file chan_iax2.c.
References ast_cli_netstats(), astman_append(), RESULT_SUCCESS, and s.
Referenced by load_module().
04756 { 04757 ast_cli_netstats(s, -1, 0); 04758 astman_append(s, "\r\n"); 04759 return RESULT_SUCCESS; 04760 }
static int manager_iax2_show_peers | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4788 of file chan_iax2.c.
References __iax2_show_peers(), ast_strlen_zero(), astman_append(), astman_get_header(), and s.
Referenced by load_module().
04789 { 04790 char *a[] = { "iax2", "show", "users" }; 04791 int ret; 04792 const char *id = astman_get_header(m,"ActionID"); 04793 04794 if (!ast_strlen_zero(id)) 04795 astman_append(s, "ActionID: %s\r\n",id); 04796 ret = __iax2_show_peers(1, -1, s, 3, a ); 04797 astman_append(s, "\r\n\r\n" ); 04798 return ret; 04799 } /* /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 1442 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::callno, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, chan_iax2_pvt::transfercallno, and chan_iax2_pvt::transferring.
Referenced by __find_callno(), ao2_callback(), ast_parse_device_state(), check_blacklist(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and softhangup_exec().
01443 { 01444 if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && 01445 (cur->addr.sin_port == sin->sin_port)) { 01446 /* This is the main host */ 01447 if ( (cur->peercallno == 0 || cur->peercallno == callno) && 01448 (check_dcallno ? dcallno == cur->callno : 1) ) { 01449 /* That's us. Be sure we keep track of the peer call number */ 01450 return 1; 01451 } 01452 } 01453 if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && 01454 (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { 01455 /* We're transferring */ 01456 if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno)) 01457 return 1; 01458 } 01459 return 0; 01460 }
static void memcpy_decrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 4162 of file chan_iax2.c.
References aes_decrypt(), ast_log(), and LOG_WARNING.
Referenced by decode_frame().
04163 { 04164 #if 0 04165 /* Debug with "fake encryption" */ 04166 int x; 04167 if (len % 16) 04168 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04169 for (x=0;x<len;x++) 04170 dst[x] = src[x] ^ 0xff; 04171 #else 04172 unsigned char lastblock[16] = { 0 }; 04173 int x; 04174 while(len > 0) { 04175 aes_decrypt(src, dst, dcx); 04176 for (x=0;x<16;x++) 04177 dst[x] ^= lastblock[x]; 04178 memcpy(lastblock, src, sizeof(lastblock)); 04179 dst += 16; 04180 src += 16; 04181 len -= 16; 04182 } 04183 #endif 04184 }
static void memcpy_encrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
aes_encrypt_ctx * | ecx | |||
) | [static] |
Definition at line 4186 of file chan_iax2.c.
References aes_encrypt(), ast_log(), and LOG_WARNING.
Referenced by encrypt_frame().
04187 { 04188 #if 0 04189 /* Debug with "fake encryption" */ 04190 int x; 04191 if (len % 16) 04192 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04193 for (x=0;x<len;x++) 04194 dst[x] = src[x] ^ 0xff; 04195 #else 04196 unsigned char curblock[16] = { 0 }; 04197 int x; 04198 while(len > 0) { 04199 for (x=0;x<16;x++) 04200 curblock[x] ^= src[x]; 04201 aes_encrypt(curblock, dst, ecx); 04202 memcpy(curblock, dst, sizeof(curblock)); 04203 dst += 16; 04204 src += 16; 04205 len -= 16; 04206 } 04207 #endif 04208 }
static void merge_encryption | ( | struct chan_iax2_pvt * | p, | |
unsigned int | enc | |||
) | [static] |
Definition at line 5363 of file chan_iax2.c.
References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.
Referenced by authenticate_reply(), and socket_process().
05364 { 05365 /* Select exactly one common encryption if there are any */ 05366 p->encmethods &= enc; 05367 if (p->encmethods) { 05368 if (p->encmethods & IAX_ENCRYPT_AES128) 05369 p->encmethods = IAX_ENCRYPT_AES128; 05370 else 05371 p->encmethods = 0; 05372 } 05373 }
static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 9104 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(), f, iax2_sched_add(), iax_frame_free(), iaxq, iaxs, iaxsl, io, option_debug, sched, send_packet(), and timing_read().
Referenced by start_network_thread().
09105 { 09106 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 09107 from the network, and queue them for delivery to the channels */ 09108 int res, count, wakeup; 09109 struct iax_frame *f; 09110 09111 if (timingfd > -1) 09112 ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL); 09113 09114 for(;;) { 09115 pthread_testcancel(); 09116 09117 /* Go through the queue, sending messages which have not yet been 09118 sent, and scheduling retransmissions if appropriate */ 09119 AST_LIST_LOCK(&iaxq.queue); 09120 count = 0; 09121 wakeup = -1; 09122 AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) { 09123 if (f->sentyet) 09124 continue; 09125 09126 /* Try to lock the pvt, if we can't... don't fret - defer it till later */ 09127 if (ast_mutex_trylock(&iaxsl[f->callno])) { 09128 wakeup = 1; 09129 continue; 09130 } 09131 09132 f->sentyet++; 09133 09134 if (iaxs[f->callno]) { 09135 send_packet(f); 09136 count++; 09137 } 09138 09139 ast_mutex_unlock(&iaxsl[f->callno]); 09140 09141 if (f->retries < 0) { 09142 /* This is not supposed to be retransmitted */ 09143 AST_LIST_REMOVE_CURRENT(&iaxq.queue, list); 09144 iaxq.count--; 09145 /* Free the iax frame */ 09146 iax_frame_free(f); 09147 } else { 09148 /* We need reliable delivery. Schedule a retransmission */ 09149 f->retries++; 09150 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 09151 } 09152 } 09153 AST_LIST_TRAVERSE_SAFE_END 09154 AST_LIST_UNLOCK(&iaxq.queue); 09155 09156 pthread_testcancel(); 09157 09158 if (option_debug && count >= 20) 09159 ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count); 09160 09161 /* Now do the IO, and run scheduled tasks */ 09162 res = ast_io_wait(io, wakeup); 09163 if (res >= 0) { 09164 if (option_debug && res >= 20) 09165 ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res); 09166 } 09167 } 09168 return NULL; 09169 }
static struct chan_iax2_pvt* new_iax | ( | struct sockaddr_in * | sin, | |
const char * | host | |||
) | [static] |
Definition at line 1383 of file chan_iax2.c.
References ao2_alloc(), ao2_ref(), ast_string_field_init, ast_string_field_set, exten, jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, prefs, pvt_destructor(), and jb_conf::resync_threshold.
Referenced by __find_callno().
01384 { 01385 struct chan_iax2_pvt *tmp; 01386 jb_conf jbconf; 01387 01388 if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) { 01389 return NULL; 01390 } 01391 01392 if (ast_string_field_init(tmp, 32)) { 01393 ao2_ref(tmp, -1); 01394 tmp = NULL; 01395 return NULL; 01396 } 01397 01398 tmp->prefs = prefs; 01399 tmp->callno = 0; 01400 tmp->peercallno = 0; 01401 tmp->transfercallno = 0; 01402 tmp->bridgecallno = 0; 01403 tmp->pingid = -1; 01404 tmp->lagid = -1; 01405 tmp->autoid = -1; 01406 tmp->authid = -1; 01407 tmp->initid = -1; 01408 01409 ast_string_field_set(tmp,exten, "s"); 01410 ast_string_field_set(tmp,host, host); 01411 01412 tmp->jb = jb_new(); 01413 tmp->jbid = -1; 01414 jbconf.max_jitterbuf = maxjitterbuffer; 01415 jbconf.resync_threshold = resyncthreshold; 01416 jbconf.max_contig_interp = maxjitterinterps; 01417 jb_setconf(tmp->jb,&jbconf); 01418 01419 return tmp; 01420 }
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 3229 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().
03230 { 03231 if (ast_strlen_zero(data)) 03232 return; 03233 03234 pds->peer = strsep(&data, "/"); 03235 pds->exten = strsep(&data, "/"); 03236 pds->options = data; 03237 03238 if (pds->exten) { 03239 data = pds->exten; 03240 pds->exten = strsep(&data, "@"); 03241 pds->context = data; 03242 } 03243 03244 if (strchr(pds->peer, '@')) { 03245 data = pds->peer; 03246 pds->username = strsep(&data, "@"); 03247 pds->peer = data; 03248 } 03249 03250 if (pds->username) { 03251 data = pds->username; 03252 pds->username = strsep(&data, ":"); 03253 pds->password = data; 03254 } 03255 03256 data = pds->peer; 03257 pds->peer = strsep(&data, ":"); 03258 pds->port = data; 03259 03260 /* check for a key name wrapped in [] in the secret position, if found, 03261 move it to the key field instead 03262 */ 03263 if (pds->password && (pds->password[0] == '[')) { 03264 pds->key = ast_strip_quoted(pds->password, "[", "]"); 03265 pds->password = NULL; 03266 } 03267 }
static int peer_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1119 of file chan_iax2.c.
Referenced by load_module().
01120 { 01121 struct iax2_peer *peer = obj, *peer2 = arg; 01122 01123 return !strcmp(peer->name, peer2->name) ? CMP_MATCH | CMP_STOP : 0; 01124 }
static int peer_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 9794 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
09795 { 09796 struct iax2_peer *peer = obj; 09797 09798 ast_set_flag(peer, IAX_DELME); 09799 09800 return 0; 09801 }
static void peer_destructor | ( | void * | obj | ) | [static] |
Definition at line 9327 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().
09328 { 09329 struct iax2_peer *peer = obj; 09330 int callno = peer->callno; 09331 09332 ast_free_ha(peer->ha); 09333 09334 if (callno > 0) { 09335 ast_mutex_lock(&iaxsl[callno]); 09336 iax2_destroy(callno); 09337 ast_mutex_unlock(&iaxsl[callno]); 09338 } 09339 09340 register_peer_exten(peer, 0); 09341 09342 if (peer->dnsmgr) 09343 ast_dnsmgr_release(peer->dnsmgr); 09344 09345 ast_string_field_free_memory(peer); 09346 }
static int peer_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1109 of file chan_iax2.c.
References ast_str_hash().
Referenced by load_module().
01110 { 01111 const struct iax2_peer *peer = obj; 01112 01113 return ast_str_hash(peer->name); 01114 }
Definition at line 1166 of file chan_iax2.c.
References ao2_ref().
Referenced by __iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), reg_source_db(), socket_process(), and update_registry().
01167 { 01168 ao2_ref(peer, +1); 01169 return peer; 01170 }
static int peer_set_sock_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11095 of file chan_iax2.c.
References iax2_peer::sockfd.
Referenced by load_module().
11096 { 11097 struct iax2_peer *peer = obj; 11098 11099 if (peer->sockfd < 0) 11100 peer->sockfd = defaultsockfd; 11101 11102 return 0; 11103 }
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 9254 of file chan_iax2.c.
References ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, io, LOG_WARNING, netsock, option_debug, outsock, socket_read(), iax2_peer::sockfd, and strsep().
Referenced by build_peer().
09255 { 09256 struct sockaddr_in sin; 09257 int nonlocal = 1; 09258 int port = IAX_DEFAULT_PORTNO; 09259 int sockfd = defaultsockfd; 09260 char *tmp; 09261 char *addr; 09262 char *portstr; 09263 09264 if (!(tmp = ast_strdupa(srcaddr))) 09265 return -1; 09266 09267 addr = strsep(&tmp, ":"); 09268 portstr = tmp; 09269 09270 if (portstr) { 09271 port = atoi(portstr); 09272 if (port < 1) 09273 port = IAX_DEFAULT_PORTNO; 09274 } 09275 09276 if (!ast_get_ip(&sin, addr)) { 09277 struct ast_netsock *sock; 09278 int res; 09279 09280 sin.sin_port = 0; 09281 sin.sin_family = AF_INET; 09282 res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin)); 09283 if (res == 0) { 09284 /* ip address valid. */ 09285 sin.sin_port = htons(port); 09286 if (!(sock = ast_netsock_find(netsock, &sin))) 09287 sock = ast_netsock_find(outsock, &sin); 09288 if (sock) { 09289 sockfd = ast_netsock_sockfd(sock); 09290 nonlocal = 0; 09291 } else { 09292 unsigned int orig_saddr = sin.sin_addr.s_addr; 09293 /* INADDR_ANY matches anyway! */ 09294 sin.sin_addr.s_addr = INADDR_ANY; 09295 if (ast_netsock_find(netsock, &sin)) { 09296 sin.sin_addr.s_addr = orig_saddr; 09297 sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL); 09298 if (sock) { 09299 sockfd = ast_netsock_sockfd(sock); 09300 ast_netsock_unref(sock); 09301 nonlocal = 0; 09302 } else { 09303 nonlocal = 2; 09304 } 09305 } 09306 } 09307 } 09308 } 09309 09310 peer->sockfd = sockfd; 09311 09312 if (nonlocal == 1) { 09313 ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", 09314 srcaddr, peer->name); 09315 return -1; 09316 } else if (nonlocal == 2) { 09317 ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n", 09318 srcaddr, peer->name); 09319 return -1; 09320 } else { 09321 if (option_debug) 09322 ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); 09323 return 0; 09324 } 09325 }
static int peer_status | ( | struct iax2_peer * | peer, | |
char * | status, | |||
int | statuslen | |||
) | [static] |
peer_status: Report Peer status in character string
Definition at line 2350 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().
02351 { 02352 int res = 0; 02353 if (peer->maxms) { 02354 if (peer->lastms < 0) { 02355 ast_copy_string(status, "UNREACHABLE", statuslen); 02356 } else if (peer->lastms > peer->maxms) { 02357 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 02358 res = 1; 02359 } else if (peer->lastms) { 02360 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 02361 res = 1; 02362 } else { 02363 ast_copy_string(status, "UNKNOWN", statuslen); 02364 } 02365 } else { 02366 ast_copy_string(status, "Unmonitored", statuslen); 02367 res = -1; 02368 } 02369 return res; 02370 }
Definition at line 1172 of file chan_iax2.c.
References ao2_ref().
Referenced by __expire_registry(), __iax2_poke_noanswer(), __iax2_poke_peer_s(), __iax2_show_peers(), authenticate_reply(), build_peer(), complete_iax2_show_peer(), create_addr(), function_iaxpeer(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), iax2_prune_realtime(), iax2_show_peer(), poke_all_peers(), prune_peers(), reg_source_db(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().
01173 { 01174 ao2_ref(peer, -1); 01175 return NULL; 01176 }
static void poke_all_peers | ( | void | ) | [static] |
Definition at line 10256 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), iax2_poke_peer(), peer_unref(), and peers.
Referenced by reload_config().
10257 { 10258 struct ao2_iterator i; 10259 struct iax2_peer *peer; 10260 10261 i = ao2_iterator_init(peers, 0); 10262 while ((peer = ao2_iterator_next(&i))) { 10263 iax2_poke_peer(peer, 0); 10264 peer_unref(peer); 10265 } 10266 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 9853 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_DELME, peer_unref(), peers, and unlink_peer().
09854 { 09855 struct iax2_peer *peer; 09856 struct ao2_iterator i; 09857 09858 i = ao2_iterator_init(peers, 0); 09859 while ((peer = ao2_iterator_next(&i))) { 09860 if (ast_test_flag(peer, IAX_DELME)) 09861 unlink_peer(peer); 09862 peer_unref(peer); 09863 } 09864 }
static void prune_users | ( | void | ) | [static] |
Definition at line 9839 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().
09840 { 09841 struct iax2_user *user; 09842 struct ao2_iterator i; 09843 09844 i = ao2_iterator_init(users, 0); 09845 while ((user = ao2_iterator_next(&i))) { 09846 if (ast_test_flag(user, IAX_DELME)) 09847 ao2_unlink(users, user); 09848 user_unref(user); 09849 } 09850 }
static int pvt_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11112 of file chan_iax2.c.
References chan_iax2_pvt::frames_received, and match().
Referenced by load_module().
11113 { 11114 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 11115 11116 /* The frames_received field is used to hold whether we're matching 11117 * against a full frame or not ... */ 11118 11119 return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 11120 pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0; 11121 }
static void pvt_destructor | ( | void * | obj | ) | [static] |
Definition at line 1344 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().
01345 { 01346 struct chan_iax2_pvt *pvt = obj; 01347 struct iax_frame *cur = NULL; 01348 01349 iax2_destroy_helper(pvt); 01350 01351 /* Already gone */ 01352 ast_set_flag(pvt, IAX_ALREADYGONE); 01353 01354 AST_LIST_LOCK(&iaxq.queue); 01355 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 01356 /* Cancel any pending transmissions */ 01357 if (cur->callno == pvt->callno) { 01358 cur->retries = -1; 01359 } 01360 } 01361 AST_LIST_UNLOCK(&iaxq.queue); 01362 01363 if (pvt->reg) { 01364 pvt->reg->callno = 0; 01365 } 01366 01367 if (!pvt->owner) { 01368 jb_frame frame; 01369 if (pvt->vars) { 01370 ast_variables_destroy(pvt->vars); 01371 pvt->vars = NULL; 01372 } 01373 01374 while (jb_getall(pvt->jb, &frame) == JB_OK) { 01375 iax2_frame_free(frame.data); 01376 } 01377 01378 jb_destroy(pvt->jb); 01379 ast_string_field_free_memory(pvt); 01380 } 01381 }
static int pvt_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 11105 of file chan_iax2.c.
References chan_iax2_pvt::peercallno.
Referenced by load_module().
11106 { 11107 const struct chan_iax2_pvt *pvt = obj; 11108 11109 return pvt->peercallno; 11110 }
static int raw_hangup | ( | struct sockaddr_in * | sin, | |
unsigned short | src, | |||
unsigned short | dst, | |||
int | sockfd | |||
) | [static] |
Definition at line 5345 of file chan_iax2.c.
References AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_showframe(), ast_iax2_full_hdr::iseqno, option_debug, ast_iax2_full_hdr::oseqno, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.
Referenced by socket_process().
05346 { 05347 struct ast_iax2_full_hdr fh; 05348 fh.scallno = htons(src | IAX_FLAG_FULL); 05349 fh.dcallno = htons(dst); 05350 fh.ts = 0; 05351 fh.oseqno = 0; 05352 fh.iseqno = 0; 05353 fh.type = AST_FRAME_IAX; 05354 fh.csub = compress_subclass(IAX_COMMAND_INVAL); 05355 if (iaxdebug) 05356 iax_showframe(NULL, &fh, 0, sin, 0); 05357 if (option_debug) 05358 ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n", 05359 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst); 05360 return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin)); 05361 }
static struct iax2_peer * realtime_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 2831 of file chan_iax2.c.
References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.
02832 { 02833 struct ast_variable *var = NULL; 02834 struct ast_variable *tmp; 02835 struct iax2_peer *peer=NULL; 02836 time_t regseconds = 0, nowtime; 02837 int dynamic=0; 02838 02839 if (peername) { 02840 var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL); 02841 if (!var && sin) 02842 var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL); 02843 } else if (sin) { 02844 char porta[25]; 02845 sprintf(porta, "%d", ntohs(sin->sin_port)); 02846 var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02847 if (var) { 02848 /* We'll need the peer name in order to build the structure! */ 02849 for (tmp = var; tmp; tmp = tmp->next) { 02850 if (!strcasecmp(tmp->name, "name")) 02851 peername = tmp->value; 02852 } 02853 } 02854 } 02855 if (!var && peername) { /* Last ditch effort */ 02856 var = ast_load_realtime("iaxpeers", "name", peername, NULL); 02857 /*!\note 02858 * If this one loaded something, then we need to ensure that the host 02859 * field matched. The only reason why we can't have this as a criteria 02860 * is because we only have the IP address and the host field might be 02861 * set as a name (and the reverse PTR might not match). 02862 */ 02863 if (var && sin) { 02864 for (tmp = var; tmp; tmp = tmp->next) { 02865 if (!strcasecmp(tmp->name, "host")) { 02866 struct ast_hostent ahp; 02867 struct hostent *hp; 02868 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 02869 /* No match */ 02870 ast_variables_destroy(var); 02871 var = NULL; 02872 } 02873 break; 02874 } 02875 } 02876 } 02877 } 02878 if (!var) 02879 return NULL; 02880 02881 peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); 02882 02883 if (!peer) { 02884 ast_variables_destroy(var); 02885 return NULL; 02886 } 02887 02888 for (tmp = var; tmp; tmp = tmp->next) { 02889 /* Make sure it's not a user only... */ 02890 if (!strcasecmp(tmp->name, "type")) { 02891 if (strcasecmp(tmp->value, "friend") && 02892 strcasecmp(tmp->value, "peer")) { 02893 /* Whoops, we weren't supposed to exist! */ 02894 peer = peer_unref(peer); 02895 break; 02896 } 02897 } else if (!strcasecmp(tmp->name, "regseconds")) { 02898 ast_get_time_t(tmp->value, ®seconds, 0, NULL); 02899 } else if (!strcasecmp(tmp->name, "ipaddr")) { 02900 inet_aton(tmp->value, &(peer->addr.sin_addr)); 02901 } else if (!strcasecmp(tmp->name, "port")) { 02902 peer->addr.sin_port = htons(atoi(tmp->value)); 02903 } else if (!strcasecmp(tmp->name, "host")) { 02904 if (!strcasecmp(tmp->value, "dynamic")) 02905 dynamic = 1; 02906 } 02907 } 02908 02909 ast_variables_destroy(var); 02910 02911 if (!peer) 02912 return NULL; 02913 02914 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 02915 ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS); 02916 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) { 02917 if (peer->expire > -1) { 02918 if (!ast_sched_del(sched, peer->expire)) { 02919 peer->expire = -1; 02920 peer_unref(peer); 02921 } 02922 } 02923 peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer)); 02924 if (peer->expire == -1) 02925 peer_unref(peer); 02926 } 02927 ao2_link(peers, peer); 02928 if (ast_test_flag(peer, IAX_DYNAMIC)) 02929 reg_source_db(peer); 02930 } else { 02931 ast_set_flag(peer, IAX_TEMPONLY); 02932 } 02933 02934 if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) { 02935 time(&nowtime); 02936 if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) { 02937 memset(&peer->addr, 0, sizeof(peer->addr)); 02938 realtime_update_peer(peer->name, &peer->addr, 0); 02939 if (option_debug) 02940 ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n", 02941 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02942 } 02943 else { 02944 if (option_debug) 02945 ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n", 02946 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02947 } 02948 } 02949 02950 return peer; 02951 }
static void realtime_update_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin, | |||
time_t | regtime | |||
) | [static] |
Definition at line 3024 of file chan_iax2.c.
References ast_inet_ntoa(), and ast_update_realtime().
Referenced by __expire_registry(), update_peer(), and update_registry().
03025 { 03026 char port[10]; 03027 char regseconds[20]; 03028 03029 snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); 03030 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 03031 ast_update_realtime("iaxpeers", "name", peername, 03032 "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 03033 "regseconds", regseconds, NULL); 03034 }
static struct iax2_user* realtime_user | ( | const char * | username, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 2953 of file chan_iax2.c.
References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.
02954 { 02955 struct ast_variable *var; 02956 struct ast_variable *tmp; 02957 struct iax2_user *user=NULL; 02958 02959 var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL); 02960 if (!var) 02961 var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL); 02962 if (!var && sin) { 02963 char porta[6]; 02964 snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port)); 02965 var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02966 if (!var) 02967 var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02968 } 02969 if (!var) { /* Last ditch effort */ 02970 var = ast_load_realtime("iaxusers", "name", username, NULL); 02971 /*!\note 02972 * If this one loaded something, then we need to ensure that the host 02973 * field matched. The only reason why we can't have this as a criteria 02974 * is because we only have the IP address and the host field might be 02975 * set as a name (and the reverse PTR might not match). 02976 */ 02977 if (var) { 02978 for (tmp = var; tmp; tmp = tmp->next) { 02979 if (!strcasecmp(tmp->name, "host")) { 02980 struct ast_hostent ahp; 02981 struct hostent *hp; 02982 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 02983 /* No match */ 02984 ast_variables_destroy(var); 02985 var = NULL; 02986 } 02987 break; 02988 } 02989 } 02990 } 02991 } 02992 if (!var) 02993 return NULL; 02994 02995 tmp = var; 02996 while(tmp) { 02997 /* Make sure it's not a peer only... */ 02998 if (!strcasecmp(tmp->name, "type")) { 02999 if (strcasecmp(tmp->value, "friend") && 03000 strcasecmp(tmp->value, "user")) { 03001 return NULL; 03002 } 03003 } 03004 tmp = tmp->next; 03005 } 03006 03007 user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); 03008 03009 ast_variables_destroy(var); 03010 03011 if (!user) 03012 return NULL; 03013 03014 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 03015 ast_set_flag(user, IAX_RTCACHEFRIENDS); 03016 ao2_link(users, user); 03017 } else { 03018 ast_set_flag(user, IAX_TEMPONLY); 03019 } 03020 03021 return user; 03022 }
static void reg_source_db | ( | struct iax2_peer * | p | ) | [static] |
Definition at line 6126 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(), sched, and VERBOSE_PREFIX_3.
Referenced by build_peer(), set_config(), and temp_peer().
06127 { 06128 char data[80]; 06129 struct in_addr in; 06130 char *c, *d; 06131 if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { 06132 c = strchr(data, ':'); 06133 if (c) { 06134 *c = '\0'; 06135 c++; 06136 if (inet_aton(data, &in)) { 06137 d = strchr(c, ':'); 06138 if (d) { 06139 *d = '\0'; 06140 d++; 06141 if (option_verbose > 2) 06142 ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 06143 ast_inet_ntoa(in), atoi(c), atoi(d)); 06144 iax2_poke_peer(p, 0); 06145 p->expiry = atoi(d); 06146 memset(&p->addr, 0, sizeof(p->addr)); 06147 p->addr.sin_family = AF_INET; 06148 p->addr.sin_addr = in; 06149 p->addr.sin_port = htons(atoi(c)); 06150 if (p->expire > -1) { 06151 if (!ast_sched_del(sched, p->expire)) { 06152 p->expire = -1; 06153 peer_unref(p); 06154 } 06155 } 06156 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06157 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 06158 if (p->expire == -1) 06159 peer_unref(p); 06160 if (iax2_regfunk) 06161 iax2_regfunk(p->name, 1); 06162 register_peer_exten(p, 1); 06163 } 06164 06165 } 06166 } 06167 } 06168 }
static void register_peer_exten | ( | struct iax2_peer * | peer, | |
int | onoff | |||
) | [static] |
Definition at line 6046 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().
06047 { 06048 char multi[256]; 06049 char *stringp, *ext; 06050 if (!ast_strlen_zero(regcontext)) { 06051 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 06052 stringp = multi; 06053 while((ext = strsep(&stringp, "&"))) { 06054 if (onoff) { 06055 if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL)) 06056 ast_add_extension(regcontext, 1, ext, 1, NULL, NULL, 06057 "Noop", ast_strdup(peer->name), ast_free, "IAX2"); 06058 } else 06059 ast_context_remove_extension(regcontext, ext, 1, NULL); 06060 } 06061 } 06062 }
static int register_verify | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Verify inbound registration.
Definition at line 5509 of file chan_iax2.c.
References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, IAX_STATE_UNCHANGED, iaxs, iaxsl, ies, inaddrcmp(), LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), secret, and strsep().
Referenced by handle_request_register(), and socket_process().
05510 { 05511 char requeststr[256] = ""; 05512 char peer[256] = ""; 05513 char md5secret[256] = ""; 05514 char rsasecret[256] = ""; 05515 char secret[256] = ""; 05516 struct iax2_peer *p = NULL; 05517 struct ast_key *key; 05518 char *keyn; 05519 int x; 05520 int expire = 0; 05521 int res = -1; 05522 05523 ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED); 05524 /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */ 05525 if (ies->username) 05526 ast_copy_string(peer, ies->username, sizeof(peer)); 05527 if (ies->password) 05528 ast_copy_string(secret, ies->password, sizeof(secret)); 05529 if (ies->md5_result) 05530 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 05531 if (ies->rsa_result) 05532 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 05533 if (ies->refresh) 05534 expire = ies->refresh; 05535 05536 if (ast_strlen_zero(peer)) { 05537 ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr)); 05538 return -1; 05539 } 05540 05541 /* SLD: first call to lookup peer during registration */ 05542 ast_mutex_unlock(&iaxsl[callno]); 05543 p = find_peer(peer, 1); 05544 ast_mutex_lock(&iaxsl[callno]); 05545 if (!p || !iaxs[callno]) { 05546 if (authdebug && !p) 05547 ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05548 goto return_unref; 05549 } 05550 05551 if (!ast_test_flag(p, IAX_DYNAMIC)) { 05552 if (authdebug) 05553 ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05554 goto return_unref; 05555 } 05556 05557 if (!ast_apply_ha(p->ha, sin)) { 05558 if (authdebug) 05559 ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05560 goto return_unref; 05561 } 05562 if (!inaddrcmp(&p->addr, sin)) 05563 ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED); 05564 ast_string_field_set(iaxs[callno], secret, p->secret); 05565 ast_string_field_set(iaxs[callno], inkeys, p->inkeys); 05566 /* Check secret against what we have on file */ 05567 if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05568 if (!ast_strlen_zero(p->inkeys)) { 05569 char tmpkeys[256]; 05570 char *stringp=NULL; 05571 ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys)); 05572 stringp=tmpkeys; 05573 keyn = strsep(&stringp, ":"); 05574 while(keyn) { 05575 key = ast_key_get(keyn, AST_KEY_PUBLIC); 05576 if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) { 05577 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05578 break; 05579 } else if (!key) 05580 ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn); 05581 keyn = strsep(&stringp, ":"); 05582 } 05583 if (!keyn) { 05584 if (authdebug) 05585 ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys); 05586 goto return_unref; 05587 } 05588 } else { 05589 if (authdebug) 05590 ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer); 05591 goto return_unref; 05592 } 05593 } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05594 struct MD5Context md5; 05595 unsigned char digest[16]; 05596 char *tmppw, *stringp; 05597 05598 tmppw = ast_strdupa(p->secret); 05599 stringp = tmppw; 05600 while((tmppw = strsep(&stringp, ";"))) { 05601 MD5Init(&md5); 05602 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 05603 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05604 MD5Final(digest, &md5); 05605 for (x=0;x<16;x++) 05606 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05607 if (!strcasecmp(requeststr, md5secret)) 05608 break; 05609 } 05610 if (tmppw) { 05611 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05612 } else { 05613 if (authdebug) 05614 ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret); 05615 goto return_unref; 05616 } 05617 } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) { 05618 /* They've provided a plain text password and we support that */ 05619 if (strcmp(secret, p->secret)) { 05620 if (authdebug) 05621 ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05622 goto return_unref; 05623 } else 05624 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05625 } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) { 05626 if (authdebug) 05627 ast_log(LOG_NOTICE, "Inappropriate authentication received\n"); 05628 goto return_unref; 05629 } 05630 ast_string_field_set(iaxs[callno], peer, peer); 05631 /* Choose lowest expiry number */ 05632 if (expire && (expire < iaxs[callno]->expiry)) 05633 iaxs[callno]->expiry = expire; 05634 05635 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05636 05637 res = 0; 05638 05639 return_unref: 05640 if (p) 05641 peer_unref(p); 05642 05643 return res; 05644 }
static int registry_authrequest | ( | int | callno | ) | [static] |
Definition at line 6305 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, 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(), and send_command().
Referenced by socket_process().
06306 { 06307 struct iax_ie_data ied; 06308 struct iax2_peer *p; 06309 char challenge[10]; 06310 const char *peer_name; 06311 int res = -1; 06312 06313 peer_name = ast_strdupa(iaxs[callno]->peer); 06314 06315 /* SLD: third call to find_peer in registration */ 06316 ast_mutex_unlock(&iaxsl[callno]); 06317 p = find_peer(peer_name, 1); 06318 ast_mutex_lock(&iaxsl[callno]); 06319 if (!iaxs[callno]) 06320 goto return_unref; 06321 if (!p) { 06322 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 06323 goto return_unref; 06324 } 06325 06326 memset(&ied, 0, sizeof(ied)); 06327 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 06328 if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) { 06329 /* Build the challenge */ 06330 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 06331 ast_string_field_set(iaxs[callno], challenge, challenge); 06332 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge); 06333 } 06334 iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name); 06335 06336 res = 0; 06337 06338 return_unref: 06339 peer_unref(p); 06340 06341 return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);; 06342 }
static int registry_rerequest | ( | struct iax_ies * | ies, | |
int | callno, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 6344 of file chan_iax2.c.
References iax2_registry::addr, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, ies, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_AUTHSENT, iax2_registry::regstate, iax2_registry::secret, send_command(), and iax2_registry::username.
Referenced by socket_process().
06345 { 06346 struct iax2_registry *reg; 06347 /* Start pessimistic */ 06348 struct iax_ie_data ied; 06349 char peer[256] = ""; 06350 char challenge[256] = ""; 06351 int res; 06352 int authmethods = 0; 06353 if (ies->authmethods) 06354 authmethods = ies->authmethods; 06355 if (ies->username) 06356 ast_copy_string(peer, ies->username, sizeof(peer)); 06357 if (ies->challenge) 06358 ast_copy_string(challenge, ies->challenge, sizeof(challenge)); 06359 memset(&ied, 0, sizeof(ied)); 06360 reg = iaxs[callno]->reg; 06361 if (reg) { 06362 if (inaddrcmp(®->addr, sin)) { 06363 ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 06364 return -1; 06365 } 06366 if (ast_strlen_zero(reg->secret)) { 06367 ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); 06368 reg->regstate = REG_STATE_NOAUTH; 06369 return -1; 06370 } 06371 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 06372 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 06373 if (reg->secret[0] == '[') { 06374 char tmpkey[256]; 06375 ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); 06376 tmpkey[strlen(tmpkey) - 1] = '\0'; 06377 res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL); 06378 } else 06379 res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL); 06380 if (!res) { 06381 reg->regstate = REG_STATE_AUTHSENT; 06382 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 06383 } else 06384 return -1; 06385 ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); 06386 } else 06387 ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); 06388 return -1; 06389 }
static char* regstate2str | ( | int | regstate | ) | [static] |
Definition at line 4801 of file chan_iax2.c.
References REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED.
Referenced by handle_response_register(), iax2_show_registry(), sip_reg_timeout(), and sip_show_registry().
04802 { 04803 switch(regstate) { 04804 case REG_STATE_UNREGISTERED: 04805 return "Unregistered"; 04806 case REG_STATE_REGSENT: 04807 return "Request Sent"; 04808 case REG_STATE_AUTHSENT: 04809 return "Auth. Sent"; 04810 case REG_STATE_REGISTERED: 04811 return "Registered"; 04812 case REG_STATE_REJECTED: 04813 return "Rejected"; 04814 case REG_STATE_TIMEOUT: 04815 return "Timeout"; 04816 case REG_STATE_NOAUTH: 04817 return "No Authentication"; 04818 default: 04819 return "Unknown"; 04820 } 04821 }
static int reload | ( | void | ) | [static] |
Definition at line 10293 of file chan_iax2.c.
References reload_config().
10294 { 10295 return reload_config(); 10296 }
static int reload_config | ( | void | ) | [static] |
Definition at line 10267 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().
10268 { 10269 char *config = "iax.conf"; 10270 struct iax2_registry *reg; 10271 10272 if (set_config(config, 1) > 0) { 10273 prune_peers(); 10274 prune_users(); 10275 AST_LIST_LOCK(®istrations); 10276 AST_LIST_TRAVERSE(®istrations, reg, entry) 10277 iax2_do_register(reg); 10278 AST_LIST_UNLOCK(®istrations); 10279 /* Qualify hosts, too */ 10280 poke_all_peers(); 10281 } 10282 reload_firmware(0); 10283 iax_provision_reload(); 10284 10285 return 0; 10286 }
static void reload_firmware | ( | int | unload | ) | [static] |
Definition at line 1994 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().
01995 { 01996 struct iax_firmware *cur, *curl, *curp; 01997 DIR *fwd; 01998 struct dirent *de; 01999 char dir[256]; 02000 char fn[256]; 02001 /* Mark all as dead */ 02002 ast_mutex_lock(&waresl.lock); 02003 cur = waresl.wares; 02004 while(cur) { 02005 cur->dead = 1; 02006 cur = cur->next; 02007 } 02008 02009 /* Now that we've freed them, load the new ones */ 02010 if (!unload) { 02011 snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR); 02012 fwd = opendir(dir); 02013 if (fwd) { 02014 while((de = readdir(fwd))) { 02015 if (de->d_name[0] != '.') { 02016 snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name); 02017 if (!try_firmware(fn)) { 02018 if (option_verbose > 1) 02019 ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name); 02020 } 02021 } 02022 } 02023 closedir(fwd); 02024 } else 02025 ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno)); 02026 } 02027 02028 /* Clean up leftovers */ 02029 cur = waresl.wares; 02030 curp = NULL; 02031 while(cur) { 02032 curl = cur; 02033 cur = cur->next; 02034 if (curl->dead) { 02035 if (curp) { 02036 curp->next = cur; 02037 } else { 02038 waresl.wares = cur; 02039 } 02040 destroy_firmware(curl); 02041 } else { 02042 curp = cur; 02043 } 02044 } 02045 ast_mutex_unlock(&waresl.lock); 02046 }
static void remove_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1257 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().
01258 { 01259 if (!pvt->peercallno) { 01260 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01261 return; 01262 } 01263 01264 ao2_unlink(iax_peercallno_pvts, pvt); 01265 }
Definition at line 6848 of file chan_iax2.c.
References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iaxs, ies, iax_rr::jitter, iax_rr::losscnt, iax_rr::losspct, iax_rr::ooo, iax_rr::packets, and chan_iax2_pvt::remote_rr.
Referenced by socket_process().
06849 { 06850 iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter; 06851 iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24; 06852 iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff; 06853 iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts; 06854 iaxs[fr->callno]->remote_rr.delay = ies->rr_delay; 06855 iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped; 06856 iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; 06857 }
static void* sched_thread | ( | void * | ignore | ) | [static] |
Definition at line 9077 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(), option_debug, and sched.
Referenced by start_network_thread().
09078 { 09079 int count; 09080 int res; 09081 struct timeval tv; 09082 struct timespec ts; 09083 09084 for (;;) { 09085 pthread_testcancel(); 09086 ast_mutex_lock(&sched_lock); 09087 res = ast_sched_wait(sched); 09088 if ((res > 1000) || (res < 0)) 09089 res = 1000; 09090 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); 09091 ts.tv_sec = tv.tv_sec; 09092 ts.tv_nsec = tv.tv_usec * 1000; 09093 ast_cond_timedwait(&sched_cond, &sched_lock, &ts); 09094 ast_mutex_unlock(&sched_lock); 09095 pthread_testcancel(); 09096 09097 count = ast_sched_runq(sched); 09098 if (option_debug && count >= 20) 09099 ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); 09100 } 09101 return NULL; 09102 }
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 2684 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, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, len, LOG_DEBUG, option_debug, ast_channel_tech::properties, sched, ast_channel::tech, iax_frame::ts, type, unwrap_timestamp(), and update_jbsched().
Referenced by socket_process().
02685 { 02686 int type, len; 02687 int ret; 02688 int needfree = 0; 02689 struct ast_channel *owner = NULL; 02690 struct ast_channel *bridge = NULL; 02691 02692 /* Attempt to recover wrapped timestamps */ 02693 unwrap_timestamp(fr); 02694 02695 /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */ 02696 if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) 02697 fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000)); 02698 else { 02699 #if 0 02700 if (option_debug) 02701 ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n"); 02702 #endif 02703 fr->af.delivery = ast_tv(0,0); 02704 } 02705 02706 type = JB_TYPE_CONTROL; 02707 len = 0; 02708 02709 if(fr->af.frametype == AST_FRAME_VOICE) { 02710 type = JB_TYPE_VOICE; 02711 len = ast_codec_get_samples(&fr->af) / 8; 02712 } else if(fr->af.frametype == AST_FRAME_CNG) { 02713 type = JB_TYPE_SILENCE; 02714 } 02715 02716 if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) { 02717 if (tsout) 02718 *tsout = fr->ts; 02719 __do_deliver(fr); 02720 return -1; 02721 } 02722 02723 if ((owner = iaxs[fr->callno]->owner)) 02724 bridge = ast_bridged_channel(owner); 02725 02726 /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to 02727 * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */ 02728 if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) { 02729 jb_frame frame; 02730 02731 /* deliver any frames in the jb */ 02732 while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { 02733 __do_deliver(frame.data); 02734 /* __do_deliver() can make the call disappear */ 02735 if (!iaxs[fr->callno]) 02736 return -1; 02737 } 02738 02739 jb_reset(iaxs[fr->callno]->jb); 02740 02741 AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid); 02742 02743 /* deliver this frame now */ 02744 if (tsout) 02745 *tsout = fr->ts; 02746 __do_deliver(fr); 02747 return -1; 02748 } 02749 02750 /* insert into jitterbuffer */ 02751 /* TODO: Perhaps we could act immediately if it's not droppable and late */ 02752 ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts, 02753 calc_rxstamp(iaxs[fr->callno],fr->ts)); 02754 if (ret == JB_DROP) { 02755 needfree++; 02756 } else if (ret == JB_SCHED) { 02757 update_jbsched(iaxs[fr->callno]); 02758 } 02759 if (tsout) 02760 *tsout = fr->ts; 02761 if (needfree) { 02762 /* Free our iax frame */ 02763 iax2_frame_free(fr); 02764 return -1; 02765 } 02766 return 0; 02767 }
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 3202 of file chan_iax2.c.
References AST_FRAME_IAX, compress_subclass(), and f.
Referenced by socket_process().
03203 { 03204 struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno), 03205 .ts = htonl(ts), .iseqno = seqno, .oseqno = seqno, .type = AST_FRAME_IAX, 03206 .csub = compress_subclass(command) }; 03207 03208 return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin)); 03209 }
static int send_command | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5085 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().
05086 { 05087 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); 05088 }
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 5104 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().
05105 { 05106 int call_num = i->callno; 05107 /* It is assumed that the callno has already been locked */ 05108 iax2_predestroy(i->callno); 05109 if (!iaxs[call_num]) 05110 return -1; 05111 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1); 05112 }
static int send_command_immediate | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5114 of file chan_iax2.c.
References __send_command().
Referenced by iax2_vnak(), and socket_process().
05115 { 05116 return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0); 05117 }
static int send_command_locked | ( | unsigned short | callno, | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5090 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().
05091 { 05092 int res; 05093 ast_mutex_lock(&iaxsl[callno]); 05094 res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno); 05095 ast_mutex_unlock(&iaxsl[callno]); 05096 return res; 05097 }
static int send_command_transfer | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | ||||
) | [static] |
Definition at line 5119 of file chan_iax2.c.
References __send_command().
Referenced by socket_process(), and try_transfer().
05120 { 05121 return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0); 05122 }
static int send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1062 of file chan_iax2.c.
References __send_lagrq(), and schedule_action.
Referenced by __find_callno(), __send_lagrq(), and make_trunk().
01063 { 01064 #ifdef SCHED_MULTITHREADED 01065 if (schedule_action(__send_lagrq, data)) 01066 #endif 01067 __send_lagrq(data); 01068 01069 return 0; 01070 }
static int send_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2119 of file chan_iax2.c.
References chan_iax2_pvt::addr, ast_inet_ntoa(), ast_log(), errno, f, handle_error(), iax_showframe(), iaxs, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, and transfer.
Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().
02120 { 02121 int res; 02122 int callno = f->callno; 02123 02124 /* Don't send if there was an error, but return error instead */ 02125 if (!callno || !iaxs[callno] || iaxs[callno]->error) 02126 return -1; 02127 02128 /* Called with iaxsl held */ 02129 if (option_debug > 2 && iaxdebug) 02130 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)); 02131 if (f->transfer) { 02132 if (iaxdebug) 02133 iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02134 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, 02135 sizeof(iaxs[callno]->transfer)); 02136 } else { 02137 if (iaxdebug) 02138 iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02139 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, 02140 sizeof(iaxs[callno]->addr)); 02141 } 02142 if (res < 0) { 02143 if (option_debug && iaxdebug) 02144 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 02145 handle_error(); 02146 } else 02147 res = 0; 02148 return res; 02149 }
static int send_ping | ( | const void * | data | ) | [static] |
Definition at line 1017 of file chan_iax2.c.
References __send_ping(), and schedule_action.
Referenced by __find_callno(), __send_ping(), and make_trunk().
01018 { 01019 #ifdef SCHED_MULTITHREADED 01020 if (schedule_action(__send_ping, data)) 01021 #endif 01022 __send_ping(data); 01023 01024 return 0; 01025 }
static int send_trunk | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [static] |
Definition at line 6526 of file chan_iax2.c.
References iax2_trunk_peer::addr, iax_frame::afdata, ast_inet_ntoa(), ast_log(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, globalflags, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_hdr::metacmd, option_debug, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.
Referenced by timing_read().
06527 { 06528 int res = 0; 06529 struct iax_frame *fr; 06530 struct ast_iax2_meta_hdr *meta; 06531 struct ast_iax2_meta_trunk_hdr *mth; 06532 int calls = 0; 06533 06534 /* Point to frame */ 06535 fr = (struct iax_frame *)tpeer->trunkdata; 06536 /* Point to meta data */ 06537 meta = (struct ast_iax2_meta_hdr *)fr->afdata; 06538 mth = (struct ast_iax2_meta_trunk_hdr *)meta->data; 06539 if (tpeer->trunkdatalen) { 06540 /* We're actually sending a frame, so fill the meta trunk header and meta header */ 06541 meta->zeros = 0; 06542 meta->metacmd = IAX_META_TRUNK; 06543 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) 06544 meta->cmddata = IAX_META_TRUNK_MINI; 06545 else 06546 meta->cmddata = IAX_META_TRUNK_SUPERMINI; 06547 mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now)); 06548 /* And the rest of the ast_iax2 header */ 06549 fr->direction = DIRECTION_OUTGRESS; 06550 fr->retrans = -1; 06551 fr->transfer = 0; 06552 /* Any appropriate call will do */ 06553 fr->data = fr->afdata; 06554 fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr); 06555 res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd); 06556 calls = tpeer->calls; 06557 #if 0 06558 if (option_debug) 06559 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)); 06560 #endif 06561 /* Reset transmit trunk side data */ 06562 tpeer->trunkdatalen = 0; 06563 tpeer->calls = 0; 06564 } 06565 if (res < 0) 06566 return res; 06567 return calls; 06568 }
static int set_config | ( | char * | config_file, | |
int | reload | |||
) | [static] |
Load configuration.
Definition at line 9897 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(), globalflags, iax2_register(), IAX_ALLOWFWDOWNLOAD, IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_RTUPDATE, IAX_TRANSFERMEDIA, IAX_TRUNKTIMESTAMPS, IAX_USEJITTERBUF, iaxmaxthreadcount, iaxthreadcount, io, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_PEER_BUCKETS, ast_variable::name, netsock, ast_variable::next, option_verbose, outsock, peer_unref(), peers, portno, prefs, reg_source_db(), 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().
09898 { 09899 struct ast_config *cfg, *ucfg; 09900 int capability=iax2_capability; 09901 struct ast_variable *v; 09902 char *cat; 09903 const char *utype; 09904 const char *tosval; 09905 int format; 09906 int portno = IAX_DEFAULT_PORTNO; 09907 int x; 09908 struct iax2_user *user; 09909 struct iax2_peer *peer; 09910 struct ast_netsock *ns; 09911 #if 0 09912 static unsigned short int last_port=0; 09913 #endif 09914 09915 cfg = ast_config_load(config_file); 09916 09917 if (!cfg) { 09918 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 09919 return -1; 09920 } 09921 09922 if (reload) { 09923 set_config_destroy(); 09924 } 09925 09926 /* Reset global codec prefs */ 09927 memset(&prefs, 0 , sizeof(struct ast_codec_pref)); 09928 09929 /* Reset Global Flags */ 09930 memset(&globalflags, 0, sizeof(globalflags)); 09931 ast_set_flag(&globalflags, IAX_RTUPDATE); 09932 09933 #ifdef SO_NO_CHECK 09934 nochecksums = 0; 09935 #endif 09936 09937 min_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09938 max_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09939 09940 maxauthreq = 3; 09941 09942 v = ast_variable_browse(cfg, "general"); 09943 09944 /* Seed initial tos value */ 09945 tosval = ast_variable_retrieve(cfg, "general", "tos"); 09946 if (tosval) { 09947 if (ast_str2tos(tosval, &tos)) 09948 ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n"); 09949 } 09950 while(v) { 09951 if (!strcasecmp(v->name, "bindport")){ 09952 if (reload) 09953 ast_log(LOG_NOTICE, "Ignoring bindport on reload\n"); 09954 else 09955 portno = atoi(v->value); 09956 } else if (!strcasecmp(v->name, "pingtime")) 09957 ping_time = atoi(v->value); 09958 else if (!strcasecmp(v->name, "iaxthreadcount")) { 09959 if (reload) { 09960 if (atoi(v->value) != iaxthreadcount) 09961 ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n"); 09962 } else { 09963 iaxthreadcount = atoi(v->value); 09964 if (iaxthreadcount < 1) { 09965 ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n"); 09966 iaxthreadcount = 1; 09967 } else if (iaxthreadcount > 256) { 09968 ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n"); 09969 iaxthreadcount = 256; 09970 } 09971 } 09972 } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) { 09973 if (reload) { 09974 AST_LIST_LOCK(&dynamic_list); 09975 iaxmaxthreadcount = atoi(v->value); 09976 AST_LIST_UNLOCK(&dynamic_list); 09977 } else { 09978 iaxmaxthreadcount = atoi(v->value); 09979 if (iaxmaxthreadcount < 0) { 09980 ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n"); 09981 iaxmaxthreadcount = 0; 09982 } else if (iaxmaxthreadcount > 256) { 09983 ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n"); 09984 iaxmaxthreadcount = 256; 09985 } 09986 } 09987 } else if (!strcasecmp(v->name, "nochecksums")) { 09988 #ifdef SO_NO_CHECK 09989 if (ast_true(v->value)) 09990 nochecksums = 1; 09991 else 09992 nochecksums = 0; 09993 #else 09994 if (ast_true(v->value)) 09995 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 09996 #endif 09997 } 09998 else if (!strcasecmp(v->name, "maxjitterbuffer")) 09999 maxjitterbuffer = atoi(v->value); 10000 else if (!strcasecmp(v->name, "resyncthreshold")) 10001 resyncthreshold = atoi(v->value); 10002 else if (!strcasecmp(v->name, "maxjitterinterps")) 10003 maxjitterinterps = atoi(v->value); 10004 else if (!strcasecmp(v->name, "lagrqtime")) 10005 lagrq_time = atoi(v->value); 10006 else if (!strcasecmp(v->name, "maxregexpire")) 10007 max_reg_expire = atoi(v->value); 10008 else if (!strcasecmp(v->name, "minregexpire")) 10009 min_reg_expire = atoi(v->value); 10010 else if (!strcasecmp(v->name, "bindaddr")) { 10011 if (reload) { 10012 ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n"); 10013 } else { 10014 if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) { 10015 ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno); 10016 } else { 10017 if (option_verbose > 1) { 10018 if (strchr(v->value, ':')) 10019 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value); 10020 else 10021 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno); 10022 } 10023 if (defaultsockfd < 0) 10024 defaultsockfd = ast_netsock_sockfd(ns); 10025 ast_netsock_unref(ns); 10026 } 10027 } 10028 } else if (!strcasecmp(v->name, "authdebug")) 10029 authdebug = ast_true(v->value); 10030 else if (!strcasecmp(v->name, "encryption")) 10031 iax2_encryption = get_encrypt_methods(v->value); 10032 else if (!strcasecmp(v->name, "notransfer")) { 10033 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 10034 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 10035 ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER); 10036 } else if (!strcasecmp(v->name, "transfer")) { 10037 if (!strcasecmp(v->value, "mediaonly")) { 10038 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 10039 } else if (ast_true(v->value)) { 10040 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 10041 } else 10042 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 10043 } else if (!strcasecmp(v->name, "codecpriority")) { 10044 if(!strcasecmp(v->value, "caller")) 10045 ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST); 10046 else if(!strcasecmp(v->value, "disabled")) 10047 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 10048 else if(!strcasecmp(v->value, "reqonly")) { 10049 ast_set_flag((&globalflags), IAX_CODEC_NOCAP); 10050 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 10051 } 10052 } else if (!strcasecmp(v->name, "jitterbuffer")) 10053 ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 10054 else if (!strcasecmp(v->name, "forcejitterbuffer")) 10055 ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF); 10056 else if (!strcasecmp(v->name, "delayreject")) 10057 delayreject = ast_true(v->value); 10058 else if (!strcasecmp(v->name, "allowfwdownload")) 10059 ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD); 10060 else if (!strcasecmp(v->name, "rtcachefriends")) 10061 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS); 10062 else if (!strcasecmp(v->name, "rtignoreregexpire")) 10063 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE); 10064 else if (!strcasecmp(v->name, "rtupdate")) 10065 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE); 10066 else if (!strcasecmp(v->name, "trunktimestamps")) 10067 ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS); 10068 else if (!strcasecmp(v->name, "rtautoclear")) { 10069 int i = atoi(v->value); 10070 if(i > 0) 10071 global_rtautoclear = i; 10072 else 10073 i = 0; 10074 ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR); 10075 } else if (!strcasecmp(v->name, "trunkfreq")) { 10076 trunkfreq = atoi(v->value); 10077 if (trunkfreq < 10) 10078 trunkfreq = 10; 10079 } else if (!strcasecmp(v->name, "autokill")) { 10080 if (sscanf(v->value, "%d", &x) == 1) { 10081 if (x >= 0) 10082 autokill = x; 10083 else 10084 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 10085 } else if (ast_true(v->value)) { 10086 autokill = DEFAULT_MAXMS; 10087 } else { 10088 autokill = 0; 10089 } 10090 } else if (!strcasecmp(v->name, "bandwidth")) { 10091 if (!strcasecmp(v->value, "low")) { 10092 capability = IAX_CAPABILITY_LOWBANDWIDTH; 10093 } else if (!strcasecmp(v->value, "medium")) { 10094 capability = IAX_CAPABILITY_MEDBANDWIDTH; 10095 } else if (!strcasecmp(v->value, "high")) { 10096 capability = IAX_CAPABILITY_FULLBANDWIDTH; 10097 } else 10098 ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); 10099 } else if (!strcasecmp(v->name, "allow")) { 10100 ast_parse_allow_disallow(&prefs, &capability, v->value, 1); 10101 } else if (!strcasecmp(v->name, "disallow")) { 10102 ast_parse_allow_disallow(&prefs, &capability, v->value, 0); 10103 } else if (!strcasecmp(v->name, "register")) { 10104 iax2_register(v->value, v->lineno); 10105 } else if (!strcasecmp(v->name, "iaxcompat")) { 10106 iaxcompat = ast_true(v->value); 10107 } else if (!strcasecmp(v->name, "regcontext")) { 10108 ast_copy_string(regcontext, v->value, sizeof(regcontext)); 10109 /* Create context if it doesn't exist already */ 10110 if (!ast_context_find(regcontext)) 10111 ast_context_create(NULL, regcontext, "IAX2"); 10112 } else if (!strcasecmp(v->name, "tos")) { 10113 if (ast_str2tos(v->value, &tos)) 10114 ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno); 10115 } else if (!strcasecmp(v->name, "accountcode")) { 10116 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 10117 } else if (!strcasecmp(v->name, "mohinterpret")) { 10118 ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); 10119 } else if (!strcasecmp(v->name, "mohsuggest")) { 10120 ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest)); 10121 } else if (!strcasecmp(v->name, "amaflags")) { 10122 format = ast_cdr_amaflags2int(v->value); 10123 if (format < 0) { 10124 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 10125 } else { 10126 amaflags = format; 10127 } 10128 } else if (!strcasecmp(v->name, "language")) { 10129 ast_copy_string(language, v->value, sizeof(language)); 10130 } else if (!strcasecmp(v->name, "maxauthreq")) { 10131 maxauthreq = atoi(v->value); 10132 if (maxauthreq < 0) 10133 maxauthreq = 0; 10134 } else if (!strcasecmp(v->name, "adsi")) { 10135 adsi = ast_true(v->value); 10136 } /*else if (strcasecmp(v->name,"type")) */ 10137 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 10138 v = v->next; 10139 } 10140 10141 if (defaultsockfd < 0) { 10142 if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) { 10143 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 10144 } else { 10145 if (option_verbose > 1) 10146 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno); 10147 defaultsockfd = ast_netsock_sockfd(ns); 10148 ast_netsock_unref(ns); 10149 } 10150 } 10151 if (reload) { 10152 ast_netsock_release(outsock); 10153 outsock = ast_netsock_list_alloc(); 10154 if (!outsock) { 10155 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 10156 return -1; 10157 } 10158 ast_netsock_init(outsock); 10159 } 10160 10161 if (min_reg_expire > max_reg_expire) { 10162 ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n", 10163 min_reg_expire, max_reg_expire, max_reg_expire); 10164 min_reg_expire = max_reg_expire; 10165 } 10166 iax2_capability = capability; 10167 10168 ucfg = ast_config_load("users.conf"); 10169 if (ucfg) { 10170 struct ast_variable *gen; 10171 int genhasiax; 10172 int genregisteriax; 10173 const char *hasiax, *registeriax; 10174 10175 genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); 10176 genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); 10177 gen = ast_variable_browse(ucfg, "general"); 10178 cat = ast_category_browse(ucfg, NULL); 10179 while (cat) { 10180 if (strcasecmp(cat, "general")) { 10181 hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); 10182 registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); 10183 if (ast_true(hasiax) || (!hasiax && genhasiax)) { 10184 /* Start with general parameters, then specific parameters, user and peer */ 10185 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 10186 if (user) { 10187 __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10188 user = user_unref(user); 10189 } 10190 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 10191 if (peer) { 10192 if (ast_test_flag(peer, IAX_DYNAMIC)) 10193 reg_source_db(peer); 10194 __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10195 peer = peer_unref(peer); 10196 } 10197 } 10198 if (ast_true(registeriax) || (!registeriax && genregisteriax)) { 10199 char tmp[256]; 10200 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 10201 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 10202 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 10203 if (!host) 10204 host = ast_variable_retrieve(ucfg, "general", "host"); 10205 if (!username) 10206 username = ast_variable_retrieve(ucfg, "general", "username"); 10207 if (!secret) 10208 secret = ast_variable_retrieve(ucfg, "general", "secret"); 10209 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 10210 if (!ast_strlen_zero(secret)) 10211 snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); 10212 else 10213 snprintf(tmp, sizeof(tmp), "%s@%s", username, host); 10214 iax2_register(tmp, 0); 10215 } 10216 } 10217 } 10218 cat = ast_category_browse(ucfg, cat); 10219 } 10220 ast_config_destroy(ucfg); 10221 } 10222 10223 cat = ast_category_browse(cfg, NULL); 10224 while(cat) { 10225 if (strcasecmp(cat, "general")) { 10226 utype = ast_variable_retrieve(cfg, cat, "type"); 10227 if (utype) { 10228 if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { 10229 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 10230 if (user) { 10231 __ao2_link(users, user, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10232 user = user_unref(user); 10233 } 10234 } 10235 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { 10236 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 10237 if (peer) { 10238 if (ast_test_flag(peer, IAX_DYNAMIC)) 10239 reg_source_db(peer); 10240 __ao2_link(peers, peer, (MAX_PEER_BUCKETS == 1) ? 1 : 0); 10241 peer = peer_unref(peer); 10242 } 10243 } else if (strcasecmp(utype, "user")) { 10244 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file); 10245 } 10246 } else 10247 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 10248 } 10249 cat = ast_category_browse(cfg, cat); 10250 } 10251 ast_config_destroy(cfg); 10252 set_timing(); 10253 return 1; 10254 }
static void set_config_destroy | ( | void | ) | [static] |
Definition at line 9881 of file chan_iax2.c.
References ast_clear_flag, delete_users(), globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, and IAX_USEJITTERBUF.
Referenced by set_config().
09882 { 09883 strcpy(accountcode, ""); 09884 strcpy(language, ""); 09885 strcpy(mohinterpret, "default"); 09886 strcpy(mohsuggest, ""); 09887 amaflags = 0; 09888 delayreject = 0; 09889 ast_clear_flag((&globalflags), IAX_NOTRANSFER); 09890 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 09891 ast_clear_flag((&globalflags), IAX_USEJITTERBUF); 09892 ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF); 09893 delete_users(); 09894 }
static void set_timing | ( | void | ) | [static] |
Definition at line 9866 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by set_config().
09867 { 09868 #ifdef HAVE_DAHDI 09869 int bs = trunkfreq * 8; 09870 if (timingfd > -1) { 09871 if ( 09872 #ifdef DAHDI_TIMERACK 09873 ioctl(timingfd, DAHDI_TIMERCONFIG, &bs) && 09874 #endif 09875 ioctl(timingfd, DAHDI_SET_BLOCKSIZE, &bs)) 09876 ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n"); 09877 } 09878 #endif 09879 }
static void signal_condition | ( | ast_mutex_t * | lock, | |
ast_cond_t * | cond | |||
) | [static] |
Definition at line 755 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().
00756 { 00757 ast_mutex_lock(lock); 00758 ast_cond_signal(cond); 00759 ast_mutex_unlock(lock); 00760 }
static int socket_process | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 7000 of file chan_iax2.c.
References 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(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax2_peer::callno, iax2_dpcache::callno, iax_frame::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, check_access(), check_provisioning(), cid_num, complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, DEADLOCK_AVOIDANCE, decrypt_frame(), dp_lookup(), EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), find_callno_locked(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, format, chan_iax2_pvt::frames_received, ast_frame::frametype, globalflags, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_vnak(), IAX_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iaxfrdup2(), iaxq, iaxs, iaxsl, ies, inaddrcmp(), chan_iax2_pvt::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_iax2_meta_trunk_mini::len, len, iax2_trunk_peer::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, NEW_ALLOW, NEW_PREVENT, option_debug, option_verbose, iax_frame::oseqno, pbx_builtin_setvar_helper(), iax2_dpcache::peer, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, raw_hangup(), REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, save_rr(), sched, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax2_peer::smoothing, spawn_dp_lookup(), stop_stuff(), store_by_peercallno(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), iax_frame::ts, ast_iax2_mini_hdr::ts, uncompress_subclass(), update_registry(), VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.
Referenced by handle_deferred_full_frames().
07001 { 07002 struct sockaddr_in sin; 07003 int res; 07004 int updatehistory=1; 07005 int new = NEW_PREVENT; 07006 void *ptr; 07007 int dcallno = 0; 07008 struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf; 07009 struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf; 07010 struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf; 07011 struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf; 07012 struct ast_iax2_meta_trunk_hdr *mth; 07013 struct ast_iax2_meta_trunk_entry *mte; 07014 struct ast_iax2_meta_trunk_mini *mtm; 07015 struct iax_frame *fr; 07016 struct iax_frame *cur; 07017 struct ast_frame f = { 0, }; 07018 struct ast_channel *c; 07019 struct iax2_dpcache *dp; 07020 struct iax2_peer *peer; 07021 struct iax2_trunk_peer *tpeer; 07022 struct timeval rxtrunktime; 07023 struct iax_ies ies; 07024 struct iax_ie_data ied0, ied1; 07025 int format; 07026 int fd; 07027 int exists; 07028 int minivid = 0; 07029 unsigned int ts; 07030 char empty[32]=""; /* Safety measure */ 07031 struct iax_frame *duped_fr; 07032 char host_pref_buf[128]; 07033 char caller_pref_buf[128]; 07034 struct ast_codec_pref pref; 07035 char *using_prefs = "mine"; 07036 07037 /* allocate an iax_frame with 4096 bytes of data buffer */ 07038 fr = alloca(sizeof(*fr) + 4096); 07039 memset(fr, 0, sizeof(*fr)); 07040 fr->afdatalen = 4096; /* From alloca() above */ 07041 07042 /* Copy frequently used parameters to the stack */ 07043 res = thread->buf_len; 07044 fd = thread->iofd; 07045 memcpy(&sin, &thread->iosin, sizeof(sin)); 07046 07047 if (res < sizeof(*mh)) { 07048 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh)); 07049 return 1; 07050 } 07051 if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { 07052 if (res < sizeof(*vh)) { 07053 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)); 07054 return 1; 07055 } 07056 07057 /* This is a video frame, get call number */ 07058 fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0); 07059 minivid = 1; 07060 } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) { 07061 unsigned char metatype; 07062 07063 if (res < sizeof(*meta)) { 07064 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)); 07065 return 1; 07066 } 07067 07068 /* This is a meta header */ 07069 switch(meta->metacmd) { 07070 case IAX_META_TRUNK: 07071 if (res < (sizeof(*meta) + sizeof(*mth))) { 07072 ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res, 07073 sizeof(*meta) + sizeof(*mth)); 07074 return 1; 07075 } 07076 mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data); 07077 ts = ntohl(mth->ts); 07078 metatype = meta->cmddata; 07079 res -= (sizeof(*meta) + sizeof(*mth)); 07080 ptr = mth->data; 07081 tpeer = find_tpeer(&sin, fd); 07082 if (!tpeer) { 07083 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)); 07084 return 1; 07085 } 07086 tpeer->trunkact = ast_tvnow(); 07087 if (!ts || ast_tvzero(tpeer->rxtrunktime)) 07088 tpeer->rxtrunktime = tpeer->trunkact; 07089 rxtrunktime = tpeer->rxtrunktime; 07090 ast_mutex_unlock(&tpeer->lock); 07091 while(res >= sizeof(*mte)) { 07092 /* Process channels */ 07093 unsigned short callno, trunked_ts, len; 07094 07095 if (metatype == IAX_META_TRUNK_MINI) { 07096 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 07097 ptr += sizeof(*mtm); 07098 res -= sizeof(*mtm); 07099 len = ntohs(mtm->len); 07100 callno = ntohs(mtm->mini.callno); 07101 trunked_ts = ntohs(mtm->mini.ts); 07102 } else if (metatype == IAX_META_TRUNK_SUPERMINI) { 07103 mte = (struct ast_iax2_meta_trunk_entry *)ptr; 07104 ptr += sizeof(*mte); 07105 res -= sizeof(*mte); 07106 len = ntohs(mte->len); 07107 callno = ntohs(mte->callno); 07108 trunked_ts = 0; 07109 } else { 07110 ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07111 break; 07112 } 07113 /* Stop if we don't have enough data */ 07114 if (len > res) 07115 break; 07116 fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, fd, 0); 07117 if (fr->callno) { 07118 /* If it's a valid call, deliver the contents. If not, we 07119 drop it, since we don't have a scallno to use for an INVAL */ 07120 /* Process as a mini frame */ 07121 memset(&f, 0, sizeof(f)); 07122 f.frametype = AST_FRAME_VOICE; 07123 if (iaxs[fr->callno]) { 07124 if (iaxs[fr->callno]->voiceformat > 0) { 07125 f.subclass = iaxs[fr->callno]->voiceformat; 07126 f.datalen = len; 07127 if (f.datalen >= 0) { 07128 if (f.datalen) 07129 f.data = ptr; 07130 if(trunked_ts) { 07131 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff); 07132 } else 07133 fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts); 07134 /* Don't pass any packets until we're started */ 07135 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07136 /* Common things */ 07137 f.src = "IAX2"; 07138 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 07139 f.samples = ast_codec_get_samples(&f); 07140 iax_frame_wrap(fr, &f); 07141 duped_fr = iaxfrdup2(fr); 07142 if (duped_fr) { 07143 schedule_delivery(duped_fr, updatehistory, 1, &fr->ts); 07144 } 07145 /* It is possible for the pvt structure to go away after we call schedule_delivery */ 07146 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 07147 iaxs[fr->callno]->last = fr->ts; 07148 #if 1 07149 if (option_debug && iaxdebug) 07150 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 07151 #endif 07152 } 07153 } 07154 } else { 07155 ast_log(LOG_WARNING, "Datalen < 0?\n"); 07156 } 07157 } else { 07158 ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n"); 07159 iax2_vnak(fr->callno); 07160 } 07161 } 07162 ast_mutex_unlock(&iaxsl[fr->callno]); 07163 } 07164 ptr += len; 07165 res -= len; 07166 } 07167 07168 } 07169 return 1; 07170 } 07171 07172 #ifdef DEBUG_SUPPORT 07173 if (iaxdebug && (res >= sizeof(*fh))) 07174 iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh)); 07175 #endif 07176 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07177 if (res < sizeof(*fh)) { 07178 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)); 07179 return 1; 07180 } 07181 07182 /* Get the destination call number */ 07183 dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; 07184 /* Retrieve the type and subclass */ 07185 f.frametype = fh->type; 07186 if (f.frametype == AST_FRAME_VIDEO) { 07187 f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 07188 } else { 07189 f.subclass = uncompress_subclass(fh->csub); 07190 } 07191 07192 /* Deal with POKE/PONG without allocating a callno */ 07193 if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) { 07194 /* Reply back with a PONG, but don't care about the result. */ 07195 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohs(fh->ts), fh->oseqno); 07196 return 1; 07197 } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) { 07198 /* Ignore */ 07199 return 1; 07200 } 07201 07202 if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) || 07203 (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) || 07204 (f.subclass == IAX_COMMAND_REGREL))) 07205 new = NEW_ALLOW; 07206 } else { 07207 /* Don't know anything about it yet */ 07208 f.frametype = AST_FRAME_NULL; 07209 f.subclass = 0; 07210 } 07211 07212 if (!fr->callno) { 07213 int check_dcallno = 0; 07214 07215 /* 07216 * We enforce accurate destination call numbers for all full frames except 07217 * LAGRQ and PING commands. This is because older versions of Asterisk 07218 * schedule these commands to get sent very quickly, and they will sometimes 07219 * be sent before they receive the first frame from the other side. When 07220 * that happens, it doesn't contain the destination call number. However, 07221 * not checking it for these frames is safe. 07222 * 07223 * Discussed in the following thread: 07224 * http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 07225 */ 07226 07227 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07228 check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1; 07229 } 07230 07231 fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno); 07232 } 07233 07234 if (fr->callno > 0) 07235 ast_mutex_lock(&iaxsl[fr->callno]); 07236 07237 if (!fr->callno || !iaxs[fr->callno]) { 07238 /* A call arrived for a nonexistent destination. Unless it's an "inval" 07239 frame, reply with an inval */ 07240 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07241 /* We can only raw hangup control frames */ 07242 if (((f.subclass != IAX_COMMAND_INVAL) && 07243 (f.subclass != IAX_COMMAND_TXCNT) && 07244 (f.subclass != IAX_COMMAND_TXACC) && 07245 (f.subclass != IAX_COMMAND_FWDOWNL))|| 07246 (f.frametype != AST_FRAME_IAX)) 07247 raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL, 07248 fd); 07249 } 07250 if (fr->callno > 0) 07251 ast_mutex_unlock(&iaxsl[fr->callno]); 07252 return 1; 07253 } 07254 if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) { 07255 if (decrypt_frame(fr->callno, fh, &f, &res)) { 07256 ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); 07257 ast_mutex_unlock(&iaxsl[fr->callno]); 07258 return 1; 07259 } 07260 #ifdef DEBUG_SUPPORT 07261 else if (iaxdebug) 07262 iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh)); 07263 #endif 07264 } 07265 07266 /* count this frame */ 07267 iaxs[fr->callno]->frames_received++; 07268 07269 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid && 07270 f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */ 07271 f.subclass != IAX_COMMAND_TXACC) { /* for attended transfer */ 07272 unsigned short new_peercallno; 07273 07274 new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL); 07275 if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) { 07276 if (iaxs[fr->callno]->peercallno) { 07277 remove_by_peercallno(iaxs[fr->callno]); 07278 } 07279 iaxs[fr->callno]->peercallno = new_peercallno; 07280 store_by_peercallno(iaxs[fr->callno]); 07281 } 07282 } 07283 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 07284 if (option_debug && iaxdebug) 07285 ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); 07286 /* Check if it's out of order (and not an ACK or INVAL) */ 07287 fr->oseqno = fh->oseqno; 07288 fr->iseqno = fh->iseqno; 07289 fr->ts = ntohl(fh->ts); 07290 #ifdef IAXTESTS 07291 if (test_resync) { 07292 if (option_debug) 07293 ast_log(LOG_DEBUG, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync); 07294 fr->ts += test_resync; 07295 } 07296 #endif /* IAXTESTS */ 07297 #if 0 07298 if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || 07299 ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX && 07300 (f.subclass == IAX_COMMAND_NEW || 07301 f.subclass == IAX_COMMAND_AUTHREQ || 07302 f.subclass == IAX_COMMAND_ACCEPT || 07303 f.subclass == IAX_COMMAND_REJECT)) ) ) 07304 #endif 07305 if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE)) 07306 updatehistory = 0; 07307 if ((iaxs[fr->callno]->iseqno != fr->oseqno) && 07308 (iaxs[fr->callno]->iseqno || 07309 ((f.subclass != IAX_COMMAND_TXCNT) && 07310 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 07311 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 07312 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 07313 (f.subclass != IAX_COMMAND_TXACC)) || 07314 (f.frametype != AST_FRAME_IAX))) { 07315 if ( 07316 ((f.subclass != IAX_COMMAND_ACK) && 07317 (f.subclass != IAX_COMMAND_INVAL) && 07318 (f.subclass != IAX_COMMAND_TXCNT) && 07319 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 07320 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 07321 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 07322 (f.subclass != IAX_COMMAND_TXACC) && 07323 (f.subclass != IAX_COMMAND_VNAK)) || 07324 (f.frametype != AST_FRAME_IAX)) { 07325 /* If it's not an ACK packet, it's out of order. */ 07326 if (option_debug) 07327 ast_log(LOG_DEBUG, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 07328 iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass); 07329 /* Check to see if we need to request retransmission, 07330 * and take sequence number wraparound into account */ 07331 if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) { 07332 /* If we've already seen it, ack it XXX There's a border condition here XXX */ 07333 if ((f.frametype != AST_FRAME_IAX) || 07334 ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) { 07335 if (option_debug) 07336 ast_log(LOG_DEBUG, "Acking anyway\n"); 07337 /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if 07338 we have anything to send, we'll retransmit and get an ACK back anyway XXX */ 07339 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07340 } 07341 } else { 07342 /* Send a VNAK requesting retransmission */ 07343 iax2_vnak(fr->callno); 07344 } 07345 ast_mutex_unlock(&iaxsl[fr->callno]); 07346 return 1; 07347 } 07348 } else { 07349 /* Increment unless it's an ACK or VNAK */ 07350 if (((f.subclass != IAX_COMMAND_ACK) && 07351 (f.subclass != IAX_COMMAND_INVAL) && 07352 (f.subclass != IAX_COMMAND_TXCNT) && 07353 (f.subclass != IAX_COMMAND_TXACC) && 07354 (f.subclass != IAX_COMMAND_VNAK)) || 07355 (f.frametype != AST_FRAME_IAX)) 07356 iaxs[fr->callno]->iseqno++; 07357 } 07358 /* A full frame */ 07359 if (res < sizeof(*fh)) { 07360 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh)); 07361 ast_mutex_unlock(&iaxsl[fr->callno]); 07362 return 1; 07363 } 07364 /* Ensure text frames are NULL-terminated */ 07365 if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') { 07366 if (res < thread->buf_size) 07367 thread->buf[res++] = '\0'; 07368 else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */ 07369 thread->buf[res - 1] = '\0'; 07370 } 07371 f.datalen = res - sizeof(*fh); 07372 07373 /* Handle implicit ACKing unless this is an INVAL, and only if this is 07374 from the real peer, not the transfer peer */ 07375 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 07376 ((f.subclass != IAX_COMMAND_INVAL) || 07377 (f.frametype != AST_FRAME_IAX))) { 07378 unsigned char x; 07379 int call_to_destroy; 07380 /* XXX This code is not very efficient. Surely there is a better way which still 07381 properly handles boundary conditions? XXX */ 07382 /* First we have to qualify that the ACKed value is within our window */ 07383 for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++) 07384 if (fr->iseqno == x) 07385 break; 07386 if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) { 07387 /* The acknowledgement is within our window. Time to acknowledge everything 07388 that it says to */ 07389 for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) { 07390 /* Ack the packet with the given timestamp */ 07391 if (option_debug && iaxdebug) 07392 ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x); 07393 call_to_destroy = 0; 07394 AST_LIST_LOCK(&iaxq.queue); 07395 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 07396 /* If it's our call, and our timestamp, mark -1 retries */ 07397 if ((fr->callno == cur->callno) && (x == cur->oseqno)) { 07398 cur->retries = -1; 07399 /* Destroy call if this is the end */ 07400 if (cur->final) 07401 call_to_destroy = fr->callno; 07402 } 07403 } 07404 AST_LIST_UNLOCK(&iaxq.queue); 07405 if (call_to_destroy) { 07406 if (iaxdebug && option_debug) 07407 ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy); 07408 ast_mutex_lock(&iaxsl[call_to_destroy]); 07409 iax2_destroy(call_to_destroy); 07410 ast_mutex_unlock(&iaxsl[call_to_destroy]); 07411 } 07412 } 07413 /* Note how much we've received acknowledgement for */ 07414 if (iaxs[fr->callno]) 07415 iaxs[fr->callno]->rseqno = fr->iseqno; 07416 else { 07417 /* Stop processing now */ 07418 ast_mutex_unlock(&iaxsl[fr->callno]); 07419 return 1; 07420 } 07421 } else if (option_debug) 07422 ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno); 07423 } 07424 if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 07425 ((f.frametype != AST_FRAME_IAX) || 07426 ((f.subclass != IAX_COMMAND_TXACC) && 07427 (f.subclass != IAX_COMMAND_TXCNT)))) { 07428 /* Only messages we accept from a transfer host are TXACC and TXCNT */ 07429 ast_mutex_unlock(&iaxsl[fr->callno]); 07430 return 1; 07431 } 07432 07433 if (f.datalen) { 07434 if (f.frametype == AST_FRAME_IAX) { 07435 if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) { 07436 ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); 07437 ast_mutex_unlock(&iaxsl[fr->callno]); 07438 return 1; 07439 } 07440 f.data = NULL; 07441 f.datalen = 0; 07442 } else 07443 f.data = thread->buf + sizeof(*fh); 07444 } else { 07445 if (f.frametype == AST_FRAME_IAX) 07446 f.data = NULL; 07447 else 07448 f.data = empty; 07449 memset(&ies, 0, sizeof(ies)); 07450 } 07451 07452 /* when we receive the first full frame for a new incoming channel, 07453 it is safe to start the PBX on the channel because we have now 07454 completed a 3-way handshake with the peer */ 07455 if ((f.frametype == AST_FRAME_VOICE) || 07456 (f.frametype == AST_FRAME_VIDEO) || 07457 (f.frametype == AST_FRAME_IAX)) { 07458 if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) { 07459 ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 07460 if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) { 07461 ast_mutex_unlock(&iaxsl[fr->callno]); 07462 return 1; 07463 } 07464 } 07465 } 07466 07467 if (f.frametype == AST_FRAME_VOICE) { 07468 if (f.subclass != iaxs[fr->callno]->voiceformat) { 07469 iaxs[fr->callno]->voiceformat = f.subclass; 07470 if (option_debug) 07471 ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass); 07472 if (iaxs[fr->callno]->owner) { 07473 int orignative; 07474 retryowner: 07475 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 07476 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 07477 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; 07478 } 07479 if (iaxs[fr->callno]) { 07480 if (iaxs[fr->callno]->owner) { 07481 orignative = iaxs[fr->callno]->owner->nativeformats; 07482 iaxs[fr->callno]->owner->nativeformats = f.subclass; 07483 if (iaxs[fr->callno]->owner->readformat) 07484 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 07485 iaxs[fr->callno]->owner->nativeformats = orignative; 07486 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 07487 } 07488 } else { 07489 if (option_debug) 07490 ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n"); 07491 ast_mutex_unlock(&iaxsl[fr->callno]); 07492 return 1; 07493 } 07494 } 07495 } 07496 } 07497 if (f.frametype == AST_FRAME_VIDEO) { 07498 if (f.subclass != iaxs[fr->callno]->videoformat) { 07499 if (option_debug) 07500 ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1); 07501 iaxs[fr->callno]->videoformat = f.subclass & ~0x1; 07502 } 07503 } 07504 if (f.frametype == AST_FRAME_IAX) { 07505 AST_SCHED_DEL(sched, iaxs[fr->callno]->initid); 07506 /* Handle the IAX pseudo frame itself */ 07507 if (option_debug && iaxdebug) 07508 ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass); 07509 07510 /* Update last ts unless the frame's timestamp originated with us. */ 07511 if (iaxs[fr->callno]->last < fr->ts && 07512 f.subclass != IAX_COMMAND_ACK && 07513 f.subclass != IAX_COMMAND_PONG && 07514 f.subclass != IAX_COMMAND_LAGRP) { 07515 iaxs[fr->callno]->last = fr->ts; 07516 if (option_debug && iaxdebug) 07517 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 07518 } 07519 07520 switch(f.subclass) { 07521 case IAX_COMMAND_ACK: 07522 /* Do nothing */ 07523 break; 07524 case IAX_COMMAND_QUELCH: 07525 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07526 /* Generate Manager Hold event, if necessary*/ 07527 if (iaxs[fr->callno]->owner) { 07528 manager_event(EVENT_FLAG_CALL, "Hold", 07529 "Channel: %s\r\n" 07530 "Uniqueid: %s\r\n", 07531 iaxs[fr->callno]->owner->name, 07532 iaxs[fr->callno]->owner->uniqueid); 07533 } 07534 07535 ast_set_flag(iaxs[fr->callno], IAX_QUELCH); 07536 if (ies.musiconhold) { 07537 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 07538 const char *mohsuggest = iaxs[fr->callno]->mohsuggest; 07539 iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 07540 S_OR(mohsuggest, NULL), 07541 !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0); 07542 if (!iaxs[fr->callno]) { 07543 ast_mutex_unlock(&iaxsl[fr->callno]); 07544 return 1; 07545 } 07546 } 07547 } 07548 } 07549 break; 07550 case IAX_COMMAND_UNQUELCH: 07551 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07552 /* Generate Manager Unhold event, if necessary*/ 07553 if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) { 07554 manager_event(EVENT_FLAG_CALL, "Unhold", 07555 "Channel: %s\r\n" 07556 "Uniqueid: %s\r\n", 07557 iaxs[fr->callno]->owner->name, 07558 iaxs[fr->callno]->owner->uniqueid); 07559 } 07560 07561 ast_clear_flag(iaxs[fr->callno], IAX_QUELCH); 07562 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 07563 iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); 07564 if (!iaxs[fr->callno]) { 07565 ast_mutex_unlock(&iaxsl[fr->callno]); 07566 return 1; 07567 } 07568 } 07569 } 07570 break; 07571 case IAX_COMMAND_TXACC: 07572 if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { 07573 /* Ack the packet with the given timestamp */ 07574 AST_LIST_LOCK(&iaxq.queue); 07575 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 07576 /* Cancel any outstanding txcnt's */ 07577 if ((fr->callno == cur->callno) && (cur->transfer)) 07578 cur->retries = -1; 07579 } 07580 AST_LIST_UNLOCK(&iaxq.queue); 07581 memset(&ied1, 0, sizeof(ied1)); 07582 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno); 07583 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1); 07584 iaxs[fr->callno]->transferring = TRANSFER_READY; 07585 } 07586 break; 07587 case IAX_COMMAND_NEW: 07588 /* Ignore if it's already up */ 07589 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) 07590 break; 07591 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 07592 ast_mutex_unlock(&iaxsl[fr->callno]); 07593 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 07594 ast_mutex_lock(&iaxsl[fr->callno]); 07595 if (!iaxs[fr->callno]) { 07596 ast_mutex_unlock(&iaxsl[fr->callno]); 07597 return 1; 07598 } 07599 } 07600 /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ 07601 if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) { 07602 int new_callno; 07603 if ((new_callno = make_trunk(fr->callno, 1)) != -1) 07604 fr->callno = new_callno; 07605 } 07606 /* For security, always ack immediately */ 07607 if (delayreject) 07608 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07609 if (check_access(fr->callno, &sin, &ies)) { 07610 /* They're not allowed on */ 07611 auth_fail(fr->callno, IAX_COMMAND_REJECT); 07612 if (authdebug) 07613 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); 07614 break; 07615 } 07616 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 07617 const char *context, *exten, *cid_num; 07618 07619 context = ast_strdupa(iaxs[fr->callno]->context); 07620 exten = ast_strdupa(iaxs[fr->callno]->exten); 07621 cid_num = ast_strdupa(iaxs[fr->callno]->cid_num); 07622 07623 /* This might re-enter the IAX code and need the lock */ 07624 ast_mutex_unlock(&iaxsl[fr->callno]); 07625 exists = ast_exists_extension(NULL, context, exten, 1, cid_num); 07626 ast_mutex_lock(&iaxsl[fr->callno]); 07627 07628 if (!iaxs[fr->callno]) { 07629 ast_mutex_unlock(&iaxsl[fr->callno]); 07630 return 1; 07631 } 07632 } else 07633 exists = 0; 07634 if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { 07635 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 07636 memset(&ied0, 0, sizeof(ied0)); 07637 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 07638 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 07639 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07640 if (!iaxs[fr->callno]) { 07641 ast_mutex_unlock(&iaxsl[fr->callno]); 07642 return 1; 07643 } 07644 if (authdebug) 07645 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); 07646 } else { 07647 /* Select an appropriate format */ 07648 07649 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07650 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07651 using_prefs = "reqonly"; 07652 } else { 07653 using_prefs = "disabled"; 07654 } 07655 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 07656 memset(&pref, 0, sizeof(pref)); 07657 strcpy(caller_pref_buf, "disabled"); 07658 strcpy(host_pref_buf, "disabled"); 07659 } else { 07660 using_prefs = "mine"; 07661 /* If the information elements are in here... use them */ 07662 if (ies.codec_prefs) 07663 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 07664 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07665 /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ 07666 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07667 pref = iaxs[fr->callno]->rprefs; 07668 using_prefs = "caller"; 07669 } else { 07670 pref = iaxs[fr->callno]->prefs; 07671 } 07672 } else 07673 pref = iaxs[fr->callno]->prefs; 07674 07675 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 07676 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 07677 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 07678 } 07679 if (!format) { 07680 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07681 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 07682 if (!format) { 07683 memset(&ied0, 0, sizeof(ied0)); 07684 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07685 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07686 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07687 if (!iaxs[fr->callno]) { 07688 ast_mutex_unlock(&iaxsl[fr->callno]); 07689 return 1; 07690 } 07691 if (authdebug) { 07692 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07693 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); 07694 else 07695 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); 07696 } 07697 } else { 07698 /* Pick one... */ 07699 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07700 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 07701 format = 0; 07702 } else { 07703 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07704 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 07705 memset(&pref, 0, sizeof(pref)); 07706 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07707 strcpy(caller_pref_buf,"disabled"); 07708 strcpy(host_pref_buf,"disabled"); 07709 } else { 07710 using_prefs = "mine"; 07711 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07712 /* Do the opposite of what we tried above. */ 07713 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07714 pref = iaxs[fr->callno]->prefs; 07715 } else { 07716 pref = iaxs[fr->callno]->rprefs; 07717 using_prefs = "caller"; 07718 } 07719 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 07720 07721 } else /* if no codec_prefs IE do it the old way */ 07722 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07723 } 07724 } 07725 07726 if (!format) { 07727 memset(&ied0, 0, sizeof(ied0)); 07728 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07729 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07730 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07731 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07732 if (!iaxs[fr->callno]) { 07733 ast_mutex_unlock(&iaxsl[fr->callno]); 07734 return 1; 07735 } 07736 if (authdebug) 07737 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); 07738 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07739 break; 07740 } 07741 } 07742 } 07743 if (format) { 07744 /* No authentication required, let them in */ 07745 memset(&ied1, 0, sizeof(ied1)); 07746 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 07747 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 07748 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 07749 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07750 if (option_verbose > 2) 07751 ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n" 07752 "%srequested format = %s,\n" 07753 "%srequested prefs = %s,\n" 07754 "%sactual format = %s,\n" 07755 "%shost prefs = %s,\n" 07756 "%spriority = %s\n", 07757 ast_inet_ntoa(sin.sin_addr), 07758 VERBOSE_PREFIX_4, 07759 ast_getformatname(iaxs[fr->callno]->peerformat), 07760 VERBOSE_PREFIX_4, 07761 caller_pref_buf, 07762 VERBOSE_PREFIX_4, 07763 ast_getformatname(format), 07764 VERBOSE_PREFIX_4, 07765 host_pref_buf, 07766 VERBOSE_PREFIX_4, 07767 using_prefs); 07768 07769 iaxs[fr->callno]->chosenformat = format; 07770 ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 07771 } else { 07772 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 07773 /* If this is a TBD call, we're ready but now what... */ 07774 if (option_verbose > 2) 07775 ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 07776 } 07777 } 07778 } 07779 break; 07780 } 07781 if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5) 07782 merge_encryption(iaxs[fr->callno],ies.encmethods); 07783 else 07784 iaxs[fr->callno]->encmethods = 0; 07785 if (!authenticate_request(fr->callno) && iaxs[fr->callno]) 07786 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); 07787 if (!iaxs[fr->callno]) { 07788 ast_mutex_unlock(&iaxsl[fr->callno]); 07789 return 1; 07790 } 07791 break; 07792 case IAX_COMMAND_DPREQ: 07793 /* Request status in the dialplan */ 07794 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) && 07795 !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) { 07796 if (iaxcompat) { 07797 /* Spawn a thread for the lookup */ 07798 spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num); 07799 } else { 07800 /* Just look it up */ 07801 dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1); 07802 } 07803 } 07804 break; 07805 case IAX_COMMAND_HANGUP: 07806 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07807 if (option_debug) 07808 ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr->callno); 07809 /* Set hangup cause according to remote */ 07810 if (ies.causecode && iaxs[fr->callno]->owner) 07811 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07812 /* Send ack immediately, before we destroy */ 07813 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07814 iax2_destroy(fr->callno); 07815 break; 07816 case IAX_COMMAND_REJECT: 07817 /* Set hangup cause according to remote */ 07818 if (ies.causecode && iaxs[fr->callno]->owner) 07819 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07820 07821 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07822 if (iaxs[fr->callno]->owner && authdebug) 07823 ast_log(LOG_WARNING, "Call rejected by %s: %s\n", 07824 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), 07825 ies.cause ? ies.cause : "<Unknown>"); 07826 if (option_debug) 07827 ast_log(LOG_DEBUG, "Immediately destroying %d, having received reject\n", 07828 fr->callno); 07829 } 07830 /* Send ack immediately, before we destroy */ 07831 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, 07832 fr->ts, NULL, 0, fr->iseqno); 07833 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) 07834 iaxs[fr->callno]->error = EPERM; 07835 iax2_destroy(fr->callno); 07836 break; 07837 case IAX_COMMAND_TRANSFER: 07838 { 07839 struct ast_channel *bridged_chan; 07840 07841 if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) { 07842 /* Set BLINDTRANSFER channel variables */ 07843 07844 ast_mutex_unlock(&iaxsl[fr->callno]); 07845 pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name); 07846 ast_mutex_lock(&iaxsl[fr->callno]); 07847 if (!iaxs[fr->callno]) { 07848 ast_mutex_unlock(&iaxsl[fr->callno]); 07849 return 1; 07850 } 07851 07852 pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name); 07853 if (!strcmp(ies.called_number, ast_parking_ext())) { 07854 struct ast_channel *saved_channel = iaxs[fr->callno]->owner; 07855 ast_mutex_unlock(&iaxsl[fr->callno]); 07856 if (iax_park(bridged_chan, saved_channel)) { 07857 ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name); 07858 } else { 07859 ast_log(LOG_DEBUG, "Parked call on '%s'\n", bridged_chan->name); 07860 } 07861 ast_mutex_lock(&iaxsl[fr->callno]); 07862 } else { 07863 if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1)) 07864 ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 07865 ies.called_number, iaxs[fr->callno]->context); 07866 else 07867 ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 07868 ies.called_number, iaxs[fr->callno]->context); 07869 } 07870 } else 07871 ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr->callno); 07872 07873 break; 07874 } 07875 case IAX_COMMAND_ACCEPT: 07876 /* Ignore if call is already up or needs authentication or is a TBD */ 07877 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED)) 07878 break; 07879 if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07880 /* Send ack immediately, before we destroy */ 07881 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07882 iax2_destroy(fr->callno); 07883 break; 07884 } 07885 if (ies.format) { 07886 iaxs[fr->callno]->peerformat = ies.format; 07887 } else { 07888 if (iaxs[fr->callno]->owner) 07889 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; 07890 else 07891 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; 07892 } 07893 if (option_verbose > 2) 07894 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)); 07895 if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { 07896 memset(&ied0, 0, sizeof(ied0)); 07897 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07898 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07899 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07900 if (!iaxs[fr->callno]) { 07901 ast_mutex_unlock(&iaxsl[fr->callno]); 07902 return 1; 07903 } 07904 if (authdebug) 07905 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); 07906 } else { 07907 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07908 if (iaxs[fr->callno]->owner) { 07909 /* Switch us to use a compatible format */ 07910 iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; 07911 if (option_verbose > 2) 07912 ast_verbose(VERBOSE_PREFIX_3 "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); 07913 retryowner2: 07914 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 07915 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 07916 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; 07917 } 07918 07919 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { 07920 /* Setup read/write formats properly. */ 07921 if (iaxs[fr->callno]->owner->writeformat) 07922 ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); 07923 if (iaxs[fr->callno]->owner->readformat) 07924 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 07925 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 07926 } 07927 } 07928 } 07929 if (iaxs[fr->callno]) { 07930 ast_mutex_lock(&dpcache_lock); 07931 dp = iaxs[fr->callno]->dpentries; 07932 while(dp) { 07933 if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) { 07934 iax2_dprequest(dp, fr->callno); 07935 } 07936 dp = dp->peer; 07937 } 07938 ast_mutex_unlock(&dpcache_lock); 07939 } 07940 break; 07941 case IAX_COMMAND_POKE: 07942 /* Send back a pong packet with the original timestamp */ 07943 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); 07944 if (!iaxs[fr->callno]) { 07945 ast_mutex_unlock(&iaxsl[fr->callno]); 07946 return 1; 07947 } 07948 break; 07949 case IAX_COMMAND_PING: 07950 { 07951 struct iax_ie_data pingied; 07952 construct_rr(iaxs[fr->callno], &pingied); 07953 /* Send back a pong packet with the original timestamp */ 07954 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1); 07955 } 07956 break; 07957 case IAX_COMMAND_PONG: 07958 /* Calculate ping time */ 07959 iaxs[fr->callno]->pingtime = calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts; 07960 /* save RR info */ 07961 save_rr(fr, &ies); 07962 07963 if (iaxs[fr->callno]->peerpoke) { 07964 peer = iaxs[fr->callno]->peerpoke; 07965 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) { 07966 if (iaxs[fr->callno]->pingtime <= peer->maxms) { 07967 ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime); 07968 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07969 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07970 } 07971 } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) { 07972 if (iaxs[fr->callno]->pingtime > peer->maxms) { 07973 ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime); 07974 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07975 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07976 } 07977 } 07978 peer->lastms = iaxs[fr->callno]->pingtime; 07979 if (peer->smoothing && (peer->lastms > -1)) 07980 peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2; 07981 else if (peer->smoothing && peer->lastms < 0) 07982 peer->historicms = (0 + peer->historicms) / 2; 07983 else 07984 peer->historicms = iaxs[fr->callno]->pingtime; 07985 07986 /* Remove scheduled iax2_poke_noanswer */ 07987 if (peer->pokeexpire > -1) { 07988 if (!ast_sched_del(sched, peer->pokeexpire)) { 07989 peer_unref(peer); 07990 peer->pokeexpire = -1; 07991 } 07992 } 07993 /* Schedule the next cycle */ 07994 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) 07995 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 07996 else 07997 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer)); 07998 if (peer->pokeexpire == -1) 07999 peer_unref(peer); 08000 /* and finally send the ack */ 08001 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08002 /* And wrap up the qualify call */ 08003 iax2_destroy(fr->callno); 08004 peer->callno = 0; 08005 if (option_debug) 08006 ast_log(LOG_DEBUG, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms); 08007 } 08008 break; 08009 case IAX_COMMAND_LAGRQ: 08010 case IAX_COMMAND_LAGRP: 08011 f.src = "LAGRQ"; 08012 f.mallocd = 0; 08013 f.offset = 0; 08014 f.samples = 0; 08015 iax_frame_wrap(fr, &f); 08016 if(f.subclass == IAX_COMMAND_LAGRQ) { 08017 /* Received a LAGRQ - echo back a LAGRP */ 08018 fr->af.subclass = IAX_COMMAND_LAGRP; 08019 iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0); 08020 } else { 08021 /* Received LAGRP in response to our LAGRQ */ 08022 unsigned int ts; 08023 /* This is a reply we've been given, actually measure the difference */ 08024 ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af); 08025 iaxs[fr->callno]->lag = ts - fr->ts; 08026 if (option_debug && iaxdebug) 08027 ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n", 08028 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag); 08029 } 08030 break; 08031 case IAX_COMMAND_AUTHREQ: 08032 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 08033 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>"); 08034 break; 08035 } 08036 if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) { 08037 struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL, 08038 .subclass = AST_CONTROL_HANGUP, 08039 }; 08040 ast_log(LOG_WARNING, 08041 "I don't know how to authenticate %s to %s\n", 08042 ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); 08043 iax2_queue_frame(fr->callno, &hangup_fr); 08044 } 08045 if (!iaxs[fr->callno]) { 08046 ast_mutex_unlock(&iaxsl[fr->callno]); 08047 return 1; 08048 } 08049 break; 08050 case IAX_COMMAND_AUTHREP: 08051 /* For security, always ack immediately */ 08052 if (delayreject) 08053 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08054 /* Ignore once we've started */ 08055 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 08056 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>"); 08057 break; 08058 } 08059 if (authenticate_verify(iaxs[fr->callno], &ies)) { 08060 if (authdebug) 08061 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); 08062 memset(&ied0, 0, sizeof(ied0)); 08063 auth_fail(fr->callno, IAX_COMMAND_REJECT); 08064 break; 08065 } 08066 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 08067 /* This might re-enter the IAX code and need the lock */ 08068 exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num); 08069 } else 08070 exists = 0; 08071 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 08072 if (authdebug) 08073 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); 08074 memset(&ied0, 0, sizeof(ied0)); 08075 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08076 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 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 /* Select an appropriate format */ 08084 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08085 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08086 using_prefs = "reqonly"; 08087 } else { 08088 using_prefs = "disabled"; 08089 } 08090 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 08091 memset(&pref, 0, sizeof(pref)); 08092 strcpy(caller_pref_buf, "disabled"); 08093 strcpy(host_pref_buf, "disabled"); 08094 } else { 08095 using_prefs = "mine"; 08096 if (ies.codec_prefs) 08097 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 08098 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08099 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08100 pref = iaxs[fr->callno]->rprefs; 08101 using_prefs = "caller"; 08102 } else { 08103 pref = iaxs[fr->callno]->prefs; 08104 } 08105 } else /* if no codec_prefs IE do it the old way */ 08106 pref = iaxs[fr->callno]->prefs; 08107 08108 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 08109 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 08110 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 08111 } 08112 if (!format) { 08113 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08114 if (option_debug) 08115 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); 08116 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 08117 } 08118 if (!format) { 08119 if (authdebug) { 08120 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08121 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); 08122 else 08123 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); 08124 } 08125 memset(&ied0, 0, sizeof(ied0)); 08126 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08127 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08128 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08129 if (!iaxs[fr->callno]) { 08130 ast_mutex_unlock(&iaxsl[fr->callno]); 08131 return 1; 08132 } 08133 } else { 08134 /* Pick one... */ 08135 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08136 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 08137 format = 0; 08138 } else { 08139 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08140 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 08141 memset(&pref, 0, sizeof(pref)); 08142 format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? 08143 iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08144 strcpy(caller_pref_buf,"disabled"); 08145 strcpy(host_pref_buf,"disabled"); 08146 } else { 08147 using_prefs = "mine"; 08148 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08149 /* Do the opposite of what we tried above. */ 08150 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08151 pref = iaxs[fr->callno]->prefs; 08152 } else { 08153 pref = iaxs[fr->callno]->rprefs; 08154 using_prefs = "caller"; 08155 } 08156 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 08157 } else /* if no codec_prefs IE do it the old way */ 08158 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08159 } 08160 } 08161 if (!format) { 08162 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08163 if (authdebug) { 08164 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08165 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); 08166 else 08167 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); 08168 } 08169 memset(&ied0, 0, sizeof(ied0)); 08170 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08171 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08172 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08173 if (!iaxs[fr->callno]) { 08174 ast_mutex_unlock(&iaxsl[fr->callno]); 08175 return 1; 08176 } 08177 } 08178 } 08179 } 08180 if (format) { 08181 /* Authentication received */ 08182 memset(&ied1, 0, sizeof(ied1)); 08183 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 08184 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 08185 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 08186 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08187 if (option_verbose > 2) 08188 ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n" 08189 "%srequested format = %s,\n" 08190 "%srequested prefs = %s,\n" 08191 "%sactual format = %s,\n" 08192 "%shost prefs = %s,\n" 08193 "%spriority = %s\n", 08194 ast_inet_ntoa(sin.sin_addr), 08195 VERBOSE_PREFIX_4, 08196 ast_getformatname(iaxs[fr->callno]->peerformat), 08197 VERBOSE_PREFIX_4, 08198 caller_pref_buf, 08199 VERBOSE_PREFIX_4, 08200 ast_getformatname(format), 08201 VERBOSE_PREFIX_4, 08202 host_pref_buf, 08203 VERBOSE_PREFIX_4, 08204 using_prefs); 08205 08206 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08207 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format))) 08208 iax2_destroy(fr->callno); 08209 } else { 08210 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08211 /* If this is a TBD call, we're ready but now what... */ 08212 if (option_verbose > 2) 08213 ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 08214 } 08215 } 08216 } 08217 break; 08218 case IAX_COMMAND_DIAL: 08219 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) { 08220 ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08221 ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); 08222 if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { 08223 if (authdebug) 08224 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); 08225 memset(&ied0, 0, sizeof(ied0)); 08226 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08227 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 08228 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08229 if (!iaxs[fr->callno]) { 08230 ast_mutex_unlock(&iaxsl[fr->callno]); 08231 return 1; 08232 } 08233 } else { 08234 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08235 if (option_verbose > 2) 08236 ast_verbose(VERBOSE_PREFIX_3 "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat); 08237 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08238 send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); 08239 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat))) 08240 iax2_destroy(fr->callno); 08241 } 08242 } 08243 break; 08244 case IAX_COMMAND_INVAL: 08245 iaxs[fr->callno]->error = ENOTCONN; 08246 if (option_debug) 08247 ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr->callno); 08248 iax2_destroy(fr->callno); 08249 if (option_debug) 08250 ast_log(LOG_DEBUG, "Destroying call %d\n", fr->callno); 08251 break; 08252 case IAX_COMMAND_VNAK: 08253 if (option_debug) 08254 ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n"); 08255 /* Force retransmission */ 08256 vnak_retransmit(fr->callno, fr->iseqno); 08257 break; 08258 case IAX_COMMAND_REGREQ: 08259 case IAX_COMMAND_REGREL: 08260 /* For security, always ack immediately */ 08261 if (delayreject) 08262 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08263 if (register_verify(fr->callno, &sin, &ies)) { 08264 if (!iaxs[fr->callno]) { 08265 ast_mutex_unlock(&iaxsl[fr->callno]); 08266 return 1; 08267 } 08268 /* Send delayed failure */ 08269 auth_fail(fr->callno, IAX_COMMAND_REGREJ); 08270 break; 08271 } 08272 if (!iaxs[fr->callno]) { 08273 ast_mutex_unlock(&iaxsl[fr->callno]); 08274 return 1; 08275 } 08276 if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 08277 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) { 08278 if (f.subclass == IAX_COMMAND_REGREL) 08279 memset(&sin, 0, sizeof(sin)); 08280 if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) 08281 ast_log(LOG_WARNING, "Registry error\n"); 08282 if (!iaxs[fr->callno]) { 08283 ast_mutex_unlock(&iaxsl[fr->callno]); 08284 return 1; 08285 } 08286 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 08287 ast_mutex_unlock(&iaxsl[fr->callno]); 08288 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 08289 ast_mutex_lock(&iaxsl[fr->callno]); 08290 if (!iaxs[fr->callno]) { 08291 ast_mutex_unlock(&iaxsl[fr->callno]); 08292 return 1; 08293 } 08294 } 08295 break; 08296 } 08297 registry_authrequest(fr->callno); 08298 if (!iaxs[fr->callno]) { 08299 ast_mutex_unlock(&iaxsl[fr->callno]); 08300 return 1; 08301 } 08302 break; 08303 case IAX_COMMAND_REGACK: 08304 if (iax2_ack_registry(&ies, &sin, fr->callno)) 08305 ast_log(LOG_WARNING, "Registration failure\n"); 08306 /* Send ack immediately, before we destroy */ 08307 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08308 iax2_destroy(fr->callno); 08309 break; 08310 case IAX_COMMAND_REGREJ: 08311 if (iaxs[fr->callno]->reg) { 08312 if (authdebug) { 08313 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)); 08314 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>"); 08315 } 08316 iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; 08317 } 08318 /* Send ack immediately, before we destroy */ 08319 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08320 iax2_destroy(fr->callno); 08321 break; 08322 case IAX_COMMAND_REGAUTH: 08323 /* Authentication request */ 08324 if (registry_rerequest(&ies, fr->callno, &sin)) { 08325 memset(&ied0, 0, sizeof(ied0)); 08326 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); 08327 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 08328 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08329 if (!iaxs[fr->callno]) { 08330 ast_mutex_unlock(&iaxsl[fr->callno]); 08331 return 1; 08332 } 08333 } 08334 break; 08335 case IAX_COMMAND_TXREJ: 08336 iaxs[fr->callno]->transferring = 0; 08337 if (option_verbose > 2) 08338 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 08339 memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer)); 08340 if (iaxs[fr->callno]->bridgecallno) { 08341 if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { 08342 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0; 08343 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 08344 } 08345 } 08346 break; 08347 case IAX_COMMAND_TXREADY: 08348 if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || 08349 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) { 08350 if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) 08351 iaxs[fr->callno]->transferring = TRANSFER_MREADY; 08352 else 08353 iaxs[fr->callno]->transferring = TRANSFER_READY; 08354 if (option_verbose > 2) 08355 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 08356 if (iaxs[fr->callno]->bridgecallno) { 08357 if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || 08358 (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { 08359 /* They're both ready, now release them. */ 08360 if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) { 08361 if (option_verbose > 2) 08362 ast_verbose(VERBOSE_PREFIX_3 "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 08363 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 08364 08365 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; 08366 iaxs[fr->callno]->transferring = TRANSFER_MEDIA; 08367 08368 memset(&ied0, 0, sizeof(ied0)); 08369 memset(&ied1, 0, sizeof(ied1)); 08370 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 08371 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 08372 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1); 08373 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1); 08374 } else { 08375 if (option_verbose > 2) 08376 ast_verbose(VERBOSE_PREFIX_3 "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 08377 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 08378 08379 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED; 08380 iaxs[fr->callno]->transferring = TRANSFER_RELEASED; 08381 ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE); 08382 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 08383 08384 /* Stop doing lag & ping requests */ 08385 stop_stuff(fr->callno); 08386 stop_stuff(iaxs[fr->callno]->bridgecallno); 08387 08388 memset(&ied0, 0, sizeof(ied0)); 08389 memset(&ied1, 0, sizeof(ied1)); 08390 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 08391 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 08392 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1); 08393 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1); 08394 } 08395 08396 } 08397 } 08398 } 08399 break; 08400 case IAX_COMMAND_TXREQ: 08401 try_transfer(iaxs[fr->callno], &ies); 08402 break; 08403 case IAX_COMMAND_TXCNT: 08404 if (iaxs[fr->callno]->transferring) 08405 send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); 08406 break; 08407 case IAX_COMMAND_TXREL: 08408 /* Send ack immediately, rather than waiting until we've changed addresses */ 08409 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08410 complete_transfer(fr->callno, &ies); 08411 stop_stuff(fr->callno); /* for attended transfer to work with libiax */ 08412 break; 08413 case IAX_COMMAND_TXMEDIA: 08414 if (iaxs[fr->callno]->transferring == TRANSFER_READY) { 08415 AST_LIST_LOCK(&iaxq.queue); 08416 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 08417 /* Cancel any outstanding frames and start anew */ 08418 if ((fr->callno == cur->callno) && (cur->transfer)) { 08419 cur->retries = -1; 08420 } 08421 } 08422 AST_LIST_UNLOCK(&iaxq.queue); 08423 /* Start sending our media to the transfer address, but otherwise leave the call as-is */ 08424 iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS; 08425 } 08426 break; 08427 case IAX_COMMAND_DPREP: 08428 complete_dpreply(iaxs[fr->callno], &ies); 08429 break; 08430 case IAX_COMMAND_UNSUPPORT: 08431 ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown); 08432 break; 08433 case IAX_COMMAND_FWDOWNL: 08434 /* Firmware download */ 08435 if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) { 08436 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1); 08437 break; 08438 } 08439 memset(&ied0, 0, sizeof(ied0)); 08440 res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc); 08441 if (res < 0) 08442 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08443 else if (res > 0) 08444 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 08445 else 08446 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 08447 if (!iaxs[fr->callno]) { 08448 ast_mutex_unlock(&iaxsl[fr->callno]); 08449 return 1; 08450 } 08451 break; 08452 default: 08453 if (option_debug) 08454 ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno); 08455 memset(&ied0, 0, sizeof(ied0)); 08456 iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass); 08457 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1); 08458 } 08459 /* Don't actually pass these frames along */ 08460 if ((f.subclass != IAX_COMMAND_ACK) && 08461 (f.subclass != IAX_COMMAND_TXCNT) && 08462 (f.subclass != IAX_COMMAND_TXACC) && 08463 (f.subclass != IAX_COMMAND_INVAL) && 08464 (f.subclass != IAX_COMMAND_VNAK)) { 08465 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 08466 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08467 } 08468 ast_mutex_unlock(&iaxsl[fr->callno]); 08469 return 1; 08470 } 08471 /* Unless this is an ACK or INVAL frame, ack it */ 08472 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 08473 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08474 } else if (minivid) { 08475 f.frametype = AST_FRAME_VIDEO; 08476 if (iaxs[fr->callno]->videoformat > 0) 08477 f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); 08478 else { 08479 ast_log(LOG_WARNING, "Received mini frame before first full video frame\n"); 08480 iax2_vnak(fr->callno); 08481 ast_mutex_unlock(&iaxsl[fr->callno]); 08482 return 1; 08483 } 08484 f.datalen = res - sizeof(*vh); 08485 if (f.datalen) 08486 f.data = thread->buf + sizeof(*vh); 08487 else 08488 f.data = NULL; 08489 #ifdef IAXTESTS 08490 if (test_resync) { 08491 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff); 08492 } else 08493 #endif /* IAXTESTS */ 08494 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff); 08495 } else { 08496 /* A mini frame */ 08497 f.frametype = AST_FRAME_VOICE; 08498 if (iaxs[fr->callno]->voiceformat > 0) 08499 f.subclass = iaxs[fr->callno]->voiceformat; 08500 else { 08501 if (option_debug) 08502 ast_log(LOG_DEBUG, "Received mini frame before first full voice frame\n"); 08503 iax2_vnak(fr->callno); 08504 ast_mutex_unlock(&iaxsl[fr->callno]); 08505 return 1; 08506 } 08507 f.datalen = res - sizeof(struct ast_iax2_mini_hdr); 08508 if (f.datalen < 0) { 08509 ast_log(LOG_WARNING, "Datalen < 0?\n"); 08510 ast_mutex_unlock(&iaxsl[fr->callno]); 08511 return 1; 08512 } 08513 if (f.datalen) 08514 f.data = thread->buf + sizeof(*mh); 08515 else 08516 f.data = NULL; 08517 #ifdef IAXTESTS 08518 if (test_resync) { 08519 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff); 08520 } else 08521 #endif /* IAXTESTS */ 08522 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts); 08523 /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */ 08524 } 08525 /* Don't pass any packets until we're started */ 08526 if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08527 ast_mutex_unlock(&iaxsl[fr->callno]); 08528 return 1; 08529 } 08530 /* Common things */ 08531 f.src = "IAX2"; 08532 f.mallocd = 0; 08533 f.offset = 0; 08534 f.len = 0; 08535 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { 08536 f.samples = ast_codec_get_samples(&f); 08537 /* We need to byteswap incoming slinear samples from network byte order */ 08538 if (f.subclass == AST_FORMAT_SLINEAR) 08539 ast_frame_byteswap_be(&f); 08540 } else 08541 f.samples = 0; 08542 iax_frame_wrap(fr, &f); 08543 08544 /* If this is our most recent packet, use it as our basis for timestamping */ 08545 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 08546 /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/ 08547 fr->outoforder = 0; 08548 } else { 08549 if (option_debug && iaxdebug && iaxs[fr->callno]) 08550 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); 08551 fr->outoforder = -1; 08552 } 08553 fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO)); 08554 duped_fr = iaxfrdup2(fr); 08555 if (duped_fr) { 08556 schedule_delivery(duped_fr, updatehistory, 0, &fr->ts); 08557 } 08558 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 08559 iaxs[fr->callno]->last = fr->ts; 08560 #if 1 08561 if (option_debug && iaxdebug) 08562 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 08563 #endif 08564 } 08565 08566 /* Always run again */ 08567 ast_mutex_unlock(&iaxsl[fr->callno]); 08568 return 1; 08569 }
static int socket_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 6922 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), 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_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().
06923 { 06924 struct iax2_thread *thread; 06925 socklen_t len; 06926 time_t t; 06927 static time_t last_errtime = 0; 06928 struct ast_iax2_full_hdr *fh; 06929 06930 if (!(thread = find_idle_thread())) { 06931 time(&t); 06932 if (t != last_errtime && option_debug) 06933 ast_log(LOG_DEBUG, "Out of idle IAX2 threads for I/O, pausing!\n"); 06934 last_errtime = t; 06935 usleep(1); 06936 return 1; 06937 } 06938 06939 len = sizeof(thread->iosin); 06940 thread->iofd = fd; 06941 thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len); 06942 thread->buf_size = sizeof(thread->readbuf); 06943 thread->buf = thread->readbuf; 06944 if (thread->buf_len < 0) { 06945 if (errno != ECONNREFUSED && errno != EAGAIN) 06946 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 06947 handle_error(); 06948 thread->iostate = IAX_IOSTATE_IDLE; 06949 signal_condition(&thread->lock, &thread->cond); 06950 return 1; 06951 } 06952 if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */ 06953 thread->iostate = IAX_IOSTATE_IDLE; 06954 signal_condition(&thread->lock, &thread->cond); 06955 return 1; 06956 } 06957 06958 /* Determine if this frame is a full frame; if so, and any thread is currently 06959 processing a full frame for the same callno from this peer, then drop this 06960 frame (and the peer will retransmit it) */ 06961 fh = (struct ast_iax2_full_hdr *) thread->buf; 06962 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 06963 struct iax2_thread *cur = NULL; 06964 uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL; 06965 06966 AST_LIST_LOCK(&active_list); 06967 AST_LIST_TRAVERSE(&active_list, cur, list) { 06968 if ((cur->ffinfo.callno == callno) && 06969 !inaddrcmp(&cur->ffinfo.sin, &thread->iosin)) 06970 break; 06971 } 06972 if (cur) { 06973 /* we found another thread processing a full frame for this call, 06974 so queue it up for processing later. */ 06975 defer_full_frame(thread, cur); 06976 AST_LIST_UNLOCK(&active_list); 06977 thread->iostate = IAX_IOSTATE_IDLE; 06978 signal_condition(&thread->lock, &thread->cond); 06979 return 1; 06980 } else { 06981 /* this thread is going to process this frame, so mark it */ 06982 thread->ffinfo.callno = callno; 06983 memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin)); 06984 thread->ffinfo.type = fh->type; 06985 thread->ffinfo.csub = fh->csub; 06986 } 06987 AST_LIST_UNLOCK(&active_list); 06988 } 06989 06990 /* Mark as ready and send on its way */ 06991 thread->iostate = IAX_IOSTATE_READY; 06992 #ifdef DEBUG_SCHED_MULTITHREAD 06993 ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc)); 06994 #endif 06995 signal_condition(&thread->lock, &thread->cond); 06996 06997 return 1; 06998 }
static void spawn_dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid | |||
) | [static] |
Definition at line 6709 of file chan_iax2.c.
References ast_calloc, ast_log(), ast_pthread_create, ast_strdup, dp_lookup_thread(), and LOG_WARNING.
Referenced by socket_process().
06710 { 06711 pthread_t newthread; 06712 struct dpreq_data *dpr; 06713 pthread_attr_t attr; 06714 06715 if (!(dpr = ast_calloc(1, sizeof(*dpr)))) 06716 return; 06717 06718 pthread_attr_init(&attr); 06719 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06720 06721 dpr->callno = callno; 06722 ast_copy_string(dpr->context, context, sizeof(dpr->context)); 06723 ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum)); 06724 if (callerid) 06725 dpr->callerid = ast_strdup(callerid); 06726 if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) { 06727 ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); 06728 } 06729 06730 pthread_attr_destroy(&attr); 06731 }
static int start_network_thread | ( | void | ) | [static] |
Definition at line 9171 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().
09172 { 09173 pthread_attr_t attr; 09174 int threadcount = 0; 09175 int x; 09176 for (x = 0; x < iaxthreadcount; x++) { 09177 struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread)); 09178 if (thread) { 09179 thread->type = IAX_TYPE_POOL; 09180 thread->threadnum = ++threadcount; 09181 ast_mutex_init(&thread->lock); 09182 ast_cond_init(&thread->cond, NULL); 09183 pthread_attr_init(&attr); 09184 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 09185 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 09186 ast_log(LOG_WARNING, "Failed to create new thread!\n"); 09187 free(thread); 09188 thread = NULL; 09189 } 09190 AST_LIST_LOCK(&idle_list); 09191 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 09192 AST_LIST_UNLOCK(&idle_list); 09193 } 09194 } 09195 ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL); 09196 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 09197 if (option_verbose > 1) 09198 ast_verbose(VERBOSE_PREFIX_2 "%d helper threads started\n", threadcount); 09199 return 0; 09200 }
static void stop_stuff | ( | int | callno | ) | [static] |
Definition at line 6391 of file chan_iax2.c.
References iax2_destroy_helper(), and iaxs.
Referenced by socket_process().
06392 { 06393 iax2_destroy_helper(iaxs[callno]); 06394 }
static void store_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1247 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().
01248 { 01249 if (!pvt->peercallno) { 01250 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01251 return; 01252 } 01253 01254 ao2_link(iax_peercallno_pvts, pvt); 01255 }
static int timing_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 6578 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_inet_ntoa(), AST_IO_PRI, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, iax2_trunk_expired(), iax2_trunk_peer::lock, LOG_WARNING, MAX_TRUNKDATA, iax2_trunk_peer::next, option_debug, send_trunk(), tpeers, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.
Referenced by network_thread().
06579 { 06580 char buf[1024]; 06581 int res; 06582 struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL; 06583 int processed = 0; 06584 int totalcalls = 0; 06585 #ifdef DAHDI_TIMERACK 06586 int x = 1; 06587 #endif 06588 struct timeval now; 06589 if (iaxtrunkdebug) 06590 ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA); 06591 gettimeofday(&now, NULL); 06592 if (events & AST_IO_PRI) { 06593 #ifdef DAHDI_TIMERACK 06594 /* Great, this is a timing interface, just call the ioctl */ 06595 if (ioctl(fd, DAHDI_TIMERACK, &x)) { 06596 ast_log(LOG_WARNING, "Unable to acknowledge timer. IAX trunking will fail!\n"); 06597 usleep(1); 06598 return -1; 06599 } 06600 #endif 06601 } else { 06602 /* Read and ignore from the pseudo channel for timing */ 06603 res = read(fd, buf, sizeof(buf)); 06604 if (res < 1) { 06605 ast_log(LOG_WARNING, "Unable to read from timing fd\n"); 06606 return 1; 06607 } 06608 } 06609 /* For each peer that supports trunking... */ 06610 ast_mutex_lock(&tpeerlock); 06611 tpeer = tpeers; 06612 while(tpeer) { 06613 processed++; 06614 res = 0; 06615 ast_mutex_lock(&tpeer->lock); 06616 /* We can drop a single tpeer per pass. That makes all this logic 06617 substantially easier */ 06618 if (!drop && iax2_trunk_expired(tpeer, &now)) { 06619 /* Take it out of the list, but don't free it yet, because it 06620 could be in use */ 06621 if (prev) 06622 prev->next = tpeer->next; 06623 else 06624 tpeers = tpeer->next; 06625 drop = tpeer; 06626 } else { 06627 res = send_trunk(tpeer, &now); 06628 if (iaxtrunkdebug) 06629 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); 06630 } 06631 totalcalls += res; 06632 res = 0; 06633 ast_mutex_unlock(&tpeer->lock); 06634 prev = tpeer; 06635 tpeer = tpeer->next; 06636 } 06637 ast_mutex_unlock(&tpeerlock); 06638 if (drop) { 06639 ast_mutex_lock(&drop->lock); 06640 /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 06641 because by the time they could get tpeerlock, we've already grabbed it */ 06642 if (option_debug) 06643 ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); 06644 if (drop->trunkdata) { 06645 free(drop->trunkdata); 06646 drop->trunkdata = NULL; 06647 } 06648 ast_mutex_unlock(&drop->lock); 06649 ast_mutex_destroy(&drop->lock); 06650 free(drop); 06651 06652 } 06653 if (iaxtrunkdebug) 06654 ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls); 06655 iaxtrunkdebug =0; 06656 return 1; 06657 }
static int transmit_trunk | ( | struct iax_frame * | f, | |
struct sockaddr_in * | sin, | |||
int | sockfd | |||
) | [static] |
Definition at line 2105 of file chan_iax2.c.
References ast_log(), errno, f, handle_error(), LOG_DEBUG, and option_debug.
Referenced by send_trunk().
02106 { 02107 int res; 02108 res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin, 02109 sizeof(*sin)); 02110 if (res < 0) { 02111 if (option_debug) 02112 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 02113 handle_error(); 02114 } else 02115 res = 0; 02116 return res; 02117 }
static int try_firmware | ( | char * | s | ) | [static] |
Definition at line 1793 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, md5(), MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
Referenced by reload_firmware().
01794 { 01795 struct stat stbuf; 01796 struct iax_firmware *cur; 01797 int ifd; 01798 int fd; 01799 int res; 01800 01801 struct ast_iax2_firmware_header *fwh, fwh2; 01802 struct MD5Context md5; 01803 unsigned char sum[16]; 01804 unsigned char buf[1024]; 01805 int len, chunk; 01806 char *s2; 01807 char *last; 01808 s2 = alloca(strlen(s) + 100); 01809 if (!s2) { 01810 ast_log(LOG_WARNING, "Alloca failed!\n"); 01811 return -1; 01812 } 01813 last = strrchr(s, '/'); 01814 if (last) 01815 last++; 01816 else 01817 last = s; 01818 snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random()); 01819 res = stat(s, &stbuf); 01820 if (res < 0) { 01821 ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno)); 01822 return -1; 01823 } 01824 /* Make sure it's not a directory */ 01825 if (S_ISDIR(stbuf.st_mode)) 01826 return -1; 01827 ifd = open(s, O_RDONLY); 01828 if (ifd < 0) { 01829 ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); 01830 return -1; 01831 } 01832 fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600); 01833 if (fd < 0) { 01834 ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); 01835 close(ifd); 01836 return -1; 01837 } 01838 /* Unlink our newly created file */ 01839 unlink(s2); 01840 01841 /* Now copy the firmware into it */ 01842 len = stbuf.st_size; 01843 while(len) { 01844 chunk = len; 01845 if (chunk > sizeof(buf)) 01846 chunk = sizeof(buf); 01847 res = read(ifd, buf, chunk); 01848 if (res != chunk) { 01849 ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01850 close(ifd); 01851 close(fd); 01852 return -1; 01853 } 01854 res = write(fd, buf, chunk); 01855 if (res != chunk) { 01856 ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01857 close(ifd); 01858 close(fd); 01859 return -1; 01860 } 01861 len -= chunk; 01862 } 01863 close(ifd); 01864 /* Return to the beginning */ 01865 lseek(fd, 0, SEEK_SET); 01866 if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) { 01867 ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s); 01868 close(fd); 01869 return -1; 01870 } 01871 if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) { 01872 ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s); 01873 close(fd); 01874 return -1; 01875 } 01876 if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) { 01877 ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s); 01878 close(fd); 01879 return -1; 01880 } 01881 if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) { 01882 ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s); 01883 close(fd); 01884 return -1; 01885 } 01886 fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 01887 if (fwh == (void *) -1) { 01888 ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno)); 01889 close(fd); 01890 return -1; 01891 } 01892 MD5Init(&md5); 01893 MD5Update(&md5, fwh->data, ntohl(fwh->datalen)); 01894 MD5Final(sum, &md5); 01895 if (memcmp(sum, fwh->chksum, sizeof(sum))) { 01896 ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s); 01897 munmap((void*)fwh, stbuf.st_size); 01898 close(fd); 01899 return -1; 01900 } 01901 cur = waresl.wares; 01902 while(cur) { 01903 if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) { 01904 /* Found a candidate */ 01905 if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version))) 01906 /* The version we have on loaded is older, load this one instead */ 01907 break; 01908 /* This version is no newer than what we have. Don't worry about it. 01909 We'll consider it a proper load anyhow though */ 01910 munmap((void*)fwh, stbuf.st_size); 01911 close(fd); 01912 return 0; 01913 } 01914 cur = cur->next; 01915 } 01916 if (!cur) { 01917 /* Allocate a new one and link it */ 01918 if ((cur = ast_calloc(1, sizeof(*cur)))) { 01919 cur->fd = -1; 01920 cur->next = waresl.wares; 01921 waresl.wares = cur; 01922 } 01923 } 01924 if (cur) { 01925 if (cur->fwh) { 01926 munmap((void*)cur->fwh, cur->mmaplen); 01927 } 01928 if (cur->fd > -1) 01929 close(cur->fd); 01930 cur->fwh = fwh; 01931 cur->fd = fd; 01932 cur->mmaplen = stbuf.st_size; 01933 cur->dead = 0; 01934 } 01935 return 0; 01936 }
static int try_transfer | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5793 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, ies, LOG_WARNING, send_command_transfer(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.
Referenced by socket_process().
05794 { 05795 int newcall = 0; 05796 char newip[256]; 05797 struct iax_ie_data ied; 05798 struct sockaddr_in new; 05799 05800 05801 memset(&ied, 0, sizeof(ied)); 05802 if (ies->apparent_addr) 05803 bcopy(ies->apparent_addr, &new, sizeof(new)); 05804 if (ies->callno) 05805 newcall = ies->callno; 05806 if (!newcall || !new.sin_addr.s_addr || !new.sin_port) { 05807 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05808 return -1; 05809 } 05810 pvt->transfercallno = newcall; 05811 memcpy(&pvt->transfer, &new, sizeof(pvt->transfer)); 05812 inet_aton(newip, &pvt->transfer.sin_addr); 05813 pvt->transfer.sin_family = AF_INET; 05814 pvt->transferring = TRANSFER_BEGIN; 05815 pvt->transferid = ies->transferid; 05816 if (ies->transferid) 05817 iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid); 05818 send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); 05819 return 0; 05820 }
static int uncompress_subclass | ( | unsigned char | csub | ) | [static] |
Definition at line 1092 of file chan_iax2.c.
References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.
Referenced by decode_frame(), and socket_process().
01093 { 01094 /* If the SC_LOG flag is set, return 2^csub otherwise csub */ 01095 if (csub & IAX_FLAG_SC_LOG) { 01096 /* special case for 'compressed' -1 */ 01097 if (csub == 0xff) 01098 return -1; 01099 else 01100 return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); 01101 } 01102 else 01103 return csub; 01104 }
static void unlink_peer | ( | struct iax2_peer * | peer | ) | [static] |
Definition at line 6065 of file chan_iax2.c.
References ao2_unlink(), ast_sched_del(), iax2_peer::expire, peer_unref(), peers, iax2_peer::pokeexpire, and sched.
Referenced by __expire_registry(), build_peer(), and prune_peers().
06066 { 06067 if (peer->expire > -1) { 06068 if (!ast_sched_del(sched, peer->expire)) { 06069 peer->expire = -1; 06070 peer_unref(peer); 06071 } 06072 } 06073 06074 if (peer->pokeexpire > -1) { 06075 if (!ast_sched_del(sched, peer->pokeexpire)) { 06076 peer->pokeexpire = -1; 06077 peer_unref(peer); 06078 } 06079 } 06080 06081 ao2_unlink(peers, peer); 06082 }
static int unload_module | ( | void | ) | [static] |
Definition at line 11089 of file chan_iax2.c.
References __unload_module(), ast_custom_function_unregister(), and iaxpeer_function.
11090 { 11091 ast_custom_function_unregister(&iaxpeer_function); 11092 return __unload_module(); 11093 }
static void unlock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3522 of file chan_iax2.c.
References ast_mutex_unlock(), and iaxsl.
Referenced by iax2_bridge().
03523 { 03524 ast_mutex_unlock(&iaxsl[callno1]); 03525 ast_mutex_unlock(&iaxsl[callno0]); 03526 }
static void unwrap_timestamp | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2539 of file chan_iax2.c.
References iax_frame::af, AST_FRAME_VIDEO, ast_log(), iax_frame::callno, ast_frame::frametype, iaxs, chan_iax2_pvt::last, LOG_DEBUG, option_debug, and iax_frame::ts.
Referenced by schedule_delivery().
02540 { 02541 /* Video mini frames only encode the lower 15 bits of the session 02542 * timestamp, but other frame types (e.g. audio) encode 16 bits. */ 02543 const int ts_shift = (fr->af.frametype == AST_FRAME_VIDEO) ? 15 : 16; 02544 const int lower_mask = (1 << ts_shift) - 1; 02545 const int upper_mask = ~lower_mask; 02546 const int last_upper = iaxs[fr->callno]->last & upper_mask; 02547 02548 if ( (fr->ts & upper_mask) == last_upper ) { 02549 const int x = fr->ts - iaxs[fr->callno]->last; 02550 const int threshold = (ts_shift == 15) ? 25000 : 50000; 02551 02552 if (x < -threshold) { 02553 /* Sudden big jump backwards in timestamp: 02554 What likely happened here is that miniframe timestamp has circled but we haven't 02555 gotten the update from the main packet. We'll just pretend that we did, and 02556 update the timestamp appropriately. */ 02557 fr->ts = (last_upper + (1 << ts_shift)) | (fr->ts & lower_mask); 02558 if (option_debug && iaxdebug) 02559 ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n"); 02560 } else if (x > threshold) { 02561 /* Sudden apparent big jump forwards in timestamp: 02562 What's likely happened is this is an old miniframe belonging to the previous 02563 top 15 or 16-bit timestamp that has turned up out of order. 02564 Adjust the timestamp appropriately. */ 02565 fr->ts = (last_upper - (1 << ts_shift)) | (fr->ts & lower_mask); 02566 if (option_debug && iaxdebug) 02567 ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n"); 02568 } 02569 } 02570 }
static void update_jbsched | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 2574 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, chan_iax2_pvt::rxcore, and sched.
Referenced by __get_from_jb(), and schedule_delivery().
02575 { 02576 int when; 02577 02578 when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore); 02579 02580 when = jb_next(pvt->jb) - when; 02581 02582 AST_SCHED_DEL(sched, pvt->jbid); 02583 02584 if(when <= 0) { 02585 /* XXX should really just empty until when > 0.. */ 02586 when = 1; 02587 } 02588 02589 pvt->jbid = iax2_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno)); 02590 }
static void update_max_nontrunk | ( | void | ) | [static] |
Definition at line 1462 of file chan_iax2.c.
References ast_log(), LOG_DEBUG, maxnontrunkcall, option_debug, and TRUNK_CALL_START.
Referenced by __find_callno(), and make_trunk().
01463 { 01464 int max = 1; 01465 int x; 01466 /* XXX Prolly don't need locks here XXX */ 01467 for (x=1;x<TRUNK_CALL_START - 1; x++) { 01468 if (iaxs[x]) 01469 max = x + 1; 01470 } 01471 maxnontrunkcall = max; 01472 if (option_debug && iaxdebug) 01473 ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max); 01474 }
static void update_max_trunk | ( | void | ) | [static] |
Definition at line 1267 of file chan_iax2.c.
References ARRAY_LEN, ast_log(), LOG_DEBUG, maxtrunkcall, option_debug, and TRUNK_CALL_START.
Referenced by iax2_destroy(), and make_trunk().
01268 { 01269 int max = TRUNK_CALL_START; 01270 int x; 01271 01272 /* XXX Prolly don't need locks here XXX */ 01273 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01274 if (iaxs[x]) { 01275 max = x + 1; 01276 } 01277 } 01278 01279 maxtrunkcall = max; 01280 if (option_debug && iaxdebug) 01281 ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max); 01282 }
static int update_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2176 of file chan_iax2.c.
References ast_iax2_full_hdr::dcallno, f, IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, and chan_iax2_pvt::iseqno.
Referenced by __attempt_transmit().
02177 { 02178 /* Called with iaxsl lock held, and iaxs[callno] non-NULL */ 02179 struct ast_iax2_full_hdr *fh = f->data; 02180 /* Mark this as a retransmission */ 02181 fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno); 02182 /* Update iseqno */ 02183 f->iseqno = iaxs[f->callno]->iseqno; 02184 fh->iseqno = f->iseqno; 02185 return 0; 02186 }
static int update_registry | ( | struct sockaddr_in * | sin, | |
int | callno, | |||
char * | devtype, | |||
int | fd, | |||
unsigned short | refresh | |||
) | [static] |
Definition at line 6176 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(), EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), globalflags, iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, iaxs, iaxsl, inaddrcmp(), LOG_NOTICE, LOG_WARNING, manager_event(), option_verbose, peer_ref(), peer_unref(), realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.
Referenced by socket_process().
06177 { 06178 /* Called from IAX thread only, with proper iaxsl lock */ 06179 struct iax_ie_data ied; 06180 struct iax2_peer *p; 06181 int msgcount; 06182 char data[80]; 06183 int version; 06184 const char *peer_name; 06185 int res = -1; 06186 06187 memset(&ied, 0, sizeof(ied)); 06188 06189 peer_name = ast_strdupa(iaxs[callno]->peer); 06190 06191 /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ 06192 ast_mutex_unlock(&iaxsl[callno]); 06193 if (!(p = find_peer(peer_name, 1))) { 06194 ast_mutex_lock(&iaxsl[callno]); 06195 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 06196 return -1; 06197 } 06198 ast_mutex_lock(&iaxsl[callno]); 06199 if (!iaxs[callno]) 06200 goto return_unref; 06201 06202 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { 06203 if (sin->sin_addr.s_addr) { 06204 time_t nowtime; 06205 time(&nowtime); 06206 realtime_update_peer(peer_name, sin, nowtime); 06207 } else { 06208 realtime_update_peer(peer_name, sin, 0); 06209 } 06210 } 06211 if (inaddrcmp(&p->addr, sin)) { 06212 if (iax2_regfunk) 06213 iax2_regfunk(p->name, 1); 06214 /* Stash the IP address from which they registered */ 06215 memcpy(&p->addr, sin, sizeof(p->addr)); 06216 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry); 06217 if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) { 06218 ast_db_put("IAX/Registry", p->name, data); 06219 if (option_verbose > 2) 06220 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 06221 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 06222 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name); 06223 register_peer_exten(p, 1); 06224 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06225 } else if (!ast_test_flag(p, IAX_TEMPONLY)) { 06226 if (option_verbose > 2) 06227 ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 06228 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED"); 06229 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name); 06230 register_peer_exten(p, 0); 06231 ast_db_del("IAX/Registry", p->name); 06232 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 06233 } 06234 /* Update the host */ 06235 /* Verify that the host is really there */ 06236 iax2_poke_peer(p, callno); 06237 } 06238 06239 /* Make sure our call still exists, an INVAL at the right point may make it go away */ 06240 if (!iaxs[callno]) { 06241 res = 0; 06242 goto return_unref; 06243 } 06244 06245 /* Store socket fd */ 06246 p->sockfd = fd; 06247 /* Setup the expiry */ 06248 if (p->expire > -1) { 06249 if (!ast_sched_del(sched, p->expire)) { 06250 p->expire = -1; 06251 peer_unref(p); 06252 } 06253 } 06254 /* treat an unspecified refresh interval as the minimum */ 06255 if (!refresh) 06256 refresh = min_reg_expire; 06257 if (refresh > max_reg_expire) { 06258 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 06259 p->name, max_reg_expire, refresh); 06260 p->expiry = max_reg_expire; 06261 } else if (refresh < min_reg_expire) { 06262 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 06263 p->name, min_reg_expire, refresh); 06264 p->expiry = min_reg_expire; 06265 } else { 06266 p->expiry = refresh; 06267 } 06268 if (p->expiry && sin->sin_addr.s_addr) { 06269 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 06270 if (p->expire == -1) 06271 peer_unref(p); 06272 } 06273 iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); 06274 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); 06275 if (sin->sin_addr.s_addr) { 06276 iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); 06277 iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); 06278 if (!ast_strlen_zero(p->mailbox)) { 06279 int new, old; 06280 ast_app_inboxcount(p->mailbox, &new, &old); 06281 if (new > 255) 06282 new = 255; 06283 if (old > 255) 06284 old = 255; 06285 msgcount = (old << 8) | new; 06286 iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount); 06287 } 06288 if (ast_test_flag(p, IAX_HASCALLERID)) { 06289 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num); 06290 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name); 06291 } 06292 } 06293 version = iax_check_version(devtype); 06294 if (version) 06295 iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version); 06296 06297 res = 0; 06298 06299 return_unref: 06300 peer_unref(p); 06301 06302 return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1); 06303 }
static int user_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1139 of file chan_iax2.c.
Referenced by load_module().
01140 { 01141 struct iax2_user *user = obj, *user2 = arg; 01142 01143 return !strcmp(user->name, user2->name) ? CMP_MATCH | CMP_STOP : 0; 01144 }
static int user_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 9803 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
09804 { 09805 struct iax2_user *user = obj; 09806 09807 ast_set_flag(user, IAX_DELME); 09808 09809 return 0; 09810 }
static void user_destructor | ( | void * | obj | ) | [static] |
Definition at line 9567 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().
09568 { 09569 struct iax2_user *user = obj; 09570 09571 ast_free_ha(user->ha); 09572 free_context(user->contexts); 09573 if(user->vars) { 09574 ast_variables_destroy(user->vars); 09575 user->vars = NULL; 09576 } 09577 ast_string_field_free_memory(user); 09578 }
static int user_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1129 of file chan_iax2.c.
References ast_str_hash().
Referenced by load_module().
01130 { 01131 const struct iax2_user *user = obj; 01132 01133 return ast_str_hash(user->name); 01134 }
Definition at line 1178 of file chan_iax2.c.
References ao2_ref().
01179 { 01180 ao2_ref(user, +1); 01181 return user; 01182 }
Definition at line 1184 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().
01185 { 01186 ao2_ref(user, -1); 01187 return NULL; 01188 }
static void vnak_retransmit | ( | int | callno, | |
int | last | |||
) | [static] |
Definition at line 6492 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, f, iaxq, iaxs, and send_packet().
Referenced by socket_process().
06493 { 06494 struct iax_frame *f; 06495 06496 AST_LIST_LOCK(&iaxq.queue); 06497 AST_LIST_TRAVERSE(&iaxq.queue, f, list) { 06498 /* Send a copy immediately */ 06499 if ((f->callno == callno) && iaxs[f->callno] && 06500 ((unsigned char ) (f->oseqno - last) < 128) && 06501 (f->retries >= 0)) { 06502 send_packet(f); 06503 } 06504 } 06505 AST_LIST_UNLOCK(&iaxq.queue); 06506 }
char accountcode[AST_MAX_ACCOUNT_CODE] [static] |
Definition at line 215 of file chan_iax2.c.
Referenced by __oh323_new(), ast_cdr_setaccount(), ast_channel_alloc(), begin_dial(), build_device(), build_gateway(), check_user_full(), dahdi_new(), disa_exec(), features_call(), gtalk_new(), local_call(), mgcp_new(), sip_new(), skinny_new(), tds_log(), and wait_for_answer().
int adsi = 0 [static] |
int amaflags = 0 [static] |
int authdebug = 1 [static] |
Definition at line 155 of file chan_iax2.c.
int autokill = 0 [static] |
Definition at line 156 of file chan_iax2.c.
struct ast_cli_entry cli_iax2[] [static] |
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 10885 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 10890 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 10900 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 10895 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 10880 of file chan_iax2.c.
char context[80] = "default" [static] |
Definition at line 142 of file chan_iax2.c.
char debug_jb_usage[] [static] |
Initial value:
"Usage: iax2 set debug jb\n" " Enables jitterbuffer debugging information\n"
Definition at line 10854 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 10846 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 10838 of file chan_iax2.c.
int defaultsockfd = -1 [static] |
Definition at line 172 of file chan_iax2.c.
int delayreject = 0 [static] |
Definition at line 220 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 274 of file chan_iax2.c.
struct ast_flags globalflags = { 0 } [static] |
Definition at line 223 of file chan_iax2.c.
Referenced by __expire_registry(), __find_callno(), aji_create_client(), aji_load_config(), build_peer(), build_user(), find_or_create(), find_user(), find_user_realtime(), forward_message(), iax2_request(), iax2_trunk_queue(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), send_trunk(), sendmail(), set_config(), set_config_destroy(), socket_process(), update_registry(), and vm_execmain().
int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static] |
Definition at line 201 of file chan_iax2.c.
int iax2_encryption = 0 [static] |
Definition at line 221 of file chan_iax2.c.
enum { ... } iax2_flags |
int(*) iax2_regfunk(const char *username, int onoff) = NULL |
Definition at line 174 of file chan_iax2.c.
Referenced by __expire_registry(), reg_source_db(), and update_registry().
char iax2_reload_usage[] [static] |
Initial value:
"Usage: iax2 reload\n" " Reloads IAX configuration from iax.conf\n"
Definition at line 10796 of file chan_iax2.c.
enum { ... } iax2_state |
struct ast_switch iax2_switch [static] |
struct ast_channel_tech iax2_tech [static] |
Definition at line 864 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 10862 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 823 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 451 of file chan_iax2.c.
Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().
int iaxcompat = 0 [static] |
Definition at line 157 of file chan_iax2.c.
int iaxdebug = 0 [static] |
Definition at line 203 of file chan_iax2.c.
int iaxdefaultdpcache = 10 * 60 [static] |
Definition at line 159 of file chan_iax2.c.
int iaxdefaulttimeout = 5 [static] |
Definition at line 161 of file chan_iax2.c.
int iaxdynamicthreadcount = 0 [static] |
Definition at line 449 of file chan_iax2.c.
Referenced by find_idle_thread(), and iax2_process_thread().
int iaxdynamicthreadnum = 0 [static] |
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 810 of file chan_iax2.c.
Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __do_deliver(), __get_from_jb(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_fail(), auth_reject(), authenticate_reply(), authenticate_request(), auto_hangup(), cache_get_callno_locked(), calc_timestamp(), check_access(), complete_transfer(), decrypt_frame(), delete_users(), dp_lookup(), find_cache(), fix_peerts(), function_iaxpeer(), iax2_ack_registry(), iax2_bridge(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_predestroy(), iax2_prov_app(), iax2_provision(), iax2_request(), iax2_show_channels(), iax2_start_transfer(), iax2_vnak(), iax2_write(), iax_showframe(), load_module(), network_thread(), register_verify(), registry_authrequest(), registry_rerequest(), save_rr(), schedule_delivery(), send_command_final(), send_command_locked(), send_packet(), socket_process(), stop_stuff(), unwrap_timestamp(), update_packet(), update_registry(), and vnak_retransmit().
ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static] |
Definition at line 811 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 447 of file chan_iax2.c.
Referenced by iax2_show_threads(), set_config(), and start_network_thread().
int iaxtrunkdebug = 0 [static] |
Definition at line 205 of file chan_iax2.c.
struct io_context* io [static] |
Definition at line 198 of file chan_iax2.c.
int lagrq_time = 10 [static] |
Definition at line 150 of file chan_iax2.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 144 of file chan_iax2.c.
Definition at line 812 of file chan_iax2.c.
int max_reg_expire [static] |
Definition at line 166 of file chan_iax2.c.
int max_retries = 4 [static] |
Definition at line 148 of file chan_iax2.c.
int maxauthreq = 3 [static] |
Definition at line 147 of file chan_iax2.c.
int maxjitterbuffer = 1000 [static] |
Definition at line 151 of file chan_iax2.c.
int maxjitterinterps = 10 [static] |
Definition at line 153 of file chan_iax2.c.
int maxnontrunkcall = 1 [static] |
Definition at line 830 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 165 of file chan_iax2.c.
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 216 of file chan_iax2.c.
char mohsuggest[MAX_MUSICCLASS] [static] |
Definition at line 217 of file chan_iax2.c.
Referenced by build_device(), check_user_full(), create_addr_from_peer(), and sip_alloc().
struct ast_netsock_list* netsock [static] |
Definition at line 170 of file chan_iax2.c.
Referenced by __unload_module(), ast_netsock_destroy(), load_module(), peer_set_srcaddr(), and set_config().
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 225 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 10858 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 10850 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 10842 of file chan_iax2.c.
struct ast_netsock_list* outsock [static] |
used if sourceaddress specified and bindaddr == INADDR_ANY
Definition at line 171 of file chan_iax2.c.
Referenced by __unload_module(), load_module(), peer_set_srcaddr(), and set_config().
char* papp = "IAX2Provision" [static] |
Definition at line 8819 of file chan_iax2.c.
char* pdescrip [static] |
Initial value:
" IAX2Provision([template]): Provisions the calling IAXy (assuming\n" "the calling entity is in fact an IAXy) with the given template or\n" "default if one is not specified. Returns -1 on error or 0 on success.\n"
Definition at line 8821 of file chan_iax2.c.
struct ao2_container* peers [static] |
Definition at line 648 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(), register_request(), set_config(), socket_read(), unlink_peer(), and unregister_request().
int ping_time = 21 [static] |
Definition at line 149 of file chan_iax2.c.
struct ast_codec_pref prefs [static] |
Definition at line 138 of file chan_iax2.c.
Referenced by ast_best_codec(), ast_rtp_codec_setpref(), build_peer(), build_user(), check_access(), create_addr(), gtalk_create_member(), gtalk_load_config(), new_iax(), set_config(), set_local_capabilities(), and set_peer_capabilities().
char prune_realtime_usage[] [static] |
Initial value:
"Usage: iax2 prune realtime [<peername>|all]\n" " Prunes object(s) from the cache\n"
Definition at line 10792 of file chan_iax2.c.
char* psyn = "Provision a calling IAXy with a given template" [static] |
Definition at line 8820 of file chan_iax2.c.
char regcontext[AST_MAX_CONTEXT] = "" [static] |
Definition at line 145 of file chan_iax2.c.
int resyncthreshold = 1000 [static] |
Definition at line 152 of file chan_iax2.c.
struct sched_context* sched [static] |
Definition at line 199 of file chan_iax2.c.
ast_cond_t sched_cond [static] |
Definition at line 228 of file chan_iax2.c.
pthread_t schedthreadid = AST_PTHREADT_NULL [static] |
Definition at line 226 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 10784 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 10812 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 10830 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 10816 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 10788 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 10824 of file chan_iax2.c.
char show_prov_usage[] [static] |
Definition at line 10800 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 10834 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 10780 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 10820 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 10807 of file chan_iax2.c.
const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static] |
Definition at line 140 of file chan_iax2.c.
int test_losspct = 0 [static] |
Definition at line 207 of file chan_iax2.c.
int timingfd = -1 [static] |
Definition at line 168 of file chan_iax2.c.
unsigned int tos = 0 [static] |
Definition at line 163 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 154 of file chan_iax2.c.
struct ao2_container* users [static] |
Definition at line 651 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(), free_vm_users(), handle_showmanager(), handle_showmanagers(), handle_voicemail_show_users(), iax2_destroy_helper(), iax2_show_users(), init_manager(), load_config(), load_module(), prune_users(), 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().