#include "asterisk.h"
#include <sys/mman.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <signal.h>
#include <strings.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/md5.h"
#include "asterisk/cdr.h"
#include "asterisk/crypto.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/app.h"
#include "asterisk/astdb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/localtime.h"
#include "asterisk/aes.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/netsock.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/event.h"
#include "asterisk/astobj2.h"
#include "asterisk/timing.h"
#include "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
#include "jitterbuf.h"
Go to the source code of this file.
Data Structures | |
struct | active_list |
struct | chan_iax2_pvt |
struct | create_addr_info |
struct | dpcache |
struct | dpreq_data |
struct | dynamic_list |
struct | firmwares |
struct | frame_queue |
a list of frames that may need to be retransmitted More... | |
struct | iax2_context |
struct | iax2_dpcache |
struct | iax2_peer |
struct | iax2_pkt_buf |
struct | iax2_registry |
struct | iax2_thread |
struct | iax2_trunk_peer |
struct | iax2_user |
struct | iax_dual |
struct | iax_firmware |
struct | iax_rr |
struct | idle_list |
struct | parsed_dial_string |
struct | registrations |
struct | tpeers |
Defines | |
#define | ACN_FORMAT1 "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n" |
#define | ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n" |
#define | CALLNO_TO_PTR(a) ((void *)(unsigned long)(a)) |
#define | DEBUG_SCHED_MULTITHREAD |
#define | DEBUG_SUPPORT |
#define | DEFAULT_CONTEXT "default" |
#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 %-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 %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_CALLENCRYPTED(pvt) (ast_test_flag(pvt, IAX_ENCRYPTED) && ast_test_flag(pvt, IAX_KEYPOPULATED)) |
#define | IAX_CAPABILITY_FULLBANDWIDTH (0xFFFF & ~AST_FORMAT_AUDIO_UNDEFINED) |
#define | IAX_CAPABILITY_LOWBANDWIDTH |
#define | IAX_CAPABILITY_LOWFREE |
#define | IAX_CAPABILITY_MEDBANDWIDTH |
#define | IAX_DEBUGDIGEST(msg, key) |
#define | MAX_JITTER_BUFFER 50 |
#define | MAX_PEER_BUCKETS 563 |
#define | MAX_RETRY_TIME 10000 |
#define | MAX_TIMESTAMP_SKEW 160 |
#define | MAX_TRUNK_MTU 1240 |
Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240. | |
#define | MAX_TRUNKDATA 640 * 200 |
#define | MAX_USER_BUCKETS MAX_PEER_BUCKETS |
#define | MEMORY_SIZE 100 |
#define | MIN_JITTER_BUFFER 10 |
#define | MIN_RETRY_TIME 100 |
#define | MIN_REUSE_TIME 60 |
#define | NEW_ALLOW 1 |
#define | NEW_FORCE 2 |
#define | NEW_PREVENT 0 |
#define | PTR_TO_CALLNO(a) ((unsigned short)(unsigned long)(a)) |
#define | SCHED_MULTITHREADED |
#define | schedule_action(func, data) __schedule_action(func, data, __PRETTY_FUNCTION__) |
#define | TRUNK_CALL_START ARRAY_LEN(iaxs) / 2 |
#define | TS_GAP_FOR_JB_RESYNC 5000 |
Enumerations | |
enum | { CACHE_FLAG_EXISTS = (1 << 0), CACHE_FLAG_NONEXISTENT = (1 << 1), CACHE_FLAG_CANEXIST = (1 << 2), CACHE_FLAG_PENDING = (1 << 3), CACHE_FLAG_TIMEOUT = (1 << 4), CACHE_FLAG_TRANSMITTED = (1 << 5), CACHE_FLAG_UNKNOWN = (1 << 6), CACHE_FLAG_MATCHMORE = (1 << 7) } |
enum | iax2_flags { IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3), IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7), IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12), IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16), IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20), IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24), IAX_DELAYPBXSTART = (1 << 25), IAX_ALLOWFWDOWNLOAD = (1 << 26) } |
enum | iax2_state { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2) } |
enum | iax2_thread_iostate { IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_SCHEDREADY } |
enum | iax2_thread_type { IAX_THREAD_TYPE_POOL, IAX_THREAD_TYPE_DYNAMIC } |
enum | iax_reg_state { REG_STATE_UNREGISTERED = 0, REG_STATE_REGSENT, REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_TIMEOUT, REG_STATE_NOAUTH } |
enum | iax_transfer_state { TRANSFER_NONE = 0, TRANSFER_BEGIN, TRANSFER_READY, TRANSFER_RELEASED, TRANSFER_PASSTHROUGH, TRANSFER_MBEGIN, TRANSFER_MREADY, TRANSFER_MRELEASED, TRANSFER_MPASSTHROUGH, TRANSFER_MEDIA, TRANSFER_MEDIAPASS } |
Functions | |
static void | __attempt_transmit (const void *data) |
static void | __auth_reject (const void *nothing) |
static void | __auto_congest (const void *nothing) |
static void | __auto_hangup (const void *nothing) |
static int | __do_deliver (void *data) |
static void | __expire_registry (const void *data) |
static int | __find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int return_locked, int check_dcallno) |
static void | __get_from_jb (const void *p) |
static void | __iax2_do_register_s (const void *data) |
static void | __iax2_poke_noanswer (const void *data) |
static void | __iax2_poke_peer_s (const void *data) |
static int | __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[]) |
static void | __reg_module (void) |
static int | __schedule_action (void(*func)(const void *data), const void *data, const char *funcname) |
static int | __send_command (struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const unsigned char *data, int datalen, int seqno, int now, int transfer, int final) |
static void | __send_lagrq (const void *data) |
static void | __send_ping (const void *data) |
static int | __unload_module (void) |
static void | __unreg_module (void) |
static int | acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen) |
static int | acf_channel_write (struct ast_channel *chan, const char *function, char *data, const char *value) |
static int | acf_iaxvar_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | acf_iaxvar_write (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
static int | apply_context (struct iax2_context *con, const char *context) |
static int | ast_cli_netstats (struct mansession *s, int fd, int limit_fmt) |
static struct ast_channel * | ast_iax2_new (int callno, int state, int capability) |
Create new call, interface with the PBX core. | |
static int | attempt_transmit (const void *data) |
static int | auth_fail (int callno, int failcode) |
static int | auth_reject (const void *data) |
static int | authenticate (const char *challenge, const char *secret, const char *keyn, int authmethods, struct iax_ie_data *ied, struct sockaddr_in *sin, struct chan_iax2_pvt *pvt) |
static int | authenticate_reply (struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey) |
static int | authenticate_request (int call_num) |
static int | authenticate_verify (struct chan_iax2_pvt *p, struct iax_ies *ies) |
static int | auto_congest (const void *data) |
static int | auto_hangup (const void *data) |
static struct iax2_context * | build_context (const char *context) |
static void | build_ecx_key (const unsigned char *digest, struct chan_iax2_pvt *pvt) |
static void | build_encryption_keys (const unsigned char *digest, struct chan_iax2_pvt *pvt) |
static struct iax2_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) |
Create peer structure based on configuration. | |
static void | build_rand_pad (unsigned char *buf, ssize_t len) |
static struct iax2_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 *now) |
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_peers (const char *line, const char *word, int pos, int state) |
static char * | complete_iax2_unregister (const char *line, const char *word, int pos, int state) |
static int | complete_transfer (int callno, struct iax_ies *ies) |
static unsigned char | compress_subclass (int subclass) |
static void | construct_rr (struct chan_iax2_pvt *pvt, struct iax_ie_data *iep) |
static int | create_addr (const char *peername, struct ast_channel *c, struct sockaddr_in *sin, struct create_addr_info *cai) |
static int | decode_frame (ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static int | decrypt_frame (int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static void | defer_full_frame (struct iax2_thread *from_here, struct iax2_thread *to_here) |
Queue the last read full frame for processing by a certain thread. | |
static void | delete_users (void) |
static void | destroy_firmware (struct iax_firmware *cur) |
static void | dp_lookup (int callno, const char *context, const char *callednum, const char *callerid, int skiplock) |
static void * | dp_lookup_thread (void *data) |
static int | encrypt_frame (ast_aes_encrypt_key *ecx, struct ast_iax2_full_hdr *fh, unsigned char *poo, int *datalen) |
static int | expire_registry (const void *data) |
static struct iax2_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 struct iax2_user * | find_user (const char *name) |
static unsigned int | fix_peerts (struct timeval *rxtrunktime, int callno, unsigned int ts) |
static void | free_context (struct iax2_context *con) |
static int | function_iaxpeer (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | get_auth_methods (const char *value) |
static int | get_encrypt_methods (const char *s) |
static int | get_from_jb (const void *p) |
static char * | handle_cli_iax2_provision (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_prune_realtime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug_jb (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug_trunk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_mtu (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Set trunk MTU from CLI. | |
static char * | handle_cli_iax2_show_cache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_firmware (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_netstats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Show one peer in detail. | |
static char * | handle_cli_iax2_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_registry (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_threads (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_test_losspct (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static void | handle_deferred_full_frames (struct iax2_thread *thread) |
Handle any deferred full frames for this thread. | |
static int | handle_error (void) |
static int | iax2_ack_registry (struct iax_ies *ies, struct sockaddr_in *sin, int callno) |
Acknowledgment received for OUR registration. | |
static void | iax2_ami_channelupdate (struct chan_iax2_pvt *pvt) |
Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers. | |
static int | iax2_answer (struct ast_channel *c) |
static int | iax2_append_register (const char *hostname, const char *username, const char *secret, const char *porta) |
static enum ast_bridge_result | iax2_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
static int | iax2_call (struct ast_channel *c, char *dest, int timeout) |
static int | iax2_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
part of the IAX2 dial plan switch interface | |
static unsigned int | iax2_datetime (const char *tz) |
static void | iax2_destroy (int callno) |
static void | iax2_destroy_helper (struct chan_iax2_pvt *pvt) |
static int | iax2_devicestate (void *data) |
Part of the device state notification system ---. | |
static int | iax2_digit_begin (struct ast_channel *c, char digit) |
static int | iax2_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
static int | iax2_do_register (struct iax2_registry *reg) |
static int | iax2_do_register_s (const void *data) |
static void | iax2_dprequest (struct iax2_dpcache *dp, int callno) |
static void * | iax2_dup_variable_datastore (void *) |
static int | iax2_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Execute IAX2 dialplan switch. | |
static int | iax2_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 switch interface. | |
static int | iax2_fixup (struct ast_channel *oldchannel, struct ast_channel *newchan) |
static void | iax2_frame_free (struct iax_frame *fr) |
static void | iax2_free_variable_datastore (void *) |
static int | iax2_getpeername (struct sockaddr_in sin, char *host, int len) |
static int | iax2_getpeertrunk (struct sockaddr_in sin) |
static int | iax2_hangup (struct ast_channel *c) |
static int | iax2_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen) |
static int | iax2_key_rotate (const void *vpvt) |
static int | iax2_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 Switch interface. | |
static int | iax2_poke_noanswer (const void *data) |
static int | iax2_poke_peer (struct iax2_peer *peer, int heldcall) |
static int | iax2_poke_peer_cb (void *obj, void *arg, int flags) |
static int | iax2_poke_peer_s (const void *data) |
static int | iax2_predestroy (int callno) |
static void * | iax2_process_thread (void *data) |
static void | iax2_process_thread_cleanup (void *data) |
static int | iax2_prov_app (struct ast_channel *chan, void *data) |
static int | iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force) |
static int | iax2_queue_control_data (int callno, enum ast_control_frame_type control, const void *data, size_t datalen) |
Queue a control frame on the ast_channel owner. | |
static int | iax2_queue_frame (int callno, struct ast_frame *f) |
Queue a frame to a call's owning asterisk channel. | |
static int | iax2_queue_hangup (int callno) |
Queue a hangup frame on the ast_channel owner. | |
static struct ast_frame * | iax2_read (struct ast_channel *c) |
static int | iax2_register (const char *value, int lineno) |
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_sched_replace (int id, struct sched_context *con, int when, ast_sched_cb callback, const void *data) |
static int | iax2_send (struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final) |
static int | iax2_sendhtml (struct ast_channel *c, int subclass, const char *data, int datalen) |
static int | iax2_sendimage (struct ast_channel *c, struct ast_frame *img) |
static int | iax2_sendtext (struct ast_channel *c, const char *text) |
static int | iax2_setoption (struct ast_channel *c, int option, void *data, int datalen) |
static int | iax2_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly) |
static int | iax2_transfer (struct ast_channel *c, const char *dest) |
static int | iax2_transmit (struct iax_frame *fr) |
static int | iax2_trunk_expired (struct iax2_trunk_peer *tpeer, struct timeval *now) |
static int | iax2_trunk_queue (struct chan_iax2_pvt *pvt, struct iax_frame *fr) |
static int | iax2_vnak (int callno) |
static int | iax2_write (struct ast_channel *c, struct ast_frame *f) |
static int | iax_check_version (char *dev) |
static void | iax_debug_output (const char *data) |
static void | iax_error_output (const char *data) |
static int | iax_firmware_append (struct iax_ie_data *ied, const unsigned char *dev, unsigned int desc) |
static void | iax_outputframe (struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen) |
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 void | log_jitterstats (unsigned short callno) |
static int | make_trunk (unsigned short callno, int locked) |
static int | manager_iax2_show_netstats (struct mansession *s, const struct message *m) |
static int | manager_iax2_show_peer_list (struct mansession *s, const struct message *m) |
callback to display iax peers in manager format | |
static int | manager_iax2_show_peers (struct mansession *s, const struct message *m) |
callback to display iax peers in manager | |
static int | match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno) |
static void | memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, ast_aes_decrypt_key *dcx) |
static void | memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, ast_aes_encrypt_key *ecx) |
static void | merge_encryption (struct chan_iax2_pvt *p, unsigned int enc) |
static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
static void * | network_thread (void *ignore) |
static struct chan_iax2_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 | remove_by_transfercallno (struct chan_iax2_pvt *pvt) |
static void | save_osptoken (struct iax_frame *fr, struct iax_ies *ies) |
static void | save_rr (struct iax_frame *fr, struct iax_ies *ies) |
static void * | sched_thread (void *ignore) |
static int | schedule_delivery (struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout) |
static int | scheduled_destroy (const void *vid) |
static int | send_apathetic_reply (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int command, int ts, unsigned char seqno) |
static int | send_command (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_final (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_immediate (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_locked (unsigned short callno, char, int, unsigned int, const unsigned char *, int, int) |
static int | send_command_transfer (struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int) |
static int | send_lagrq (const void *data) |
static int | send_packet (struct iax_frame *f) |
static int | send_ping (const void *data) |
static int | send_trunk (struct iax2_trunk_peer *tpeer, struct timeval *now) |
static int | set_config (char *config_file, int reload) |
Load configuration. | |
static void | set_config_destroy (void) |
static void | signal_condition (ast_mutex_t *lock, ast_cond_t *cond) |
static int | socket_process (struct iax2_thread *thread) |
static int | socket_process_meta (int packet_len, struct ast_iax2_meta_hdr *meta, struct sockaddr_in *sin, int sockfd, struct iax_frame *fr) |
static int | socket_read (int *id, int fd, short events, void *cbdata) |
static void | spawn_dp_lookup (int callno, const char *context, const char *callednum, const char *callerid) |
static int | start_network_thread (void) |
static void | stop_stuff (int callno) |
static void | store_by_peercallno (struct chan_iax2_pvt *pvt) |
static void | store_by_transfercallno (struct chan_iax2_pvt *pvt) |
static int | timing_read (int *id, int fd, short events, void *cbdata) |
static int | transfercallno_pvt_cmp_cb (void *obj, void *arg, int flags) |
static int | transfercallno_pvt_hash_cb (const void *obj, const int flags) |
static int | transmit_trunk (struct iax_frame *f, struct sockaddr_in *sin, int sockfd) |
static int | try_firmware (char *s) |
static int | try_transfer (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
static int | uncompress_subclass (unsigned char csub) |
static void | unlink_peer (struct iax2_peer *peer) |
static int | unload_module (void) |
static void | unlock_both (unsigned short callno0, unsigned short callno1) |
static void | unwrap_timestamp (struct iax_frame *fr) |
static void | update_jbsched (struct chan_iax2_pvt *pvt) |
static void | update_max_nontrunk (void) |
static void | update_max_trunk (void) |
static int | update_packet (struct iax_frame *f) |
static int | update_registry (struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) |
static int | user_cmp_cb (void *obj, void *arg, int flags) |
static int | user_delme_cb (void *obj, void *arg, int flags) |
static void | user_destructor (void *obj) |
static int | user_hash_cb (const void *obj, const int flags) |
static struct iax2_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) |
static int | wait_for_peercallno (struct chan_iax2_pvt *pvt) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Inter Asterisk eXchange (Ver 2)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
static char | accountcode [AST_MAX_ACCOUNT_CODE] |
static int | adsi = 0 |
static int | amaflags = 0 |
static struct ast_module_info * | ast_module_info = &__mod_info |
static int | authdebug = 1 |
static int | autokill = 0 |
static struct ast_cli_entry | cli_iax2 [] |
static struct sockaddr_in | debugaddr |
static char | default_parkinglot [AST_MAX_CONTEXT] |
static int | defaultsockfd = -1 |
static int | delayreject = 0 |
static int | global_max_trunk_mtu |
static int | global_rtautoclear = 120 |
static struct ast_flags | globalflags = { 0 } |
static int | iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH |
static int | iax2_encryption = 0 |
int(*) | iax2_regfunk (const char *username, int onoff) = NULL |
static struct ast_switch | iax2_switch |
static struct ast_channel_tech | iax2_tech |
static struct ast_datastore_info | iax2_variable_datastore_info |
static struct ao2_container * | iax_peercallno_pvts |
Another container of iax2_pvt structures. | |
static struct ao2_container * | iax_transfercallno_pvts |
Another container of iax2_pvt structures. | |
static int | iaxactivethreadcount = 0 |
static int | iaxcompat = 0 |
static int | iaxdebug = 0 |
static int | iaxdefaultdpcache = 10 * 60 |
static int | iaxdefaulttimeout = 5 |
static int | iaxdynamicthreadcount = 0 |
static int | iaxdynamicthreadnum = 0 |
static int | iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT |
ast_custom_function | iaxpeer_function |
static struct chan_iax2_pvt * | iaxs [IAX_MAX_CALLS] |
an array of iax2 pvt structures | |
static ast_mutex_t | iaxsl [ARRAY_LEN(iaxs)] |
chan_iax2_pvt structure locks | |
static int | iaxthreadcount = DEFAULT_THREAD_COUNT |
static int | iaxtrunkdebug = 0 |
static struct ast_custom_function | iaxvar_function |
static struct io_context * | io |
static int | jittertargetextra = 40 |
static int | lagrq_time = 10 |
static char | language [MAX_LANGUAGE] = "" |
static int | last_authmethod = 0 |
static struct timeval | lastused [ARRAY_LEN(iaxs)] |
The last time a call number was used. | |
static int | max_reg_expire |
static int | max_retries = 4 |
static int | maxauthreq = 3 |
static int | maxjitterbuffer = 1000 |
static int | maxjitterinterps = 10 |
static int | maxnontrunkcall = 1 |
static int | maxtrunkcall = TRUNK_CALL_START |
static int | min_reg_expire |
static char | mohinterpret [MAX_MUSICCLASS] |
static char | mohsuggest [MAX_MUSICCLASS] |
static struct ast_netsock_list * | netsock |
static pthread_t | netthreadid = AST_PTHREADT_NULL |
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 * | psyn = "Provision a calling IAXy with a given template" |
struct { | |
unsigned int cos | |
unsigned int tos | |
} | qos |
static char | regcontext [AST_MAX_CONTEXT] = "" |
static int | resyncthreshold = 1000 |
static struct sched_context * | sched |
static ast_cond_t | sched_cond |
static ast_mutex_t | sched_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static pthread_t | schedthreadid = AST_PTHREADT_NULL |
static int | srvlookup = 0 |
static const char | tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)" |
static int | test_losspct = 0 |
static struct ast_timer * | timer |
static int | trunk_maxmtu |
static int | trunk_nmaxmtu |
static int | trunk_timed |
static int | trunk_untimed |
static int | trunkfreq = 20 |
static int | trunkmaxsize = MAX_TRUNKDATA |
static struct ao2_container * | users |
Definition in file chan_iax2.c.
#define ACN_FORMAT1 "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n" |
Referenced by ast_cli_netstats().
#define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n" |
Referenced by ast_cli_netstats().
#define CALLNO_TO_PTR | ( | a | ) | ((void *)(unsigned long)(a)) |
Definition at line 111 of file chan_iax2.c.
Referenced by ast_iax2_new(), iax2_call(), iax2_hangup(), and update_jbsched().
#define DEBUG_SCHED_MULTITHREAD |
Definition at line 103 of file chan_iax2.c.
#define DEBUG_SUPPORT |
Definition at line 119 of file chan_iax2.c.
#define DEFAULT_CONTEXT "default" |
Definition at line 138 of file chan_iax2.c.
Referenced by check_access(), and handle_cli_iax2_show_users().
#define DEFAULT_DROP 3 |
Definition at line 117 of file chan_iax2.c.
#define DEFAULT_FREQ_NOTOK 10 * 1000 |
Definition at line 207 of file chan_iax2.c.
Referenced by build_peer(), handle_response_peerpoke(), and sip_poke_noanswer().
#define DEFAULT_FREQ_OK 60 * 1000 |
#define DEFAULT_MAX_THREAD_COUNT 100 |
Definition at line 114 of file chan_iax2.c.
#define DEFAULT_MAXMS 2000 |
Definition at line 205 of file chan_iax2.c.
#define DEFAULT_RETRY_TIME 1000 |
#define DEFAULT_THREAD_COUNT 10 |
Definition at line 113 of file chan_iax2.c.
#define DEFAULT_TRUNKDATA 640 * 10 |
40ms, uncompressed linear * 10 channels
Definition at line 468 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 %-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 %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 124 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_CALLENCRYPTED | ( | pvt | ) | (ast_test_flag(pvt, IAX_ENCRYPTED) && ast_test_flag(pvt, IAX_KEYPOPULATED)) |
Definition at line 210 of file chan_iax2.c.
Referenced by iax2_send(), iax2_start_transfer(), and socket_process().
#define IAX_CAPABILITY_FULLBANDWIDTH (0xFFFF & ~AST_FORMAT_AUDIO_UNDEFINED) |
Definition at line 187 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 196 of file chan_iax2.c.
Referenced by set_config().
#define IAX_CAPABILITY_LOWFREE |
Value:
Definition at line 201 of file chan_iax2.c.
#define IAX_CAPABILITY_MEDBANDWIDTH |
#define IAX_DEBUGDIGEST | ( | msg, | |||
key | ) |
#define MAX_JITTER_BUFFER 50 |
Definition at line 465 of file chan_iax2.c.
#define MAX_PEER_BUCKETS 563 |
This module will get much higher performance when doing a lot of user and peer lookups if the number of buckets is increased from 1. However, to maintain old behavior for Asterisk 1.4, these are set to 1 by default. When using multiple buckets, search order through these containers is considered random, so you will not be able to depend on the order the entires are specified in iax.conf for matching order.
Definition at line 691 of file chan_iax2.c.
Referenced by load_module().
#define MAX_RETRY_TIME 10000 |
#define MAX_TIMESTAMP_SKEW 160 |
maximum difference between actual and predicted ts for sending
Definition at line 470 of file chan_iax2.c.
#define MAX_TRUNK_MTU 1240 |
Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240.
Definition at line 133 of file chan_iax2.c.
Referenced by handle_cli_iax2_set_mtu(), and set_config_destroy().
#define MAX_TRUNKDATA 640 * 200 |
40ms, uncompressed linear * 200 channels
Definition at line 154 of file chan_iax2.c.
Referenced by set_config(), and set_config_destroy().
#define MAX_USER_BUCKETS MAX_PEER_BUCKETS |
#define MEMORY_SIZE 100 |
Definition at line 116 of file chan_iax2.c.
#define MIN_JITTER_BUFFER 10 |
Definition at line 466 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 1588 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_poke_peer(), iax2_provision(), and iax2_request().
#define NEW_PREVENT 0 |
Definition at line 1586 of file chan_iax2.c.
Referenced by socket_process(), and socket_process_meta().
#define PTR_TO_CALLNO | ( | a | ) | ((unsigned short)(unsigned long)(a)) |
Definition at line 110 of file chan_iax2.c.
Referenced by __auto_congest(), __get_from_jb(), acf_channel_read(), acf_channel_write(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), iax2_write(), and scheduled_destroy().
#define SCHED_MULTITHREADED |
Definition at line 99 of file chan_iax2.c.
#define schedule_action | ( | func, | |||
data | ) | __schedule_action(func, data, __PRETTY_FUNCTION__) |
Definition at line 1186 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 874 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 473 of file chan_iax2.c.
anonymous enum |
Definition at line 700 of file chan_iax2.c.
00700 { 00701 /*! Extension exists */ 00702 CACHE_FLAG_EXISTS = (1 << 0), 00703 /*! Extension is nonexistent */ 00704 CACHE_FLAG_NONEXISTENT = (1 << 1), 00705 /*! Extension can exist */ 00706 CACHE_FLAG_CANEXIST = (1 << 2), 00707 /*! Waiting to hear back response */ 00708 CACHE_FLAG_PENDING = (1 << 3), 00709 /*! Timed out */ 00710 CACHE_FLAG_TIMEOUT = (1 << 4), 00711 /*! Request transmitted */ 00712 CACHE_FLAG_TRANSMITTED = (1 << 5), 00713 /*! Timeout */ 00714 CACHE_FLAG_UNKNOWN = (1 << 6), 00715 /*! Matchmore */ 00716 CACHE_FLAG_MATCHMORE = (1 << 7), 00717 };
enum iax2_flags |
Definition at line 269 of file chan_iax2.c.
00269 { 00270 IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ 00271 IAX_DELME = (1 << 1), /*!< Needs to be deleted */ 00272 IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ 00273 IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ 00274 IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ 00275 IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ 00276 IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ 00277 IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ 00278 /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ 00279 IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ 00280 IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ 00281 IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ 00282 IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ 00283 IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ 00284 IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ 00285 IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ 00286 IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ 00287 IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ 00288 IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ 00289 IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ 00290 IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 00291 IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ 00292 IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ 00293 IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ 00294 IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ 00295 IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a 00296 response, so that we've achieved a three-way handshake with 00297 them before sending voice or anything else*/ 00298 IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */ 00299 };
enum iax2_state |
Definition at line 258 of file chan_iax2.c.
00258 { 00259 IAX_STATE_STARTED = (1 << 0), 00260 IAX_STATE_AUTHENTICATED = (1 << 1), 00261 IAX_STATE_TBD = (1 << 2), 00262 };
enum iax2_thread_iostate |
Definition at line 740 of file chan_iax2.c.
00740 { 00741 IAX_IOSTATE_IDLE, 00742 IAX_IOSTATE_READY, 00743 IAX_IOSTATE_PROCESSING, 00744 IAX_IOSTATE_SCHEDREADY, 00745 };
enum iax2_thread_type |
Definition at line 747 of file chan_iax2.c.
00747 { 00748 IAX_THREAD_TYPE_POOL, 00749 IAX_THREAD_TYPE_DYNAMIC, 00750 };
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 421 of file chan_iax2.c.
00421 { 00422 REG_STATE_UNREGISTERED = 0, 00423 REG_STATE_REGSENT, 00424 REG_STATE_AUTHSENT, 00425 REG_STATE_REGISTERED, 00426 REG_STATE_REJECTED, 00427 REG_STATE_TIMEOUT, 00428 REG_STATE_NOAUTH 00429 };
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 431 of file chan_iax2.c.
00431 { 00432 TRANSFER_NONE = 0, 00433 TRANSFER_BEGIN, 00434 TRANSFER_READY, 00435 TRANSFER_RELEASED, 00436 TRANSFER_PASSTHROUGH, 00437 TRANSFER_MBEGIN, 00438 TRANSFER_MREADY, 00439 TRANSFER_MRELEASED, 00440 TRANSFER_MPASSTHROUGH, 00441 TRANSFER_MEDIA, 00442 TRANSFER_MEDIAPASS 00443 };
static void __attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2469 of file chan_iax2.c.
References AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, f, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iax2_trunk_peer::list, LOG_WARNING, MAX_RETRY_TIME, ast_format::name, REG_STATE_TIMEOUT, sched, send_command(), send_packet(), and update_packet().
Referenced by attempt_transmit().
02470 { 02471 /* Attempt to transmit the frame to the remote peer... 02472 Called without iaxsl held. */ 02473 struct iax_frame *f = (struct iax_frame *)data; 02474 int freeme = 0; 02475 int callno = f->callno; 02476 /* Make sure this call is still active */ 02477 if (callno) 02478 ast_mutex_lock(&iaxsl[callno]); 02479 if (callno && iaxs[callno]) { 02480 if ((f->retries < 0) /* Already ACK'd */ || 02481 (f->retries >= max_retries) /* Too many attempts */) { 02482 /* Record an error if we've transmitted too many times */ 02483 if (f->retries >= max_retries) { 02484 if (f->transfer) { 02485 /* Transfer timeout */ 02486 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 02487 } else if (f->final) { 02488 if (f->final) 02489 iax2_destroy(callno); 02490 } else { 02491 if (iaxs[callno]->owner) 02492 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); 02493 iaxs[callno]->error = ETIMEDOUT; 02494 if (iaxs[callno]->owner) { 02495 struct ast_frame fr = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP, .data.uint32 = AST_CAUSE_DESTINATION_OUT_OF_ORDER }; 02496 /* Hangup the fd */ 02497 iax2_queue_frame(callno, &fr); /* XXX */ 02498 /* Remember, owner could disappear */ 02499 if (iaxs[callno] && iaxs[callno]->owner) 02500 iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 02501 } else { 02502 if (iaxs[callno]->reg) { 02503 memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us)); 02504 iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT; 02505 iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; 02506 } 02507 iax2_destroy(callno); 02508 } 02509 } 02510 02511 } 02512 freeme = 1; 02513 } else { 02514 /* Update it if it needs it */ 02515 update_packet(f); 02516 /* Attempt transmission */ 02517 send_packet(f); 02518 f->retries++; 02519 /* Try again later after 10 times as long */ 02520 f->retrytime *= 10; 02521 if (f->retrytime > MAX_RETRY_TIME) 02522 f->retrytime = MAX_RETRY_TIME; 02523 /* Transfer messages max out at one second */ 02524 if (f->transfer && (f->retrytime > 1000)) 02525 f->retrytime = 1000; 02526 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 02527 } 02528 } else { 02529 /* Make sure it gets freed */ 02530 f->retries = -1; 02531 freeme = 1; 02532 } 02533 if (callno) 02534 ast_mutex_unlock(&iaxsl[callno]); 02535 /* Do not try again */ 02536 if (freeme) { 02537 /* Don't attempt delivery, just remove it from the queue */ 02538 AST_LIST_LOCK(&frame_queue); 02539 AST_LIST_REMOVE(&frame_queue, f, list); 02540 AST_LIST_UNLOCK(&frame_queue); 02541 f->retrans = -1; 02542 /* Free the IAX frame */ 02543 iax2_frame_free(f); 02544 } 02545 }
static void __auth_reject | ( | const void * | nothing | ) | [static] |
Definition at line 7390 of file chan_iax2.c.
References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, and send_command_final().
Referenced by auth_reject().
07391 { 07392 /* Called from IAX thread only, without iaxs lock */ 07393 int callno = (int)(long)(nothing); 07394 struct iax_ie_data ied; 07395 ast_mutex_lock(&iaxsl[callno]); 07396 if (iaxs[callno]) { 07397 memset(&ied, 0, sizeof(ied)); 07398 if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { 07399 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); 07400 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); 07401 } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { 07402 iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); 07403 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 07404 } 07405 send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); 07406 } 07407 ast_mutex_unlock(&iaxsl[callno]); 07408 }
static void __auto_congest | ( | const void * | nothing | ) | [static] |
Definition at line 3575 of file chan_iax2.c.
References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, iax2_queue_frame(), LOG_NOTICE, and PTR_TO_CALLNO.
Referenced by auto_congest().
03576 { 03577 int callno = PTR_TO_CALLNO(nothing); 03578 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; 03579 ast_mutex_lock(&iaxsl[callno]); 03580 if (iaxs[callno]) { 03581 iaxs[callno]->initid = -1; 03582 iax2_queue_frame(callno, &f); 03583 ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n"); 03584 } 03585 ast_mutex_unlock(&iaxsl[callno]); 03586 }
static void __auto_hangup | ( | const void * | nothing | ) | [static] |
Definition at line 7439 of file chan_iax2.c.
References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, and send_command_final().
Referenced by auto_hangup().
07440 { 07441 /* Called from IAX thread only, without iaxs lock */ 07442 int callno = (int)(long)(nothing); 07443 struct iax_ie_data ied; 07444 ast_mutex_lock(&iaxsl[callno]); 07445 if (iaxs[callno]) { 07446 memset(&ied, 0, sizeof(ied)); 07447 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); 07448 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); 07449 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 07450 } 07451 ast_mutex_unlock(&iaxsl[callno]); 07452 }
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 2262 of file chan_iax2.c.
References iax_frame::af, ast_clear_flag, AST_FRFLAG_HAS_TIMING_INFO, ast_test_flag, iax_frame::callno, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, and iax_frame::retrans.
Referenced by __get_from_jb(), and schedule_delivery().
02263 { 02264 /* Just deliver the packet by using queueing. This is called by 02265 the IAX thread with the iaxsl lock held. */ 02266 struct iax_frame *fr = data; 02267 fr->retrans = -1; 02268 ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO); 02269 if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) 02270 iax2_queue_frame(fr->callno, &fr->af); 02271 /* Free our iax frame */ 02272 iax2_frame_free(fr); 02273 /* And don't run again */ 02274 return 0; 02275 }
static void __expire_registry | ( | const void * | data | ) | [static] |
Definition at line 7051 of file chan_iax2.c.
References iax2_peer::addr, ast_db_del(), ast_debug, AST_DEVICE_UNAVAILABLE, ast_devstate_changed(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, globalflags, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, manager_event, iax2_peer::name, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().
Referenced by expire_registry().
07052 { 07053 struct iax2_peer *peer = (struct iax2_peer *) data; 07054 07055 if (!peer) 07056 return; 07057 07058 peer->expire = -1; 07059 07060 ast_debug(1, "Expiring registration for peer '%s'\n", peer->name); 07061 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) 07062 realtime_update_peer(peer->name, &peer->addr, 0); 07063 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 07064 /* Reset the address */ 07065 memset(&peer->addr, 0, sizeof(peer->addr)); 07066 /* Reset expiry value */ 07067 peer->expiry = min_reg_expire; 07068 if (!ast_test_flag(peer, IAX_TEMPONLY)) 07069 ast_db_del("IAX/Registry", peer->name); 07070 register_peer_exten(peer, 0); 07071 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ 07072 if (iax2_regfunk) 07073 iax2_regfunk(peer->name, 0); 07074 07075 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) 07076 unlink_peer(peer); 07077 07078 peer_unref(peer); 07079 }
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 1733 of file chan_iax2.c.
References chan_iax2_pvt::addr, ao2_find, ao2_ref, ast_copy_flags, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_string_field_set, ast_tvnow(), chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, globalflags, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, iax_transfercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, LOG_WARNING, match(), MIN_REUSE_TIME, NEW_ALLOW, new_iax(), OBJ_POINTER, parkinglot, chan_iax2_pvt::peercallno, sched, send_lagrq(), send_ping(), store_by_peercallno(), chan_iax2_pvt::transfer, TRUNK_CALL_START, and update_max_nontrunk().
Referenced by find_callno(), and find_callno_locked().
01734 { 01735 int res = 0; 01736 int x; 01737 struct timeval now; 01738 char host[80]; 01739 01740 if (new <= NEW_ALLOW) { 01741 if (callno) { 01742 struct chan_iax2_pvt *pvt; 01743 struct chan_iax2_pvt tmp_pvt = { 01744 .callno = dcallno, 01745 .peercallno = callno, 01746 .transfercallno = callno, 01747 /* hack!! */ 01748 .frames_received = check_dcallno, 01749 }; 01750 01751 memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr)); 01752 /* this works for finding normal call numbers not involving transfering */ 01753 if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 01754 if (return_locked) { 01755 ast_mutex_lock(&iaxsl[pvt->callno]); 01756 } 01757 res = pvt->callno; 01758 ao2_ref(pvt, -1); 01759 pvt = NULL; 01760 return res; 01761 } 01762 /* this searches for transfer call numbers that might not get caught otherwise */ 01763 memset(&tmp_pvt.addr, 0, sizeof(tmp_pvt.addr)); 01764 memcpy(&tmp_pvt.transfer, sin, sizeof(tmp_pvt.addr)); 01765 if ((pvt = ao2_find(iax_transfercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 01766 if (return_locked) { 01767 ast_mutex_lock(&iaxsl[pvt->callno]); 01768 } 01769 res = pvt->callno; 01770 ao2_ref(pvt, -1); 01771 pvt = NULL; 01772 return res; 01773 } 01774 } 01775 /* This will occur on the first response to a message that we initiated, 01776 * such as a PING. */ 01777 if (dcallno) { 01778 ast_mutex_lock(&iaxsl[dcallno]); 01779 } 01780 if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) { 01781 iaxs[dcallno]->peercallno = callno; 01782 res = dcallno; 01783 store_by_peercallno(iaxs[dcallno]); 01784 if (!res || !return_locked) { 01785 ast_mutex_unlock(&iaxsl[dcallno]); 01786 } 01787 return res; 01788 } 01789 if (dcallno) { 01790 ast_mutex_unlock(&iaxsl[dcallno]); 01791 } 01792 #ifdef IAX_OLD_FIND 01793 /* If we get here, we SHOULD NOT find a call structure for this 01794 callno; if we do, it means that there is a call structure that 01795 has a peer callno but did NOT get entered into the hash table, 01796 which is bad. 01797 01798 If we find a call structure using this old, slow method, output a log 01799 message so we'll know about it. After a few months of leaving this in 01800 place, if we don't hear about people seeing these messages, we can 01801 remove this code for good. 01802 */ 01803 01804 for (x = 1; !res && x < maxnontrunkcall; x++) { 01805 ast_mutex_lock(&iaxsl[x]); 01806 if (iaxs[x]) { 01807 /* Look for an exact match */ 01808 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01809 res = x; 01810 } 01811 } 01812 if (!res || !return_locked) 01813 ast_mutex_unlock(&iaxsl[x]); 01814 } 01815 for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) { 01816 ast_mutex_lock(&iaxsl[x]); 01817 if (iaxs[x]) { 01818 /* Look for an exact match */ 01819 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01820 res = x; 01821 } 01822 } 01823 if (!res || !return_locked) 01824 ast_mutex_unlock(&iaxsl[x]); 01825 } 01826 #endif 01827 } 01828 if (!res && (new >= NEW_ALLOW)) { 01829 int start, found = 0; 01830 01831 /* It may seem odd that we look through the peer list for a name for 01832 * this *incoming* call. Well, it is weird. However, users don't 01833 * have an IP address/port number that we can match against. So, 01834 * this is just checking for a peer that has that IP/port and 01835 * assuming that we have a user of the same name. This isn't always 01836 * correct, but it will be changed if needed after authentication. */ 01837 if (!iax2_getpeername(*sin, host, sizeof(host))) 01838 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 01839 01840 now = ast_tvnow(); 01841 start = 2 + (ast_random() % (TRUNK_CALL_START - 1)); 01842 for (x = start; 1; x++) { 01843 if (x == TRUNK_CALL_START) { 01844 x = 1; 01845 continue; 01846 } 01847 01848 /* Find first unused call number that hasn't been used in a while */ 01849 ast_mutex_lock(&iaxsl[x]); 01850 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01851 found = 1; 01852 break; 01853 } 01854 ast_mutex_unlock(&iaxsl[x]); 01855 01856 if (x == start - 1) { 01857 break; 01858 } 01859 } 01860 /* We've still got lock held if we found a spot */ 01861 if (x == start - 1 && !found) { 01862 ast_log(LOG_WARNING, "No more space\n"); 01863 return 0; 01864 } 01865 iaxs[x] = new_iax(sin, host); 01866 update_max_nontrunk(); 01867 if (iaxs[x]) { 01868 if (iaxdebug) 01869 ast_debug(1, "Creating new call structure %d\n", x); 01870 iaxs[x]->sockfd = sockfd; 01871 iaxs[x]->addr.sin_port = sin->sin_port; 01872 iaxs[x]->addr.sin_family = sin->sin_family; 01873 iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr; 01874 iaxs[x]->peercallno = callno; 01875 iaxs[x]->callno = x; 01876 iaxs[x]->pingtime = DEFAULT_RETRY_TIME; 01877 iaxs[x]->expiry = min_reg_expire; 01878 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01879 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01880 iaxs[x]->amaflags = amaflags; 01881 ast_copy_flags(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 01882 01883 ast_string_field_set(iaxs[x], accountcode, accountcode); 01884 ast_string_field_set(iaxs[x], mohinterpret, mohinterpret); 01885 ast_string_field_set(iaxs[x], mohsuggest, mohsuggest); 01886 ast_string_field_set(iaxs[x], parkinglot, default_parkinglot); 01887 01888 if (iaxs[x]->peercallno) { 01889 store_by_peercallno(iaxs[x]); 01890 } 01891 } else { 01892 ast_log(LOG_WARNING, "Out of resources\n"); 01893 ast_mutex_unlock(&iaxsl[x]); 01894 return 0; 01895 } 01896 if (!return_locked) 01897 ast_mutex_unlock(&iaxsl[x]); 01898 res = x; 01899 } 01900 return res; 01901 }
static void __get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 3028 of file chan_iax2.c.
References __do_deliver(), ast_codec_interp_len(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_test_flag, ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, chan_iax2_pvt::jb, JB_DROP, JB_EMPTY, jb_get(), JB_INTERP, jb_next(), JB_NOFRAME, JB_OK, chan_iax2_pvt::jbid, jb_frame::ms, iax2_trunk_peer::next, ast_frame::offset, PTR_TO_CALLNO, chan_iax2_pvt::rxcore, ast_frame::samples, ast_frame::src, ast_frame::subclass, update_jbsched(), and chan_iax2_pvt::voiceformat.
Referenced by get_from_jb().
03029 { 03030 int callno = PTR_TO_CALLNO(p); 03031 struct chan_iax2_pvt *pvt = NULL; 03032 struct iax_frame *fr; 03033 jb_frame frame; 03034 int ret; 03035 long ms; 03036 long next; 03037 struct timeval now = ast_tvnow(); 03038 03039 /* Make sure we have a valid private structure before going on */ 03040 ast_mutex_lock(&iaxsl[callno]); 03041 pvt = iaxs[callno]; 03042 if (!pvt) { 03043 /* No go! */ 03044 ast_mutex_unlock(&iaxsl[callno]); 03045 return; 03046 } 03047 03048 pvt->jbid = -1; 03049 03050 /* round up a millisecond since ast_sched_runq does; */ 03051 /* prevents us from spinning while waiting for our now */ 03052 /* to catch up with runq's now */ 03053 now.tv_usec += 1000; 03054 03055 ms = ast_tvdiff_ms(now, pvt->rxcore); 03056 03057 if(ms >= (next = jb_next(pvt->jb))) { 03058 ret = jb_get(pvt->jb,&frame,ms,ast_codec_interp_len(pvt->voiceformat)); 03059 switch(ret) { 03060 case JB_OK: 03061 fr = frame.data; 03062 __do_deliver(fr); 03063 /* __do_deliver() can cause the call to disappear */ 03064 pvt = iaxs[callno]; 03065 break; 03066 case JB_INTERP: 03067 { 03068 struct ast_frame af = { 0, }; 03069 03070 /* create an interpolation frame */ 03071 af.frametype = AST_FRAME_VOICE; 03072 af.subclass = pvt->voiceformat; 03073 af.samples = frame.ms * 8; 03074 af.src = "IAX2 JB interpolation"; 03075 af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); 03076 af.offset = AST_FRIENDLY_OFFSET; 03077 03078 /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame, 03079 * which we'd need to malloc, and then it would free it. That seems like a drag */ 03080 if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 03081 iax2_queue_frame(callno, &af); 03082 /* iax2_queue_frame() could cause the call to disappear */ 03083 pvt = iaxs[callno]; 03084 } 03085 } 03086 break; 03087 case JB_DROP: 03088 iax2_frame_free(frame.data); 03089 break; 03090 case JB_NOFRAME: 03091 case JB_EMPTY: 03092 /* do nothing */ 03093 break; 03094 default: 03095 /* shouldn't happen */ 03096 break; 03097 } 03098 } 03099 if (pvt) 03100 update_jbsched(pvt); 03101 ast_mutex_unlock(&iaxsl[callno]); 03102 }
static void __iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 6736 of file chan_iax2.c.
References iax2_registry::expire, and iax2_do_register().
Referenced by iax2_do_register_s().
06737 { 06738 struct iax2_registry *reg = (struct iax2_registry *)data; 06739 reg->expire = -1; 06740 iax2_do_register(reg); 06741 }
static void __iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 10161 of file chan_iax2.c.
References AST_DEVICE_UNAVAILABLE, ast_devstate_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iax2_sched_add(), iax2_peer::lastms, LOG_NOTICE, manager_event, iax2_peer::name, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, and sched.
Referenced by iax2_poke_noanswer().
10162 { 10163 struct iax2_peer *peer = (struct iax2_peer *)data; 10164 int callno; 10165 10166 if (peer->lastms > -1) { 10167 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); 10168 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); 10169 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ 10170 } 10171 if ((callno = peer->callno) > 0) { 10172 ast_mutex_lock(&iaxsl[callno]); 10173 iax2_destroy(callno); 10174 ast_mutex_unlock(&iaxsl[callno]); 10175 } 10176 peer->callno = 0; 10177 peer->lastms = -1; 10178 /* Try again quickly */ 10179 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 10180 if (peer->pokeexpire == -1) 10181 peer_unref(peer); 10182 }
static void __iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 7502 of file chan_iax2.c.
References iax2_poke_peer(), and peer_unref().
Referenced by iax2_poke_peer_s().
07503 { 07504 struct iax2_peer *peer = (struct iax2_peer *)data; 07505 iax2_poke_peer(peer, 0); 07506 peer_unref(peer); 07507 }
static int __iax2_show_peers | ( | int | manager, | |
int | fd, | |||
struct mansession * | s, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 5219 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_cli(), ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, iax2_peer::name, name, peer_status(), peer_unref(), RESULT_SHOWUSAGE, RESULT_SUCCESS, s, status, and iax2_peer::username.
Referenced by handle_cli_iax2_show_peers(), and manager_iax2_show_peers().
05220 { 05221 regex_t regexbuf; 05222 int havepattern = 0; 05223 int total_peers = 0; 05224 int online_peers = 0; 05225 int offline_peers = 0; 05226 int unmonitored_peers = 0; 05227 struct ao2_iterator i; 05228 05229 #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" 05230 #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" 05231 05232 struct iax2_peer *peer = NULL; 05233 char name[256]; 05234 int registeredonly=0; 05235 char *term = manager ? "\r\n" : "\n"; 05236 char idtext[256] = ""; 05237 switch (argc) { 05238 case 6: 05239 if (!strcasecmp(argv[3], "registered")) 05240 registeredonly = 1; 05241 else 05242 return RESULT_SHOWUSAGE; 05243 if (!strcasecmp(argv[4], "like")) { 05244 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB)) 05245 return RESULT_SHOWUSAGE; 05246 havepattern = 1; 05247 } else 05248 return RESULT_SHOWUSAGE; 05249 break; 05250 case 5: 05251 if (!strcasecmp(argv[3], "like")) { 05252 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 05253 return RESULT_SHOWUSAGE; 05254 havepattern = 1; 05255 } else 05256 return RESULT_SHOWUSAGE; 05257 break; 05258 case 4: 05259 if (!strcasecmp(argv[3], "registered")) 05260 registeredonly = 1; 05261 else 05262 return RESULT_SHOWUSAGE; 05263 break; 05264 case 3: 05265 break; 05266 default: 05267 return RESULT_SHOWUSAGE; 05268 } 05269 05270 05271 if (!s) 05272 ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 05273 05274 i = ao2_iterator_init(peers, 0); 05275 for (peer = ao2_iterator_next(&i); peer; 05276 peer_unref(peer), peer = ao2_iterator_next(&i)) { 05277 char nm[20]; 05278 char status[20]; 05279 char srch[2000]; 05280 int retstatus; 05281 05282 if (registeredonly && !peer->addr.sin_addr.s_addr) 05283 continue; 05284 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) 05285 continue; 05286 05287 if (!ast_strlen_zero(peer->username)) 05288 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 05289 else 05290 ast_copy_string(name, peer->name, sizeof(name)); 05291 05292 retstatus = peer_status(peer, status, sizeof(status)); 05293 if (retstatus > 0) 05294 online_peers++; 05295 else if (!retstatus) 05296 offline_peers++; 05297 else 05298 unmonitored_peers++; 05299 05300 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 05301 05302 snprintf(srch, sizeof(srch), FORMAT, name, 05303 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 05304 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 05305 nm, 05306 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 05307 peer->encmethods ? "(E)" : " ", status, term); 05308 05309 if (s) 05310 astman_append(s, 05311 "Event: PeerEntry\r\n%s" 05312 "Channeltype: IAX2\r\n" 05313 "ChanObjectType: peer\r\n" 05314 "ObjectName: %s\r\n" 05315 "IPaddress: %s\r\n" 05316 "IPport: %d\r\n" 05317 "Dynamic: %s\r\n" 05318 "Status: %s\r\n\r\n", 05319 idtext, 05320 name, 05321 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-", 05322 ntohs(peer->addr.sin_port), 05323 ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no", 05324 status); 05325 05326 else 05327 ast_cli(fd, FORMAT, name, 05328 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 05329 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 05330 nm, 05331 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 05332 peer->encmethods ? "(E)" : " ", status, term); 05333 total_peers++; 05334 } 05335 05336 if (!s) 05337 ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 05338 05339 if (havepattern) 05340 regfree(®exbuf); 05341 05342 return RESULT_SUCCESS; 05343 #undef FORMAT 05344 #undef FORMAT2 05345 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 12539 of file chan_iax2.c.
static int __schedule_action | ( | void(*)(const void *data) | func, | |
const void * | data, | |||
const char * | funcname | |||
) | [static] |
Definition at line 1161 of file chan_iax2.c.
References ast_copy_string(), ast_debug, find_idle_thread(), IAX_IOSTATE_SCHEDREADY, signal_condition(), and thread.
01162 { 01163 struct iax2_thread *thread = NULL; 01164 static time_t lasterror; 01165 static time_t t; 01166 01167 thread = find_idle_thread(); 01168 01169 if (thread != NULL) { 01170 thread->schedfunc = func; 01171 thread->scheddata = data; 01172 thread->iostate = IAX_IOSTATE_SCHEDREADY; 01173 #ifdef DEBUG_SCHED_MULTITHREAD 01174 ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc)); 01175 #endif 01176 signal_condition(&thread->lock, &thread->cond); 01177 return 0; 01178 } 01179 time(&t); 01180 if (t != lasterror) 01181 ast_debug(1, "Out of idle IAX2 threads for scheduling!\n"); 01182 lasterror = t; 01183 01184 return -1; 01185 }
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 5951 of file chan_iax2.c.
References f, and iax2_send().
Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().
05953 { 05954 struct ast_frame f = { 0, }; 05955 05956 f.frametype = type; 05957 f.subclass = command; 05958 f.datalen = datalen; 05959 f.src = __FUNCTION__; 05960 f.data.ptr = (void *) data; 05961 05962 return iax2_send(i, &f, ts, seqno, now, transfer, final); 05963 }
static void __send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1254 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_thread::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, LOG_WARNING, sched, send_command(), and send_lagrq().
Referenced by send_lagrq().
01255 { 01256 int callno = (long) data; 01257 01258 ast_mutex_lock(&iaxsl[callno]); 01259 01260 if (iaxs[callno]) { 01261 if (iaxs[callno]->peercallno) { 01262 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); 01263 iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data); 01264 } else { 01265 /* I am the schedule, so I'm allowed to do this */ 01266 iaxs[callno]->lagid = -1; 01267 } 01268 } else { 01269 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); 01270 } 01271 01272 ast_mutex_unlock(&iaxsl[callno]); 01273 }
static void __send_ping | ( | const void * | data | ) | [static] |
Definition at line 1209 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_thread::callno, iax2_sched_add(), IAX_COMMAND_PING, LOG_DEBUG, option_debug, sched, send_command(), and send_ping().
Referenced by send_ping().
01210 { 01211 int callno = (long) data; 01212 01213 ast_mutex_lock(&iaxsl[callno]); 01214 01215 if (iaxs[callno]) { 01216 if (iaxs[callno]->peercallno) { 01217 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); 01218 iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data); 01219 } else { 01220 /* I am the schedule, so I'm allowed to do this */ 01221 iaxs[callno]->pingid = -1; 01222 } 01223 } else if (option_debug > 0) { 01224 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); 01225 } 01226 01227 ast_mutex_unlock(&iaxsl[callno]); 01228 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 12278 of file chan_iax2.c.
References ao2_ref, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), ast_context_destroy(), ast_context_find(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_release(), AST_PTHREADT_NULL, ast_timer_close(), ast_unload_realtime(), ast_unregister_application(), ast_unregister_switch(), cli_iax2, delete_users(), iax2_destroy(), iax2_switch, iax2_tech, iax_peercallno_pvts, iax_provision_unload(), iax_transfercallno_pvts, iaxactivethreadcount, netsock, outsock, papp, reload_firmware(), sched, sched_context_destroy(), sched_lock, thread, and timer.
12279 { 12280 struct iax2_thread *thread = NULL; 12281 struct ast_context *con; 12282 int x; 12283 12284 /* Make sure threads do not hold shared resources when they are canceled */ 12285 12286 /* Grab the sched lock resource to keep it away from threads about to die */ 12287 /* Cancel the network thread, close the net socket */ 12288 if (netthreadid != AST_PTHREADT_NULL) { 12289 AST_LIST_LOCK(&frame_queue); 12290 ast_mutex_lock(&sched_lock); 12291 pthread_cancel(netthreadid); 12292 ast_cond_signal(&sched_cond); 12293 ast_mutex_unlock(&sched_lock); /* Release the schedule lock resource */ 12294 AST_LIST_UNLOCK(&frame_queue); 12295 pthread_join(netthreadid, NULL); 12296 } 12297 if (schedthreadid != AST_PTHREADT_NULL) { 12298 ast_mutex_lock(&sched_lock); 12299 pthread_cancel(schedthreadid); 12300 ast_cond_signal(&sched_cond); 12301 ast_mutex_unlock(&sched_lock); 12302 pthread_join(schedthreadid, NULL); 12303 } 12304 12305 /* Call for all threads to halt */ 12306 AST_LIST_LOCK(&idle_list); 12307 while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list))) 12308 pthread_cancel(thread->threadid); 12309 AST_LIST_UNLOCK(&idle_list); 12310 12311 AST_LIST_LOCK(&active_list); 12312 while ((thread = AST_LIST_REMOVE_HEAD(&active_list, list))) 12313 pthread_cancel(thread->threadid); 12314 AST_LIST_UNLOCK(&active_list); 12315 12316 AST_LIST_LOCK(&dynamic_list); 12317 while ((thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list))) 12318 pthread_cancel(thread->threadid); 12319 AST_LIST_UNLOCK(&dynamic_list); 12320 12321 /* Wait for threads to exit */ 12322 while(0 < iaxactivethreadcount) 12323 usleep(10000); 12324 12325 ast_netsock_release(netsock); 12326 ast_netsock_release(outsock); 12327 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 12328 if (iaxs[x]) { 12329 iax2_destroy(x); 12330 } 12331 } 12332 ast_manager_unregister( "IAXpeers" ); 12333 ast_manager_unregister( "IAXpeerlist" ); 12334 ast_manager_unregister( "IAXnetstats" ); 12335 ast_unregister_application(papp); 12336 ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 12337 ast_unregister_switch(&iax2_switch); 12338 ast_channel_unregister(&iax2_tech); 12339 delete_users(); 12340 iax_provision_unload(); 12341 sched_context_destroy(sched); 12342 reload_firmware(1); 12343 12344 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 12345 ast_mutex_destroy(&iaxsl[x]); 12346 } 12347 12348 ao2_ref(peers, -1); 12349 ao2_ref(users, -1); 12350 ao2_ref(iax_peercallno_pvts, -1); 12351 ao2_ref(iax_transfercallno_pvts, -1); 12352 if (timer) { 12353 ast_timer_close(timer); 12354 } 12355 12356 con = ast_context_find(regcontext); 12357 if (con) 12358 ast_context_destroy(con, "IAX2"); 12359 ast_unload_realtime("iaxpeers"); 12360 return 0; 12361 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 12539 of file chan_iax2.c.
static int acf_channel_read | ( | struct ast_channel * | chan, | |
const char * | funcname, | |||
char * | preparse, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 12064 of file chan_iax2.c.
References chan_iax2_pvt::addr, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), chan, iax2_tech, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, and chan_iax2_pvt::username.
12065 { 12066 struct chan_iax2_pvt *pvt; 12067 unsigned int callno; 12068 int res = 0; 12069 12070 if (!chan || chan->tech != &iax2_tech) { 12071 ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); 12072 return -1; 12073 } 12074 12075 callno = PTR_TO_CALLNO(chan->tech_pvt); 12076 ast_mutex_lock(&iaxsl[callno]); 12077 if (!(pvt = iaxs[callno])) { 12078 ast_mutex_unlock(&iaxsl[callno]); 12079 return -1; 12080 } 12081 12082 if (!strcasecmp(args, "osptoken")) { 12083 ast_copy_string(buf, pvt->osptoken, buflen); 12084 } else if (!strcasecmp(args, "peerip")) { 12085 ast_copy_string(buf, pvt->addr.sin_addr.s_addr ? ast_inet_ntoa(pvt->addr.sin_addr) : "", buflen); 12086 } else if (!strcasecmp(args, "peername")) { 12087 ast_copy_string(buf, pvt->username, buflen); 12088 } else { 12089 res = -1; 12090 } 12091 12092 ast_mutex_unlock(&iaxsl[callno]); 12093 12094 return res; 12095 }
static int acf_channel_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 12036 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_set, chan, iax2_tech, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
12037 { 12038 struct chan_iax2_pvt *pvt; 12039 unsigned int callno; 12040 int res = 0; 12041 12042 if (!chan || chan->tech != &iax2_tech) { 12043 ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); 12044 return -1; 12045 } 12046 12047 callno = PTR_TO_CALLNO(chan->tech_pvt); 12048 ast_mutex_lock(&iaxsl[callno]); 12049 if (!(pvt = iaxs[callno])) { 12050 ast_mutex_unlock(&iaxsl[callno]); 12051 return -1; 12052 } 12053 12054 if (!strcasecmp(args, "osptoken")) 12055 ast_string_field_set(pvt, osptoken, value); 12056 else 12057 res = -1; 12058 12059 ast_mutex_unlock(&iaxsl[callno]); 12060 12061 return res; 12062 }
static int acf_iaxvar_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 8170 of file chan_iax2.c.
References ast_channel_datastore_find(), ast_copy_string(), AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, chan, ast_datastore::data, ast_var_t::entries, iax2_variable_datastore_info, and var.
08171 { 08172 struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL); 08173 AST_LIST_HEAD(, ast_var_t) *varlist; 08174 struct ast_var_t *var; 08175 08176 if (!variablestore) { 08177 *buf = '\0'; 08178 return 0; 08179 } 08180 varlist = variablestore->data; 08181 08182 AST_LIST_LOCK(varlist); 08183 AST_LIST_TRAVERSE(varlist, var, entries) { 08184 if (strcmp(var->name, data) == 0) { 08185 ast_copy_string(buf, var->value, len); 08186 break; 08187 } 08188 } 08189 AST_LIST_UNLOCK(varlist); 08190 return 0; 08191 }
static int acf_iaxvar_write | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 8193 of file chan_iax2.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_delete(), chan, ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_var_t::entries, iax2_variable_datastore_info, ast_datastore::inheritance, LOG_ERROR, and var.
08194 { 08195 struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL); 08196 AST_LIST_HEAD(, ast_var_t) *varlist; 08197 struct ast_var_t *var; 08198 08199 if (!variablestore) { 08200 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 08201 if (!variablestore) { 08202 ast_log(LOG_ERROR, "Memory allocation error\n"); 08203 return -1; 08204 } 08205 varlist = ast_calloc(1, sizeof(*varlist)); 08206 if (!varlist) { 08207 ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data); 08208 return -1; 08209 } 08210 08211 AST_LIST_HEAD_INIT(varlist); 08212 variablestore->data = varlist; 08213 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 08214 ast_channel_datastore_add(chan, variablestore); 08215 } else 08216 varlist = variablestore->data; 08217 08218 AST_LIST_LOCK(varlist); 08219 AST_LIST_TRAVERSE_SAFE_BEGIN(varlist, var, entries) { 08220 if (strcmp(var->name, data) == 0) { 08221 AST_LIST_REMOVE_CURRENT(entries); 08222 ast_var_delete(var); 08223 break; 08224 } 08225 } 08226 AST_LIST_TRAVERSE_SAFE_END; 08227 var = ast_var_assign(data, value); 08228 if (var) 08229 AST_LIST_INSERT_TAIL(varlist, var, entries); 08230 else 08231 ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data); 08232 AST_LIST_UNLOCK(varlist); 08233 return 0; 08234 }
static int apply_context | ( | struct iax2_context * | con, | |
const char * | context | |||
) | [static] |
Definition at line 6004 of file chan_iax2.c.
References iax2_context::context, and iax2_context::next.
Referenced by check_access().
06005 { 06006 while(con) { 06007 if (!strcmp(con->context, context) || !strcmp(con->context, "*")) 06008 return -1; 06009 con = con->next; 06010 } 06011 return 0; 06012 }
static int ast_cli_netstats | ( | struct mansession * | s, | |
int | fd, | |||
int | limit_fmt | |||
) | [static] |
Definition at line 5722 of file chan_iax2.c.
References ACN_FORMAT1, ACN_FORMAT2, ARRAY_LEN, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, IAX_USEJITTERBUF, jb_getinfo(), jb_info::jitter, jb_info::losspct, jb_info::min, and s.
Referenced by handle_cli_iax2_show_netstats(), and manager_iax2_show_netstats().
05723 { 05724 int x; 05725 int numchans = 0; 05726 #define ACN_FORMAT1 "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n" 05727 #define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n" 05728 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 05729 ast_mutex_lock(&iaxsl[x]); 05730 if (iaxs[x]) { 05731 int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; 05732 jb_info jbinfo; 05733 05734 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 05735 jb_getinfo(iaxs[x]->jb, &jbinfo); 05736 localjitter = jbinfo.jitter; 05737 localdelay = jbinfo.current - jbinfo.min; 05738 locallost = jbinfo.frames_lost; 05739 locallosspct = jbinfo.losspct/1000; 05740 localdropped = jbinfo.frames_dropped; 05741 localooo = jbinfo.frames_ooo; 05742 } else { 05743 localjitter = -1; 05744 localdelay = 0; 05745 locallost = -1; 05746 locallosspct = -1; 05747 localdropped = 0; 05748 localooo = -1; 05749 } 05750 if (s) 05751 05752 astman_append(s, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2, 05753 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 05754 iaxs[x]->pingtime, 05755 localjitter, 05756 localdelay, 05757 locallost, 05758 locallosspct, 05759 localdropped, 05760 localooo, 05761 iaxs[x]->frames_received/1000, 05762 iaxs[x]->remote_rr.jitter, 05763 iaxs[x]->remote_rr.delay, 05764 iaxs[x]->remote_rr.losscnt, 05765 iaxs[x]->remote_rr.losspct, 05766 iaxs[x]->remote_rr.dropped, 05767 iaxs[x]->remote_rr.ooo, 05768 iaxs[x]->remote_rr.packets/1000); 05769 else 05770 ast_cli(fd, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2, 05771 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 05772 iaxs[x]->pingtime, 05773 localjitter, 05774 localdelay, 05775 locallost, 05776 locallosspct, 05777 localdropped, 05778 localooo, 05779 iaxs[x]->frames_received/1000, 05780 iaxs[x]->remote_rr.jitter, 05781 iaxs[x]->remote_rr.delay, 05782 iaxs[x]->remote_rr.losscnt, 05783 iaxs[x]->remote_rr.losspct, 05784 iaxs[x]->remote_rr.dropped, 05785 iaxs[x]->remote_rr.ooo, 05786 iaxs[x]->remote_rr.packets/1000 05787 ); 05788 numchans++; 05789 } 05790 ast_mutex_unlock(&iaxsl[x]); 05791 } 05792 05793 return numchans; 05794 }
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 4322 of file chan_iax2.c.
References chan_iax2_pvt::accountcode, chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, chan_iax2_pvt::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc(), ast_channel_datastore_add(), ast_channel_free(), ast_copy_string(), ast_datastore_alloc(), ast_datastore_free(), ast_debug, ast_free, ast_hangup(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, chan_iax2_pvt::callno, CALLNO_TO_PTR, chan_iax2_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, chan_iax2_pvt::cid_name, chan_iax2_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, chan_iax2_pvt::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, chan_iax2_pvt::dnid, ast_var_t::entries, ast_channel::exten, chan_iax2_pvt::exten, chan_iax2_pvt::host, iax2_ami_channelupdate(), iax2_tech, iax2_variable_datastore_info, chan_iax2_pvt::iaxvars, ast_datastore::inheritance, chan_iax2_pvt::language, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, chan_iax2_pvt::owner, parkinglot, chan_iax2_pvt::parkinglot, pbx_builtin_setvar_helper(), chan_iax2_pvt::peeradsicpe, ast_channel::rawreadformat, ast_channel::rawwriteformat, chan_iax2_pvt::rdnis, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, var, chan_iax2_pvt::vars, and ast_channel::writeformat.
Referenced by iax2_request(), and socket_process().
04323 { 04324 struct ast_channel *tmp; 04325 struct chan_iax2_pvt *i; 04326 struct ast_variable *v = NULL; 04327 04328 if (!(i = iaxs[callno])) { 04329 ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); 04330 return NULL; 04331 } 04332 04333 /* Don't hold call lock */ 04334 ast_mutex_unlock(&iaxsl[callno]); 04335 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); 04336 ast_mutex_lock(&iaxsl[callno]); 04337 if (i != iaxs[callno]) { 04338 if (tmp) { 04339 /* unlock and relock iaxsl[callno] to preserve locking order */ 04340 ast_mutex_unlock(&iaxsl[callno]); 04341 ast_channel_free(tmp); 04342 ast_mutex_lock(&iaxsl[callno]); 04343 } 04344 return NULL; 04345 } 04346 iax2_ami_channelupdate(i); 04347 if (!tmp) 04348 return NULL; 04349 tmp->tech = &iax2_tech; 04350 /* We can support any format by default, until we get restricted */ 04351 tmp->nativeformats = capability; 04352 tmp->readformat = tmp->rawreadformat = ast_best_codec(capability); 04353 tmp->writeformat = tmp->rawwriteformat = ast_best_codec(capability); 04354 tmp->tech_pvt = CALLNO_TO_PTR(i->callno); 04355 04356 if (!ast_strlen_zero(i->parkinglot)) 04357 ast_string_field_set(tmp, parkinglot, i->parkinglot); 04358 /* Don't use ast_set_callerid() here because it will 04359 * generate a NewCallerID event before the NewChannel event */ 04360 if (!ast_strlen_zero(i->ani)) 04361 tmp->cid.cid_ani = ast_strdup(i->ani); 04362 else 04363 tmp->cid.cid_ani = ast_strdup(i->cid_num); 04364 tmp->cid.cid_dnid = ast_strdup(i->dnid); 04365 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 04366 tmp->cid.cid_pres = i->calling_pres; 04367 tmp->cid.cid_ton = i->calling_ton; 04368 tmp->cid.cid_tns = i->calling_tns; 04369 if (!ast_strlen_zero(i->language)) 04370 ast_string_field_set(tmp, language, i->language); 04371 if (!ast_strlen_zero(i->accountcode)) 04372 ast_string_field_set(tmp, accountcode, i->accountcode); 04373 if (i->amaflags) 04374 tmp->amaflags = i->amaflags; 04375 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 04376 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 04377 if (i->adsi) 04378 tmp->adsicpe = i->peeradsicpe; 04379 else 04380 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 04381 i->owner = tmp; 04382 i->capability = capability; 04383 04384 /* Set inherited variables */ 04385 if (i->vars) { 04386 for (v = i->vars ; v ; v = v->next) 04387 pbx_builtin_setvar_helper(tmp, v->name, v->value); 04388 } 04389 if (i->iaxvars) { 04390 struct ast_datastore *variablestore; 04391 struct ast_variable *var, *prev = NULL; 04392 AST_LIST_HEAD(, ast_var_t) *varlist; 04393 ast_debug(1, "Loading up the channel with IAXVARs\n"); 04394 varlist = ast_calloc(1, sizeof(*varlist)); 04395 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 04396 if (variablestore && varlist) { 04397 variablestore->data = varlist; 04398 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 04399 AST_LIST_HEAD_INIT(varlist); 04400 for (var = i->iaxvars; var; var = var->next) { 04401 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 04402 if (prev) 04403 ast_free(prev); 04404 prev = var; 04405 if (!newvar) { 04406 /* Don't abort list traversal, as this would leave i->iaxvars in an inconsistent state. */ 04407 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 04408 } else { 04409 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 04410 } 04411 } 04412 if (prev) 04413 ast_free(prev); 04414 i->iaxvars = NULL; 04415 ast_channel_datastore_add(i->owner, variablestore); 04416 } else { 04417 if (variablestore) { 04418 ast_datastore_free(variablestore); 04419 } 04420 if (varlist) { 04421 ast_free(varlist); 04422 } 04423 } 04424 } 04425 04426 if (state != AST_STATE_DOWN) { 04427 if (ast_pbx_start(tmp)) { 04428 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 04429 ast_hangup(tmp); 04430 i->owner = NULL; 04431 return NULL; 04432 } 04433 } 04434 04435 ast_module_ref(ast_module_info->self); 04436 return tmp; 04437 }
static int attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2547 of file chan_iax2.c.
References __attempt_transmit(), and schedule_action.
Referenced by __attempt_transmit(), and network_thread().
02548 { 02549 #ifdef SCHED_MULTITHREADED 02550 if (schedule_action(__attempt_transmit, data)) 02551 #endif 02552 __attempt_transmit(data); 02553 return 0; 02554 }
static int auth_fail | ( | int | callno, | |
int | failcode | |||
) | [static] |
Definition at line 7424 of file chan_iax2.c.
References auth_reject(), iax2_sched_replace(), and sched.
Referenced by socket_process().
07425 { 07426 /* Schedule sending the authentication failure in one second, to prevent 07427 guessing */ 07428 if (iaxs[callno]) { 07429 iaxs[callno]->authfail = failcode; 07430 if (delayreject) { 07431 iaxs[callno]->authid = iax2_sched_replace(iaxs[callno]->authid, 07432 sched, 1000, auth_reject, (void *)(long)callno); 07433 } else 07434 auth_reject((void *)(long)callno); 07435 } 07436 return 0; 07437 }
static int auth_reject | ( | const void * | data | ) | [static] |
Definition at line 7410 of file chan_iax2.c.
References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), and schedule_action.
Referenced by auth_fail().
07411 { 07412 int callno = (int)(long)(data); 07413 ast_mutex_lock(&iaxsl[callno]); 07414 if (iaxs[callno]) 07415 iaxs[callno]->authid = -1; 07416 ast_mutex_unlock(&iaxsl[callno]); 07417 #ifdef SCHED_MULTITHREADED 07418 if (schedule_action(__auth_reject, data)) 07419 #endif 07420 __auth_reject(data); 07421 return 0; 07422 }
static int authenticate | ( | const char * | challenge, | |
const char * | secret, | |||
const char * | keyn, | |||
int | authmethods, | |||
struct iax_ie_data * | ied, | |||
struct sockaddr_in * | sin, | |||
struct chan_iax2_pvt * | pvt | |||
) | [static] |
Definition at line 6568 of file chan_iax2.c.
References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_encryption_keys(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, iax_ie_append_str(), IAX_IE_MD5_RESULT, IAX_IE_PASSWORD, IAX_IE_RSA_RESULT, LOG_NOTICE, md5(), MD5Final(), MD5Init(), and MD5Update().
06569 { 06570 int res = -1; 06571 int x; 06572 if (!ast_strlen_zero(keyn)) { 06573 if (!(authmethods & IAX_AUTH_RSA)) { 06574 if (ast_strlen_zero(secret)) 06575 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)); 06576 } else if (ast_strlen_zero(challenge)) { 06577 ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr)); 06578 } else { 06579 char sig[256]; 06580 struct ast_key *key; 06581 key = ast_key_get(keyn, AST_KEY_PRIVATE); 06582 if (!key) { 06583 ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); 06584 } else { 06585 if (ast_sign(key, (char*)challenge, sig)) { 06586 ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); 06587 res = -1; 06588 } else { 06589 iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); 06590 res = 0; 06591 } 06592 } 06593 } 06594 } 06595 /* Fall back */ 06596 if (res && !ast_strlen_zero(secret)) { 06597 if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) { 06598 struct MD5Context md5; 06599 unsigned char digest[16]; 06600 char digres[128]; 06601 MD5Init(&md5); 06602 MD5Update(&md5, (unsigned char *)challenge, strlen(challenge)); 06603 MD5Update(&md5, (unsigned char *)secret, strlen(secret)); 06604 MD5Final(digest, &md5); 06605 /* If they support md5, authenticate with it. */ 06606 for (x=0;x<16;x++) 06607 sprintf(digres + (x << 1), "%2.2x", digest[x]); /* safe */ 06608 if (pvt) { 06609 build_encryption_keys(digest, pvt); 06610 } 06611 iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); 06612 res = 0; 06613 } else if (authmethods & IAX_AUTH_PLAINTEXT) { 06614 iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); 06615 res = 0; 06616 } else 06617 ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods); 06618 } 06619 return res; 06620 }
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 6626 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_calloc, ast_channel_datastore_add(), ast_datastore_alloc(), ast_datastore_free(), AST_FRAME_IAX, ast_free, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), authenticate(), iax_ies::authmethods, iax2_peer::authmethods, chan_iax2_pvt::callno, iax_ies::challenge, ast_datastore::data, DATASTORE_INHERIT_FOREVER, iax_ies::encmethods, ast_var_t::entries, iax2_variable_datastore_info, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, ast_datastore::inheritance, LOG_ERROR, iax2_peer::mask, merge_encryption(), iax2_peer::name, iax2_peer::outkey, peer_unref(), realtime_peer(), iax2_peer::secret, send_command(), iax2_peer::username, iax_ies::username, var, and iax_ies::vars.
Referenced by socket_process().
06627 { 06628 struct iax2_peer *peer = NULL; 06629 /* Start pessimistic */ 06630 int res = -1; 06631 int authmethods = 0; 06632 struct iax_ie_data ied; 06633 uint16_t callno = p->callno; 06634 06635 memset(&ied, 0, sizeof(ied)); 06636 06637 if (ies->username) 06638 ast_string_field_set(p, username, ies->username); 06639 if (ies->challenge) 06640 ast_string_field_set(p, challenge, ies->challenge); 06641 if (ies->authmethods) 06642 authmethods = ies->authmethods; 06643 if (authmethods & IAX_AUTH_MD5) 06644 merge_encryption(p, ies->encmethods); 06645 else 06646 p->encmethods = 0; 06647 06648 /* Check for override RSA authentication first */ 06649 if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) { 06650 /* Normal password authentication */ 06651 res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, p); 06652 } else { 06653 struct ao2_iterator i = ao2_iterator_init(peers, 0); 06654 while ((peer = ao2_iterator_next(&i))) { 06655 if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 06656 /* No peer specified at our end, or this is the peer */ 06657 && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) 06658 /* No username specified in peer rule, or this is the right username */ 06659 && (!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))) 06660 /* No specified host, or this is our host */ 06661 ) { 06662 res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, p); 06663 if (!res) { 06664 peer_unref(peer); 06665 break; 06666 } 06667 } 06668 peer_unref(peer); 06669 } 06670 if (!peer) { 06671 /* We checked our list and didn't find one. It's unlikely, but possible, 06672 that we're trying to authenticate *to* a realtime peer */ 06673 const char *peer_name = ast_strdupa(p->peer); 06674 ast_mutex_unlock(&iaxsl[callno]); 06675 if ((peer = realtime_peer(peer_name, NULL))) { 06676 ast_mutex_lock(&iaxsl[callno]); 06677 if (!(p = iaxs[callno])) { 06678 peer_unref(peer); 06679 return -1; 06680 } 06681 res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, p); 06682 peer_unref(peer); 06683 } 06684 if (!peer) { 06685 ast_mutex_lock(&iaxsl[callno]); 06686 if (!(p = iaxs[callno])) 06687 return -1; 06688 } 06689 } 06690 } 06691 if (ies->encmethods) 06692 ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); 06693 if (!res) { 06694 struct ast_datastore *variablestore; 06695 struct ast_variable *var, *prev = NULL; 06696 AST_LIST_HEAD(, ast_var_t) *varlist; 06697 varlist = ast_calloc(1, sizeof(*varlist)); 06698 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 06699 if (variablestore && varlist && p->owner) { 06700 variablestore->data = varlist; 06701 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 06702 AST_LIST_HEAD_INIT(varlist); 06703 for (var = ies->vars; var; var = var->next) { 06704 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 06705 if (prev) 06706 ast_free(prev); 06707 prev = var; 06708 if (!newvar) { 06709 /* Don't abort list traversal, as this would leave ies->vars in an inconsistent state. */ 06710 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 06711 } else { 06712 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 06713 } 06714 } 06715 if (prev) 06716 ast_free(prev); 06717 ies->vars = NULL; 06718 ast_channel_datastore_add(p->owner, variablestore); 06719 } else { 06720 if (p->owner) 06721 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 06722 if (variablestore) 06723 ast_datastore_free(variablestore); 06724 if (varlist) 06725 ast_free(varlist); 06726 } 06727 } 06728 06729 if (!res) 06730 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); 06731 return res; 06732 }
static int authenticate_request | ( | int | call_num | ) | [static] |
Definition at line 6279 of file chan_iax2.c.
References ao2_find, AST_CAUSE_CALL_REJECTED, AST_FRAME_IAX, ast_random(), ast_set_flag, ast_string_field_set, ast_test_flag, chan_iax2_pvt::authmethods, chan_iax2_pvt::challenge, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, OBJ_POINTER, send_command(), send_command_final(), user, user_unref(), and chan_iax2_pvt::username.
Referenced by socket_process().
06280 { 06281 struct iax_ie_data ied; 06282 int res = -1, authreq_restrict = 0; 06283 char challenge[10]; 06284 struct chan_iax2_pvt *p = iaxs[call_num]; 06285 06286 memset(&ied, 0, sizeof(ied)); 06287 06288 /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */ 06289 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 06290 struct iax2_user *user, tmp_user = { 06291 .name = p->username, 06292 }; 06293 06294 user = ao2_find(users, &tmp_user, OBJ_POINTER); 06295 if (user) { 06296 if (user->curauthreq == user->maxauthreq) 06297 authreq_restrict = 1; 06298 else 06299 user->curauthreq++; 06300 user = user_unref(user); 06301 } 06302 } 06303 06304 /* If the AUTHREQ limit test failed, send back an error */ 06305 if (authreq_restrict) { 06306 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached"); 06307 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED); 06308 send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); 06309 return 0; 06310 } 06311 06312 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 06313 if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) { 06314 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 06315 ast_string_field_set(p, challenge, challenge); 06316 /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */ 06317 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge); 06318 } 06319 if (p->encmethods) 06320 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods); 06321 06322 iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username); 06323 06324 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1); 06325 06326 if (p->encmethods) 06327 ast_set_flag(p, IAX_ENCRYPTED); 06328 06329 return res; 06330 }
static int authenticate_verify | ( | struct chan_iax2_pvt * | p, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6332 of file chan_iax2.c.
References ao2_find, ast_atomic_fetchadd_int(), ast_check_signature, ast_clear_flag, ast_copy_string(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, chan_iax2_pvt::authrej, chan_iax2_pvt::challenge, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, chan_iax2_pvt::inkeys, LOG_WARNING, md5(), iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), OBJ_POINTER, iax_ies::password, iax_ies::rsa_result, chan_iax2_pvt::secret, secret, chan_iax2_pvt::state, strsep(), user, user_unref(), and chan_iax2_pvt::username.
Referenced by socket_process().
06333 { 06334 char requeststr[256]; 06335 char md5secret[256] = ""; 06336 char secret[256] = ""; 06337 char rsasecret[256] = ""; 06338 int res = -1; 06339 int x; 06340 struct iax2_user *user, tmp_user = { 06341 .name = p->username, 06342 }; 06343 06344 if (p->authrej) { 06345 return res; 06346 } 06347 user = ao2_find(users, &tmp_user, OBJ_POINTER); 06348 if (user) { 06349 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 06350 ast_atomic_fetchadd_int(&user->curauthreq, -1); 06351 ast_clear_flag(p, IAX_MAXAUTHREQ); 06352 } 06353 ast_string_field_set(p, host, user->name); 06354 user = user_unref(user); 06355 } 06356 06357 if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) 06358 return res; 06359 if (ies->password) 06360 ast_copy_string(secret, ies->password, sizeof(secret)); 06361 if (ies->md5_result) 06362 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 06363 if (ies->rsa_result) 06364 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 06365 if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) { 06366 struct ast_key *key; 06367 char *keyn; 06368 char tmpkey[256]; 06369 char *stringp=NULL; 06370 ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey)); 06371 stringp=tmpkey; 06372 keyn = strsep(&stringp, ":"); 06373 while(keyn) { 06374 key = ast_key_get(keyn, AST_KEY_PUBLIC); 06375 if (key && !ast_check_signature(key, p->challenge, rsasecret)) { 06376 res = 0; 06377 break; 06378 } else if (!key) 06379 ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); 06380 keyn = strsep(&stringp, ":"); 06381 } 06382 } else if (p->authmethods & IAX_AUTH_MD5) { 06383 struct MD5Context md5; 06384 unsigned char digest[16]; 06385 char *tmppw, *stringp; 06386 06387 tmppw = ast_strdupa(p->secret); 06388 stringp = tmppw; 06389 while((tmppw = strsep(&stringp, ";"))) { 06390 MD5Init(&md5); 06391 MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge)); 06392 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 06393 MD5Final(digest, &md5); 06394 /* If they support md5, authenticate with it. */ 06395 for (x=0;x<16;x++) 06396 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 06397 if (!strcasecmp(requeststr, md5secret)) { 06398 res = 0; 06399 break; 06400 } 06401 } 06402 } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { 06403 if (!strcmp(secret, p->secret)) 06404 res = 0; 06405 } 06406 return res; 06407 }
static int auto_congest | ( | const void * | data | ) | [static] |
Definition at line 3588 of file chan_iax2.c.
References __auto_congest(), and schedule_action.
Referenced by iax2_call(), sip_call(), and sip_show_sched().
03589 { 03590 #ifdef SCHED_MULTITHREADED 03591 if (schedule_action(__auto_congest, data)) 03592 #endif 03593 __auto_congest(data); 03594 return 0; 03595 }
static int auto_hangup | ( | const void * | data | ) | [static] |
Definition at line 7454 of file chan_iax2.c.
References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), and schedule_action.
Referenced by iax2_dprequest(), and iax2_provision().
07455 { 07456 int callno = (int)(long)(data); 07457 ast_mutex_lock(&iaxsl[callno]); 07458 if (iaxs[callno]) { 07459 iaxs[callno]->autoid = -1; 07460 } 07461 ast_mutex_unlock(&iaxsl[callno]); 07462 #ifdef SCHED_MULTITHREADED 07463 if (schedule_action(__auto_hangup, data)) 07464 #endif 07465 __auto_hangup(data); 07466 return 0; 07467 }
static struct iax2_context* build_context | ( | const char * | context | ) | [static] |
Definition at line 10476 of file chan_iax2.c.
References ast_calloc, and ast_copy_string().
Referenced by build_user().
10477 { 10478 struct iax2_context *con; 10479 10480 if ((con = ast_calloc(1, sizeof(*con)))) 10481 ast_copy_string(con->context, context, sizeof(con->context)); 10482 10483 return con; 10484 }
static void build_ecx_key | ( | const unsigned char * | digest, | |
struct chan_iax2_pvt * | pvt | |||
) | [static] |
Definition at line 4776 of file chan_iax2.c.
References ast_aes_decrypt_key, ast_aes_encrypt_key, build_rand_pad(), chan_iax2_pvt::ecx, chan_iax2_pvt::mydcx, and chan_iax2_pvt::semirand.
Referenced by build_encryption_keys(), and iax2_key_rotate().
04777 { 04778 /* it is required to hold the corresponding decrypt key to our encrypt key 04779 * in the pvt struct because queued frames occasionally need to be decrypted and 04780 * re-encrypted when updated for a retransmission */ 04781 build_rand_pad(pvt->semirand, sizeof(pvt->semirand)); 04782 ast_aes_encrypt_key(digest, &pvt->ecx); 04783 ast_aes_decrypt_key(digest, &pvt->mydcx); 04784 }
static void build_encryption_keys | ( | const unsigned char * | digest, | |
struct chan_iax2_pvt * | pvt | |||
) | [static] |
Definition at line 4770 of file chan_iax2.c.
References ast_aes_decrypt_key, build_ecx_key(), and chan_iax2_pvt::dcx.
Referenced by authenticate(), and decrypt_frame().
04771 { 04772 build_ecx_key(digest, pvt); 04773 ast_aes_decrypt_key(digest, &pvt->dcx); 04774 }
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 10624 of file chan_iax2.c.
References ao2_alloc, ao2_find, ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), AST_SCHED_DEL, ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), cid_name, cid_num, context, iax2_peer::dbsecret, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, get_auth_methods(), get_encrypt_methods(), globalflags, iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, inet_aton(), iax2_peer::inkeys, ast_variable::lineno, LOG_WARNING, mailbox, mwi_event_cb(), ast_variable::name, iax2_peer::name, ast_variable::next, OBJ_POINTER, iax2_peer::outkey, peer_destructor(), peer_set_srcaddr(), peer_unref(), iax2_peer::peercontext, prefs, regexten, S_OR, sched, secret, strsep(), timer, unlink_peer(), ast_variable::value, and zonetag.
10625 { 10626 struct iax2_peer *peer = NULL; 10627 struct ast_ha *oldha = NULL; 10628 int maskfound = 0; 10629 int found = 0; 10630 int firstpass = 1; 10631 struct iax2_peer tmp_peer = { 10632 .name = name, 10633 }; 10634 10635 if (!temponly) { 10636 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 10637 if (peer && !ast_test_flag(peer, IAX_DELME)) 10638 firstpass = 0; 10639 } 10640 10641 if (peer) { 10642 found++; 10643 if (firstpass) { 10644 oldha = peer->ha; 10645 peer->ha = NULL; 10646 } 10647 unlink_peer(peer); 10648 } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) { 10649 peer->expire = -1; 10650 peer->pokeexpire = -1; 10651 peer->sockfd = defaultsockfd; 10652 if (ast_string_field_init(peer, 32)) 10653 peer = peer_unref(peer); 10654 } 10655 10656 if (peer) { 10657 if (firstpass) { 10658 ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 10659 peer->encmethods = iax2_encryption; 10660 peer->adsi = adsi; 10661 ast_string_field_set(peer,secret,""); 10662 if (!found) { 10663 ast_string_field_set(peer, name, name); 10664 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 10665 peer->expiry = min_reg_expire; 10666 } 10667 peer->prefs = prefs; 10668 peer->capability = iax2_capability; 10669 peer->smoothing = 0; 10670 peer->pokefreqok = DEFAULT_FREQ_OK; 10671 peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; 10672 ast_string_field_set(peer,context,""); 10673 ast_string_field_set(peer,peercontext,""); 10674 ast_clear_flag(peer, IAX_HASCALLERID); 10675 ast_string_field_set(peer, cid_name, ""); 10676 ast_string_field_set(peer, cid_num, ""); 10677 } 10678 10679 if (!v) { 10680 v = alt; 10681 alt = NULL; 10682 } 10683 while(v) { 10684 if (!strcasecmp(v->name, "secret")) { 10685 ast_string_field_set(peer, secret, v->value); 10686 } else if (!strcasecmp(v->name, "mailbox")) { 10687 ast_string_field_set(peer, mailbox, v->value); 10688 } else if (!strcasecmp(v->name, "hasvoicemail")) { 10689 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) { 10690 ast_string_field_set(peer, mailbox, name); 10691 } 10692 } else if (!strcasecmp(v->name, "mohinterpret")) { 10693 ast_string_field_set(peer, mohinterpret, v->value); 10694 } else if (!strcasecmp(v->name, "mohsuggest")) { 10695 ast_string_field_set(peer, mohsuggest, v->value); 10696 } else if (!strcasecmp(v->name, "dbsecret")) { 10697 ast_string_field_set(peer, dbsecret, v->value); 10698 } else if (!strcasecmp(v->name, "trunk")) { 10699 ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); 10700 if (ast_test_flag(peer, IAX_TRUNK) && !timer) { 10701 ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without a timing interface\n", peer->name); 10702 ast_clear_flag(peer, IAX_TRUNK); 10703 } 10704 } else if (!strcasecmp(v->name, "auth")) { 10705 peer->authmethods = get_auth_methods(v->value); 10706 } else if (!strcasecmp(v->name, "encryption")) { 10707 peer->encmethods |= get_encrypt_methods(v->value); 10708 } else if (!strcasecmp(v->name, "transfer")) { 10709 if (!strcasecmp(v->value, "mediaonly")) { 10710 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 10711 } else if (ast_true(v->value)) { 10712 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 10713 } else 10714 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 10715 } else if (!strcasecmp(v->name, "jitterbuffer")) { 10716 ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF); 10717 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 10718 ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF); 10719 } else if (!strcasecmp(v->name, "host")) { 10720 if (!strcasecmp(v->value, "dynamic")) { 10721 /* They'll register with us */ 10722 ast_set_flag(peer, IAX_DYNAMIC); 10723 if (!found) { 10724 /* Initialize stuff iff we're not found, otherwise 10725 we keep going with what we had */ 10726 memset(&peer->addr.sin_addr, 0, 4); 10727 if (peer->addr.sin_port) { 10728 /* If we've already got a port, make it the default rather than absolute */ 10729 peer->defaddr.sin_port = peer->addr.sin_port; 10730 peer->addr.sin_port = 0; 10731 } 10732 } 10733 } else { 10734 /* Non-dynamic. Make sure we become that way if we're not */ 10735 AST_SCHED_DEL(sched, peer->expire); 10736 ast_clear_flag(peer, IAX_DYNAMIC); 10737 if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL)) 10738 return peer_unref(peer); 10739 if (!peer->addr.sin_port) 10740 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 10741 } 10742 if (!maskfound) 10743 inet_aton("255.255.255.255", &peer->mask); 10744 } else if (!strcasecmp(v->name, "defaultip")) { 10745 if (ast_get_ip(&peer->defaddr, v->value)) 10746 return peer_unref(peer); 10747 } else if (!strcasecmp(v->name, "sourceaddress")) { 10748 peer_set_srcaddr(peer, v->value); 10749 } else if (!strcasecmp(v->name, "permit") || 10750 !strcasecmp(v->name, "deny")) { 10751 peer->ha = ast_append_ha(v->name, v->value, peer->ha, NULL); 10752 } else if (!strcasecmp(v->name, "mask")) { 10753 maskfound++; 10754 inet_aton(v->value, &peer->mask); 10755 } else if (!strcasecmp(v->name, "context")) { 10756 ast_string_field_set(peer, context, v->value); 10757 } else if (!strcasecmp(v->name, "regexten")) { 10758 ast_string_field_set(peer, regexten, v->value); 10759 } else if (!strcasecmp(v->name, "peercontext")) { 10760 ast_string_field_set(peer, peercontext, v->value); 10761 } else if (!strcasecmp(v->name, "port")) { 10762 if (ast_test_flag(peer, IAX_DYNAMIC)) 10763 peer->defaddr.sin_port = htons(atoi(v->value)); 10764 else 10765 peer->addr.sin_port = htons(atoi(v->value)); 10766 } else if (!strcasecmp(v->name, "username")) { 10767 ast_string_field_set(peer, username, v->value); 10768 } else if (!strcasecmp(v->name, "allow")) { 10769 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); 10770 } else if (!strcasecmp(v->name, "disallow")) { 10771 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); 10772 } else if (!strcasecmp(v->name, "callerid")) { 10773 if (!ast_strlen_zero(v->value)) { 10774 char name2[80]; 10775 char num2[80]; 10776 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 10777 ast_string_field_set(peer, cid_name, name2); 10778 ast_string_field_set(peer, cid_num, num2); 10779 } else { 10780 ast_string_field_set(peer, cid_name, ""); 10781 ast_string_field_set(peer, cid_num, ""); 10782 } 10783 ast_set_flag(peer, IAX_HASCALLERID); 10784 } else if (!strcasecmp(v->name, "fullname")) { 10785 ast_string_field_set(peer, cid_name, S_OR(v->value, "")); 10786 ast_set_flag(peer, IAX_HASCALLERID); 10787 } else if (!strcasecmp(v->name, "cid_number")) { 10788 ast_string_field_set(peer, cid_num, S_OR(v->value, "")); 10789 ast_set_flag(peer, IAX_HASCALLERID); 10790 } else if (!strcasecmp(v->name, "sendani")) { 10791 ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 10792 } else if (!strcasecmp(v->name, "inkeys")) { 10793 ast_string_field_set(peer, inkeys, v->value); 10794 } else if (!strcasecmp(v->name, "outkey")) { 10795 ast_string_field_set(peer, outkey, v->value); 10796 } else if (!strcasecmp(v->name, "qualify")) { 10797 if (!strcasecmp(v->value, "no")) { 10798 peer->maxms = 0; 10799 } else if (!strcasecmp(v->value, "yes")) { 10800 peer->maxms = DEFAULT_MAXMS; 10801 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 10802 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); 10803 peer->maxms = 0; 10804 } 10805 } else if (!strcasecmp(v->name, "qualifysmoothing")) { 10806 peer->smoothing = ast_true(v->value); 10807 } else if (!strcasecmp(v->name, "qualifyfreqok")) { 10808 if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) { 10809 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); 10810 } 10811 } else if (!strcasecmp(v->name, "qualifyfreqnotok")) { 10812 if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) { 10813 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); 10814 } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok); 10815 } else if (!strcasecmp(v->name, "timezone")) { 10816 ast_string_field_set(peer, zonetag, v->value); 10817 } else if (!strcasecmp(v->name, "adsi")) { 10818 peer->adsi = ast_true(v->value); 10819 }/* else if (strcasecmp(v->name,"type")) */ 10820 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 10821 v = v->next; 10822 if (!v) { 10823 v = alt; 10824 alt = NULL; 10825 } 10826 } 10827 if (!peer->authmethods) 10828 peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 10829 ast_clear_flag(peer, IAX_DELME); 10830 /* Make sure these are IPv4 addresses */ 10831 peer->addr.sin_family = AF_INET; 10832 } 10833 10834 if (oldha) 10835 ast_free_ha(oldha); 10836 10837 if (!ast_strlen_zero(peer->mailbox)) { 10838 char *mailbox, *context; 10839 context = mailbox = ast_strdupa(peer->mailbox); 10840 strsep(&context, "@"); 10841 if (ast_strlen_zero(context)) 10842 context = "default"; 10843 peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 10844 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 10845 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 10846 AST_EVENT_IE_END); 10847 } 10848 10849 return peer; 10850 }
static void build_rand_pad | ( | unsigned char * | buf, | |
ssize_t | len | |||
) | [static] |
Definition at line 4760 of file chan_iax2.c.
References ast_random().
Referenced by build_ecx_key(), and update_packet().
04761 { 04762 long tmp; 04763 for (tmp = ast_random(); len > 0; tmp = ast_random()) { 04764 memcpy(buf, (unsigned char *) &tmp, (len > sizeof(tmp)) ? sizeof(tmp) : len); 04765 buf += sizeof(tmp); 04766 len -= sizeof(tmp); 04767 } 04768 }
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 10866 of file chan_iax2.c.
References ao2_alloc, ao2_find, ao2_unlink, ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_clear_flag, ast_copy_flags, ast_free_ha(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_build, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_new(), build_context(), cid_name, cid_num, cleanup(), iax2_user::dbsecret, format, free_context(), get_auth_methods(), get_encrypt_methods(), globalflags, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_user::inkeys, ast_variable::lineno, LOG_WARNING, ast_variable::name, iax2_user::name, ast_variable::next, OBJ_POINTER, parkinglot, prefs, secret, timer, user, user_destructor(), user_unref(), and ast_variable::value.
10867 { 10868 struct iax2_user *user = NULL; 10869 struct iax2_context *con, *conl = NULL; 10870 struct ast_ha *oldha = NULL; 10871 struct iax2_context *oldcon = NULL; 10872 int format; 10873 int firstpass=1; 10874 int oldcurauthreq = 0; 10875 char *varname = NULL, *varval = NULL; 10876 struct ast_variable *tmpvar = NULL; 10877 struct iax2_user tmp_user = { 10878 .name = name, 10879 }; 10880 10881 if (!temponly) { 10882 user = ao2_find(users, &tmp_user, OBJ_POINTER); 10883 if (user && !ast_test_flag(user, IAX_DELME)) 10884 firstpass = 0; 10885 } 10886 10887 if (user) { 10888 if (firstpass) { 10889 oldcurauthreq = user->curauthreq; 10890 oldha = user->ha; 10891 oldcon = user->contexts; 10892 user->ha = NULL; 10893 user->contexts = NULL; 10894 } 10895 /* Already in the list, remove it and it will be added back (or FREE'd) */ 10896 ao2_unlink(users, user); 10897 } else { 10898 user = ao2_alloc(sizeof(*user), user_destructor); 10899 } 10900 10901 if (user) { 10902 if (firstpass) { 10903 ast_string_field_free_memory(user); 10904 memset(user, 0, sizeof(struct iax2_user)); 10905 if (ast_string_field_init(user, 32)) { 10906 user = user_unref(user); 10907 goto cleanup; 10908 } 10909 user->maxauthreq = maxauthreq; 10910 user->curauthreq = oldcurauthreq; 10911 user->prefs = prefs; 10912 user->capability = iax2_capability; 10913 user->encmethods = iax2_encryption; 10914 user->adsi = adsi; 10915 ast_string_field_set(user, name, name); 10916 ast_string_field_set(user, language, language); 10917 ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); 10918 ast_clear_flag(user, IAX_HASCALLERID); 10919 ast_string_field_set(user, cid_name, ""); 10920 ast_string_field_set(user, cid_num, ""); 10921 } 10922 if (!v) { 10923 v = alt; 10924 alt = NULL; 10925 } 10926 while(v) { 10927 if (!strcasecmp(v->name, "context")) { 10928 con = build_context(v->value); 10929 if (con) { 10930 if (conl) 10931 conl->next = con; 10932 else 10933 user->contexts = con; 10934 conl = con; 10935 } 10936 } else if (!strcasecmp(v->name, "permit") || 10937 !strcasecmp(v->name, "deny")) { 10938 user->ha = ast_append_ha(v->name, v->value, user->ha, NULL); 10939 } else if (!strcasecmp(v->name, "setvar")) { 10940 varname = ast_strdupa(v->value); 10941 if (varname && (varval = strchr(varname,'='))) { 10942 *varval = '\0'; 10943 varval++; 10944 if((tmpvar = ast_variable_new(varname, varval, ""))) { 10945 tmpvar->next = user->vars; 10946 user->vars = tmpvar; 10947 } 10948 } 10949 } else if (!strcasecmp(v->name, "allow")) { 10950 ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); 10951 } else if (!strcasecmp(v->name, "disallow")) { 10952 ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); 10953 } else if (!strcasecmp(v->name, "trunk")) { 10954 ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); 10955 if (ast_test_flag(user, IAX_TRUNK) && !timer) { 10956 ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without a timing interface\n", user->name); 10957 ast_clear_flag(user, IAX_TRUNK); 10958 } 10959 } else if (!strcasecmp(v->name, "auth")) { 10960 user->authmethods = get_auth_methods(v->value); 10961 } else if (!strcasecmp(v->name, "encryption")) { 10962 user->encmethods |= get_encrypt_methods(v->value); 10963 } else if (!strcasecmp(v->name, "transfer")) { 10964 if (!strcasecmp(v->value, "mediaonly")) { 10965 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 10966 } else if (ast_true(v->value)) { 10967 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 10968 } else 10969 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 10970 } else if (!strcasecmp(v->name, "codecpriority")) { 10971 if(!strcasecmp(v->value, "caller")) 10972 ast_set_flag(user, IAX_CODEC_USER_FIRST); 10973 else if(!strcasecmp(v->value, "disabled")) 10974 ast_set_flag(user, IAX_CODEC_NOPREFS); 10975 else if(!strcasecmp(v->value, "reqonly")) { 10976 ast_set_flag(user, IAX_CODEC_NOCAP); 10977 ast_set_flag(user, IAX_CODEC_NOPREFS); 10978 } 10979 } else if (!strcasecmp(v->name, "jitterbuffer")) { 10980 ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF); 10981 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 10982 ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF); 10983 } else if (!strcasecmp(v->name, "dbsecret")) { 10984 ast_string_field_set(user, dbsecret, v->value); 10985 } else if (!strcasecmp(v->name, "secret")) { 10986 if (!ast_strlen_zero(user->secret)) { 10987 char *old = ast_strdupa(user->secret); 10988 10989 ast_string_field_build(user, secret, "%s;%s", old, v->value); 10990 } else 10991 ast_string_field_set(user, secret, v->value); 10992 } else if (!strcasecmp(v->name, "callerid")) { 10993 if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) { 10994 char name2[80]; 10995 char num2[80]; 10996 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 10997 ast_string_field_set(user, cid_name, name2); 10998 ast_string_field_set(user, cid_num, num2); 10999 ast_set_flag(user, IAX_HASCALLERID); 11000 } else { 11001 ast_clear_flag(user, IAX_HASCALLERID); 11002 ast_string_field_set(user, cid_name, ""); 11003 ast_string_field_set(user, cid_num, ""); 11004 } 11005 } else if (!strcasecmp(v->name, "fullname")) { 11006 if (!ast_strlen_zero(v->value)) { 11007 ast_string_field_set(user, cid_name, v->value); 11008 ast_set_flag(user, IAX_HASCALLERID); 11009 } else { 11010 ast_string_field_set(user, cid_name, ""); 11011 if (ast_strlen_zero(user->cid_num)) 11012 ast_clear_flag(user, IAX_HASCALLERID); 11013 } 11014 } else if (!strcasecmp(v->name, "cid_number")) { 11015 if (!ast_strlen_zero(v->value)) { 11016 ast_string_field_set(user, cid_num, v->value); 11017 ast_set_flag(user, IAX_HASCALLERID); 11018 } else { 11019 ast_string_field_set(user, cid_num, ""); 11020 if (ast_strlen_zero(user->cid_name)) 11021 ast_clear_flag(user, IAX_HASCALLERID); 11022 } 11023 } else if (!strcasecmp(v->name, "accountcode")) { 11024 ast_string_field_set(user, accountcode, v->value); 11025 } else if (!strcasecmp(v->name, "mohinterpret")) { 11026 ast_string_field_set(user, mohinterpret, v->value); 11027 } else if (!strcasecmp(v->name, "mohsuggest")) { 11028 ast_string_field_set(user, mohsuggest, v->value); 11029 } else if (!strcasecmp(v->name, "parkinglot")) { 11030 ast_string_field_set(user, parkinglot, v->value); 11031 } else if (!strcasecmp(v->name, "language")) { 11032 ast_string_field_set(user, language, v->value); 11033 } else if (!strcasecmp(v->name, "amaflags")) { 11034 format = ast_cdr_amaflags2int(v->value); 11035 if (format < 0) { 11036 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 11037 } else { 11038 user->amaflags = format; 11039 } 11040 } else if (!strcasecmp(v->name, "inkeys")) { 11041 ast_string_field_set(user, inkeys, v->value); 11042 } else if (!strcasecmp(v->name, "maxauthreq")) { 11043 user->maxauthreq = atoi(v->value); 11044 if (user->maxauthreq < 0) 11045 user->maxauthreq = 0; 11046 } else if (!strcasecmp(v->name, "adsi")) { 11047 user->adsi = ast_true(v->value); 11048 }/* else if (strcasecmp(v->name,"type")) */ 11049 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 11050 v = v->next; 11051 if (!v) { 11052 v = alt; 11053 alt = NULL; 11054 } 11055 } 11056 if (!user->authmethods) { 11057 if (!ast_strlen_zero(user->secret)) { 11058 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 11059 if (!ast_strlen_zero(user->inkeys)) 11060 user->authmethods |= IAX_AUTH_RSA; 11061 } else if (!ast_strlen_zero(user->inkeys)) { 11062 user->authmethods = IAX_AUTH_RSA; 11063 } else { 11064 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 11065 } 11066 } 11067 ast_clear_flag(user, IAX_DELME); 11068 } 11069 cleanup: 11070 if (oldha) 11071 ast_free_ha(oldha); 11072 if (oldcon) 11073 free_context(oldcon); 11074 return user; 11075 }
static int cache_get_callno_locked | ( | const char * | data | ) | [static] |
Definition at line 11626 of file chan_iax2.c.
References ARRAY_LEN, ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), create_addr(), find_callno_locked(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, LOG_WARNING, NEW_FORCE, parse_dial_string(), secret, and send_command().
Referenced by find_cache().
11627 { 11628 struct sockaddr_in sin; 11629 int x; 11630 int callno; 11631 struct iax_ie_data ied; 11632 struct create_addr_info cai; 11633 struct parsed_dial_string pds; 11634 char *tmpstr; 11635 11636 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 11637 /* Look for an *exact match* call. Once a call is negotiated, it can only 11638 look up entries for a single context */ 11639 if (!ast_mutex_trylock(&iaxsl[x])) { 11640 if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) 11641 return x; 11642 ast_mutex_unlock(&iaxsl[x]); 11643 } 11644 } 11645 11646 /* No match found, we need to create a new one */ 11647 11648 memset(&cai, 0, sizeof(cai)); 11649 memset(&ied, 0, sizeof(ied)); 11650 memset(&pds, 0, sizeof(pds)); 11651 11652 tmpstr = ast_strdupa(data); 11653 parse_dial_string(tmpstr, &pds); 11654 11655 if (ast_strlen_zero(pds.peer)) { 11656 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data); 11657 return -1; 11658 } 11659 11660 /* Populate our address from the given */ 11661 if (create_addr(pds.peer, NULL, &sin, &cai)) 11662 return -1; 11663 11664 ast_debug(1, "peer: %s, username: %s, password: %s, context: %s\n", 11665 pds.peer, pds.username, pds.password, pds.context); 11666 11667 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 11668 if (callno < 1) { 11669 ast_log(LOG_WARNING, "Unable to create call\n"); 11670 return -1; 11671 } 11672 11673 ast_string_field_set(iaxs[callno], dproot, data); 11674 iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; 11675 11676 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 11677 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); 11678 /* the string format is slightly different from a standard dial string, 11679 because the context appears in the 'exten' position 11680 */ 11681 if (pds.exten) 11682 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); 11683 if (pds.username) 11684 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 11685 iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); 11686 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); 11687 /* Keep password handy */ 11688 if (pds.password) 11689 ast_string_field_set(iaxs[callno], secret, pds.password); 11690 if (pds.key) 11691 ast_string_field_set(iaxs[callno], outkey, pds.key); 11692 /* Start the call going */ 11693 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 11694 11695 return callno; 11696 }
static unsigned int calc_rxstamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | offset | |||
) | [static] |
Definition at line 4612 of file chan_iax2.c.
References ast_debug, ast_random(), ast_samp2tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), chan_iax2_pvt::callno, and chan_iax2_pvt::rxcore.
04613 { 04614 /* Returns where in "receive time" we are. That is, how many ms 04615 since we received (or would have received) the frame with timestamp 0 */ 04616 int ms; 04617 #ifdef IAXTESTS 04618 int jit; 04619 #endif /* IAXTESTS */ 04620 /* Setup rxcore if necessary */ 04621 if (ast_tvzero(p->rxcore)) { 04622 p->rxcore = ast_tvnow(); 04623 if (iaxdebug) 04624 ast_debug(1, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n", 04625 p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset); 04626 p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000)); 04627 #if 1 04628 if (iaxdebug) 04629 ast_debug(1, "calc_rxstamp: call=%d: works out as %d.%6.6d\n", 04630 p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec)); 04631 #endif 04632 } 04633 04634 ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore); 04635 #ifdef IAXTESTS 04636 if (test_jit) { 04637 if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) { 04638 jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0)); 04639 if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0))) 04640 jit = -jit; 04641 ms += jit; 04642 } 04643 } 04644 if (test_late) { 04645 ms += test_late; 04646 test_late = 0; 04647 } 04648 #endif /* IAXTESTS */ 04649 return ms; 04650 }
static unsigned int calc_timestamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | ts, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 4483 of file chan_iax2.c.
References ast_debug, AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_samp2tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), chan_iax2_pvt::callno, f, chan_iax2_pvt::lastsent, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, and chan_iax2_pvt::offset.
Referenced by iax2_send(), and socket_process().
04484 { 04485 int ms; 04486 int voice = 0; 04487 int genuine = 0; 04488 int adjust; 04489 struct timeval *delivery = NULL; 04490 04491 04492 /* What sort of frame do we have?: voice is self-explanatory 04493 "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK 04494 non-genuine frames are CONTROL frames [ringing etc], DTMF 04495 The "genuine" distinction is needed because genuine frames must get a clock-based timestamp, 04496 the others need a timestamp slaved to the voice frames so that they go in sequence 04497 */ 04498 if (f) { 04499 if (f->frametype == AST_FRAME_VOICE) { 04500 voice = 1; 04501 delivery = &f->delivery; 04502 } else if (f->frametype == AST_FRAME_IAX) { 04503 genuine = 1; 04504 } else if (f->frametype == AST_FRAME_CNG) { 04505 p->notsilenttx = 0; 04506 } 04507 } 04508 if (ast_tvzero(p->offset)) { 04509 p->offset = ast_tvnow(); 04510 /* Round to nearest 20ms for nice looking traces */ 04511 p->offset.tv_usec -= p->offset.tv_usec % 20000; 04512 } 04513 /* If the timestamp is specified, just send it as is */ 04514 if (ts) 04515 return ts; 04516 /* If we have a time that the frame arrived, always use it to make our timestamp */ 04517 if (delivery && !ast_tvzero(*delivery)) { 04518 ms = ast_tvdiff_ms(*delivery, p->offset); 04519 if (iaxdebug) 04520 ast_debug(3, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno); 04521 } else { 04522 ms = ast_tvdiff_ms(ast_tvnow(), p->offset); 04523 if (ms < 0) 04524 ms = 0; 04525 if (voice) { 04526 /* On a voice frame, use predicted values if appropriate */ 04527 if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) { 04528 /* Adjust our txcore, keeping voice and non-voice synchronized */ 04529 /* AN EXPLANATION: 04530 When we send voice, we usually send "calculated" timestamps worked out 04531 on the basis of the number of samples sent. When we send other frames, 04532 we usually send timestamps worked out from the real clock. 04533 The problem is that they can tend to drift out of step because the 04534 source channel's clock and our clock may not be exactly at the same rate. 04535 We fix this by continuously "tweaking" p->offset. p->offset is "time zero" 04536 for this call. Moving it adjusts timestamps for non-voice frames. 04537 We make the adjustment in the style of a moving average. Each time we 04538 adjust p->offset by 10% of the difference between our clock-derived 04539 timestamp and the predicted timestamp. That's why you see "10000" 04540 below even though IAX2 timestamps are in milliseconds. 04541 The use of a moving average avoids offset moving too radically. 04542 Generally, "adjust" roams back and forth around 0, with offset hardly 04543 changing at all. But if a consistent different starts to develop it 04544 will be eliminated over the course of 10 frames (200-300msecs) 04545 */ 04546 adjust = (ms - p->nextpred); 04547 if (adjust < 0) 04548 p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000)); 04549 else if (adjust > 0) 04550 p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000)); 04551 04552 if (!p->nextpred) { 04553 p->nextpred = ms; /*f->samples / 8;*/ 04554 if (p->nextpred <= p->lastsent) 04555 p->nextpred = p->lastsent + 3; 04556 } 04557 ms = p->nextpred; 04558 } else { 04559 /* in this case, just use the actual 04560 * time, since we're either way off 04561 * (shouldn't happen), or we're ending a 04562 * silent period -- and seed the next 04563 * predicted time. Also, round ms to the 04564 * next multiple of frame size (so our 04565 * silent periods are multiples of 04566 * frame size too) */ 04567 04568 if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW ) 04569 ast_debug(1, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n", 04570 abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW); 04571 04572 if (f->samples >= 8) /* check to make sure we dont core dump */ 04573 { 04574 int diff = ms % (f->samples / 8); 04575 if (diff) 04576 ms += f->samples/8 - diff; 04577 } 04578 04579 p->nextpred = ms; 04580 p->notsilenttx = 1; 04581 } 04582 } else if ( f->frametype == AST_FRAME_VIDEO ) { 04583 /* 04584 * IAX2 draft 03 says that timestamps MUST be in order. 04585 * It does not say anything about several frames having the same timestamp 04586 * When transporting video, we can have a frame that spans multiple iax packets 04587 * (so called slices), so it would make sense to use the same timestamp for all of 04588 * them 04589 * We do want to make sure that frames don't go backwards though 04590 */ 04591 if ( (unsigned int)ms < p->lastsent ) 04592 ms = p->lastsent; 04593 } else { 04594 /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless 04595 it's a genuine frame */ 04596 if (genuine) { 04597 /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */ 04598 if (ms <= p->lastsent) 04599 ms = p->lastsent + 3; 04600 } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) { 04601 /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */ 04602 ms = p->lastsent + 3; 04603 } 04604 } 04605 } 04606 p->lastsent = ms; 04607 if (voice) 04608 p->nextpred = p->nextpred + f->samples / 8; 04609 return ms; 04610 }
static unsigned int calc_txpeerstamp | ( | struct iax2_trunk_peer * | tpeer, | |
int | sampms, | |||
struct timeval * | now | |||
) | [static] |
Definition at line 4439 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvzero(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lasttxtime, MAX_TIMESTAMP_SKEW, iax2_trunk_peer::trunkact, and iax2_trunk_peer::txtrunktime.
Referenced by send_trunk().
04440 { 04441 unsigned long int mssincetx; /* unsigned to handle overflows */ 04442 long int ms, pred; 04443 04444 tpeer->trunkact = *now; 04445 mssincetx = ast_tvdiff_ms(*now, tpeer->lasttxtime); 04446 if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) { 04447 /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */ 04448 tpeer->txtrunktime = *now; 04449 tpeer->lastsent = 999999; 04450 } 04451 /* Update last transmit time now */ 04452 tpeer->lasttxtime = *now; 04453 04454 /* Calculate ms offset */ 04455 ms = ast_tvdiff_ms(*now, tpeer->txtrunktime); 04456 /* Predict from last value */ 04457 pred = tpeer->lastsent + sampms; 04458 if (abs(ms - pred) < MAX_TIMESTAMP_SKEW) 04459 ms = pred; 04460 04461 /* We never send the same timestamp twice, so fudge a little if we must */ 04462 if (ms == tpeer->lastsent) 04463 ms = tpeer->lastsent + 1; 04464 tpeer->lastsent = ms; 04465 return ms; 04466 }
static int check_access | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6015 of file chan_iax2.c.
References iax_ies::adsicpe, 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(), iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, iax_ies::calling_pres, iax_ies::calling_tns, iax_ies::calling_ton, iax_ies::capability, cid_name, cid_num, iax_ies::codec_prefs, context, DEFAULT_CONTEXT, iax_ies::dnid, exten, ast_variable::file, iax_ies::format, iax2_getpeertrunk(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax_ies::language, LOG_WARNING, ast_variable::name, ast_variable::next, parkinglot, prefs, iax_ies::rdnis, realtime_user(), secret, user, user_unref(), iax_ies::username, ast_variable::value, iax_ies::version, and version.
Referenced by socket_process().
06016 { 06017 /* Start pessimistic */ 06018 int res = -1; 06019 int version = 2; 06020 struct iax2_user *user = NULL, *best = NULL; 06021 int bestscore = 0; 06022 int gotcapability = 0; 06023 struct ast_variable *v = NULL, *tmpvar = NULL; 06024 struct ao2_iterator i; 06025 06026 if (!iaxs[callno]) 06027 return res; 06028 if (ies->called_number) 06029 ast_string_field_set(iaxs[callno], exten, ies->called_number); 06030 if (ies->calling_number) { 06031 ast_shrink_phone_number(ies->calling_number); 06032 ast_string_field_set(iaxs[callno], cid_num, ies->calling_number); 06033 } 06034 if (ies->calling_name) 06035 ast_string_field_set(iaxs[callno], cid_name, ies->calling_name); 06036 if (ies->calling_ani) 06037 ast_string_field_set(iaxs[callno], ani, ies->calling_ani); 06038 if (ies->dnid) 06039 ast_string_field_set(iaxs[callno], dnid, ies->dnid); 06040 if (ies->rdnis) 06041 ast_string_field_set(iaxs[callno], rdnis, ies->rdnis); 06042 if (ies->called_context) 06043 ast_string_field_set(iaxs[callno], context, ies->called_context); 06044 if (ies->language) 06045 ast_string_field_set(iaxs[callno], language, ies->language); 06046 if (ies->username) 06047 ast_string_field_set(iaxs[callno], username, ies->username); 06048 if (ies->calling_ton > -1) 06049 iaxs[callno]->calling_ton = ies->calling_ton; 06050 if (ies->calling_tns > -1) 06051 iaxs[callno]->calling_tns = ies->calling_tns; 06052 if (ies->calling_pres > -1) 06053 iaxs[callno]->calling_pres = ies->calling_pres; 06054 if (ies->format) 06055 iaxs[callno]->peerformat = ies->format; 06056 if (ies->adsicpe) 06057 iaxs[callno]->peeradsicpe = ies->adsicpe; 06058 if (ies->capability) { 06059 gotcapability = 1; 06060 iaxs[callno]->peercapability = ies->capability; 06061 } 06062 if (ies->version) 06063 version = ies->version; 06064 06065 /* Use provided preferences until told otherwise for actual preferences */ 06066 if(ies->codec_prefs) { 06067 ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); 06068 ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); 06069 } 06070 06071 if (!gotcapability) 06072 iaxs[callno]->peercapability = iaxs[callno]->peerformat; 06073 if (version > IAX_PROTO_VERSION) { 06074 ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 06075 ast_inet_ntoa(sin->sin_addr), version); 06076 return res; 06077 } 06078 /* Search the userlist for a compatible entry, and fill in the rest */ 06079 i = ao2_iterator_init(users, 0); 06080 while ((user = ao2_iterator_next(&i))) { 06081 if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ 06082 !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ 06083 && ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */ 06084 && (ast_strlen_zero(iaxs[callno]->context) || /* No context specified */ 06085 apply_context(user->contexts, iaxs[callno]->context))) { /* Context is permitted */ 06086 if (!ast_strlen_zero(iaxs[callno]->username)) { 06087 /* Exact match, stop right now. */ 06088 if (best) 06089 user_unref(best); 06090 best = user; 06091 break; 06092 } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) { 06093 /* No required authentication */ 06094 if (user->ha) { 06095 /* There was host authentication and we passed, bonus! */ 06096 if (bestscore < 4) { 06097 bestscore = 4; 06098 if (best) 06099 user_unref(best); 06100 best = user; 06101 continue; 06102 } 06103 } else { 06104 /* No host access, but no secret, either, not bad */ 06105 if (bestscore < 3) { 06106 bestscore = 3; 06107 if (best) 06108 user_unref(best); 06109 best = user; 06110 continue; 06111 } 06112 } 06113 } else { 06114 if (user->ha) { 06115 /* Authentication, but host access too, eh, it's something.. */ 06116 if (bestscore < 2) { 06117 bestscore = 2; 06118 if (best) 06119 user_unref(best); 06120 best = user; 06121 continue; 06122 } 06123 } else { 06124 /* Authentication and no host access... This is our baseline */ 06125 if (bestscore < 1) { 06126 bestscore = 1; 06127 if (best) 06128 user_unref(best); 06129 best = user; 06130 continue; 06131 } 06132 } 06133 } 06134 } 06135 user_unref(user); 06136 } 06137 user = best; 06138 if (!user && !ast_strlen_zero(iaxs[callno]->username)) { 06139 user = realtime_user(iaxs[callno]->username, sin); 06140 if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ 06141 !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ 06142 user = user_unref(user); 06143 } 06144 } 06145 if (user) { 06146 /* We found our match (use the first) */ 06147 /* copy vars */ 06148 for (v = user->vars ; v ; v = v->next) { 06149 if((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 06150 tmpvar->next = iaxs[callno]->vars; 06151 iaxs[callno]->vars = tmpvar; 06152 } 06153 } 06154 /* If a max AUTHREQ restriction is in place, activate it */ 06155 if (user->maxauthreq > 0) 06156 ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ); 06157 iaxs[callno]->prefs = user->prefs; 06158 ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST); 06159 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS); 06160 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP); 06161 iaxs[callno]->encmethods = user->encmethods; 06162 /* Store the requested username if not specified */ 06163 if (ast_strlen_zero(iaxs[callno]->username)) 06164 ast_string_field_set(iaxs[callno], username, user->name); 06165 /* Store whether this is a trunked call, too, of course, and move if appropriate */ 06166 ast_copy_flags(iaxs[callno], user, IAX_TRUNK); 06167 iaxs[callno]->capability = user->capability; 06168 /* And use the default context */ 06169 if (ast_strlen_zero(iaxs[callno]->context)) { 06170 if (user->contexts) 06171 ast_string_field_set(iaxs[callno], context, user->contexts->context); 06172 else 06173 ast_string_field_set(iaxs[callno], context, DEFAULT_CONTEXT); 06174 } 06175 /* And any input keys */ 06176 ast_string_field_set(iaxs[callno], inkeys, user->inkeys); 06177 /* And the permitted authentication methods */ 06178 iaxs[callno]->authmethods = user->authmethods; 06179 iaxs[callno]->adsi = user->adsi; 06180 /* If the user has callerid, override the remote caller id. */ 06181 if (ast_test_flag(user, IAX_HASCALLERID)) { 06182 iaxs[callno]->calling_tns = 0; 06183 iaxs[callno]->calling_ton = 0; 06184 ast_string_field_set(iaxs[callno], cid_num, user->cid_num); 06185 ast_string_field_set(iaxs[callno], cid_name, user->cid_name); 06186 ast_string_field_set(iaxs[callno], ani, user->cid_num); 06187 iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 06188 } else if (ast_strlen_zero(iaxs[callno]->cid_num) && ast_strlen_zero(iaxs[callno]->cid_name)) { 06189 iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE; 06190 } /* else user is allowed to set their own CID settings */ 06191 if (!ast_strlen_zero(user->accountcode)) 06192 ast_string_field_set(iaxs[callno], accountcode, user->accountcode); 06193 if (!ast_strlen_zero(user->mohinterpret)) 06194 ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret); 06195 if (!ast_strlen_zero(user->mohsuggest)) 06196 ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest); 06197 if (!ast_strlen_zero(user->parkinglot)) 06198 ast_string_field_set(iaxs[callno], parkinglot, user->parkinglot); 06199 if (user->amaflags) 06200 iaxs[callno]->amaflags = user->amaflags; 06201 if (!ast_strlen_zero(user->language)) 06202 ast_string_field_set(iaxs[callno], language, user->language); 06203 ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 06204 /* Keep this check last */ 06205 if (!ast_strlen_zero(user->dbsecret)) { 06206 char *family, *key=NULL; 06207 char buf[80]; 06208 family = ast_strdupa(user->dbsecret); 06209 key = strchr(family, '/'); 06210 if (key) { 06211 *key = '\0'; 06212 key++; 06213 } 06214 if (!key || ast_db_get(family, key, buf, sizeof(buf))) 06215 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); 06216 else 06217 ast_string_field_set(iaxs[callno], secret, buf); 06218 } else 06219 ast_string_field_set(iaxs[callno], secret, user->secret); 06220 res = 0; 06221 user = user_unref(user); 06222 } else { 06223 /* user was not found, but we should still fake an AUTHREQ. 06224 * Set authmethods to the last known authmethod used by the system 06225 * Set a fake secret, it's not looked at, just required to attempt authentication. 06226 * Set authrej so the AUTHREP is rejected without even looking at its contents */ 06227 iaxs[callno]->authmethods = last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT); 06228 ast_string_field_set(iaxs[callno], secret, "badsecret"); 06229 iaxs[callno]->authrej = 1; 06230 if (!ast_strlen_zero(iaxs[callno]->username)) { 06231 /* only send the AUTHREQ if a username was specified. */ 06232 res = 0; 06233 } 06234 } 06235 ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK); 06236 return res; 06237 }
static int check_provisioning | ( | struct sockaddr_in * | sin, | |
int | sockfd, | |||
char * | si, | |||
unsigned int | ver | |||
) | [static] |
Definition at line 7778 of file chan_iax2.c.
References ast_debug, iax2_provision(), and iax_provision_version().
Referenced by socket_process().
07779 { 07780 unsigned int ourver; 07781 char rsi[80]; 07782 snprintf(rsi, sizeof(rsi), "si-%s", si); 07783 if (iax_provision_version(&ourver, rsi, 1)) 07784 return 0; 07785 ast_debug(1, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver); 07786 if (ourver != ver) 07787 iax2_provision(sin, sockfd, NULL, rsi, 1); 07788 return 0; 07789 }
static int check_srcaddr | ( | struct sockaddr * | sa, | |
socklen_t | salen | |||
) | [static] |
Check if address can be used as packet source.
Definition at line 10502 of file chan_iax2.c.
References ast_debug, ast_log(), errno, and LOG_ERROR.
Referenced by peer_set_srcaddr().
10503 { 10504 int sd; 10505 int res; 10506 10507 sd = socket(AF_INET, SOCK_DGRAM, 0); 10508 if (sd < 0) { 10509 ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); 10510 return -1; 10511 } 10512 10513 res = bind(sd, sa, salen); 10514 if (res < 0) { 10515 ast_debug(1, "Can't bind: %s\n", strerror(errno)); 10516 close(sd); 10517 return 1; 10518 } 10519 10520 close(sd); 10521 return 0; 10522 }
static int complete_dpreply | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6782 of file chan_iax2.c.
References ARRAY_LEN, ast_copy_string(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_UNKNOWN, iax_ies::called_number, iax2_dpcache::callno, iax_ies::dpstatus, iax2_dpcache::expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, matchmore(), iax2_dpcache::orig, iax2_dpcache::peer_list, iax_ies::refresh, status, and iax2_dpcache::waiters.
Referenced by socket_process().
06783 { 06784 char exten[256] = ""; 06785 int status = CACHE_FLAG_UNKNOWN, expiry = iaxdefaultdpcache, x, matchmore = 0; 06786 struct iax2_dpcache *dp = NULL; 06787 06788 if (ies->called_number) 06789 ast_copy_string(exten, ies->called_number, sizeof(exten)); 06790 06791 if (ies->dpstatus & IAX_DPSTATUS_EXISTS) 06792 status = CACHE_FLAG_EXISTS; 06793 else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST) 06794 status = CACHE_FLAG_CANEXIST; 06795 else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT) 06796 status = CACHE_FLAG_NONEXISTENT; 06797 06798 if (ies->refresh) 06799 expiry = ies->refresh; 06800 if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE) 06801 matchmore = CACHE_FLAG_MATCHMORE; 06802 06803 AST_LIST_LOCK(&dpcache); 06804 AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, peer_list) { 06805 if (strcmp(dp->exten, exten)) 06806 continue; 06807 AST_LIST_REMOVE_CURRENT(peer_list); 06808 dp->callno = 0; 06809 dp->expiry.tv_sec = dp->orig.tv_sec + expiry; 06810 if (dp->flags & CACHE_FLAG_PENDING) { 06811 dp->flags &= ~CACHE_FLAG_PENDING; 06812 dp->flags |= status; 06813 dp->flags |= matchmore; 06814 } 06815 /* Wake up waiters */ 06816 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 06817 if (dp->waiters[x] > -1) { 06818 if (write(dp->waiters[x], "asdf", 4) < 0) { 06819 } 06820 } 06821 } 06822 } 06823 AST_LIST_TRAVERSE_SAFE_END; 06824 AST_LIST_UNLOCK(&dpcache); 06825 06826 return 0; 06827 }
static char * complete_iax2_peers | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 2798 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_strdup, iax2_peer::name, and peer_unref().
Referenced by handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), and handle_cli_iax2_show_peer().
02799 { 02800 int which = 0; 02801 struct iax2_peer *peer; 02802 char *res = NULL; 02803 int wordlen = strlen(word); 02804 struct ao2_iterator i; 02805 02806 i = ao2_iterator_init(peers, 0); 02807 while ((peer = ao2_iterator_next(&i))) { 02808 if (!strncasecmp(peer->name, word, wordlen) && ++which > state) { 02809 res = ast_strdup(peer->name); 02810 peer_unref(peer); 02811 break; 02812 } 02813 peer_unref(peer); 02814 } 02815 02816 return res; 02817 }
static char * complete_iax2_unregister | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 5459 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_strdup, iax2_peer::expire, iax2_peer::name, and peer_unref().
Referenced by handle_cli_iax2_unregister().
05460 { 05461 int which = 0; 05462 struct iax2_peer *p = NULL; 05463 char *res = NULL; 05464 int wordlen = strlen(word); 05465 05466 /* 0 - iax2; 1 - unregister; 2 - <peername> */ 05467 if (pos == 2) { 05468 struct ao2_iterator i = ao2_iterator_init(peers, 0); 05469 while ((p = ao2_iterator_next(&i))) { 05470 if (!strncasecmp(p->name, word, wordlen) && 05471 ++which > state && p->expire > 0) { 05472 res = ast_strdup(p->name); 05473 peer_unref(p); 05474 break; 05475 } 05476 peer_unref(p); 05477 } 05478 } 05479 05480 return res; 05481 }
static int complete_transfer | ( | int | callno, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6829 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, iax_ies::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, iax_frame::list, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, remove_by_peercallno(), remove_by_transfercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, store_by_peercallno(), chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, TRANSFER_NONE, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, chan_iax2_pvt::videoformat, and chan_iax2_pvt::voiceformat.
Referenced by socket_process().
06830 { 06831 int peercallno = 0; 06832 struct chan_iax2_pvt *pvt = iaxs[callno]; 06833 struct iax_frame *cur; 06834 jb_frame frame; 06835 06836 if (ies->callno) 06837 peercallno = ies->callno; 06838 06839 if (peercallno < 1) { 06840 ast_log(LOG_WARNING, "Invalid transfer request\n"); 06841 return -1; 06842 } 06843 remove_by_transfercallno(pvt); 06844 memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr)); 06845 memset(&pvt->transfer, 0, sizeof(pvt->transfer)); 06846 /* Reset sequence numbers */ 06847 pvt->oseqno = 0; 06848 pvt->rseqno = 0; 06849 pvt->iseqno = 0; 06850 pvt->aseqno = 0; 06851 06852 if (pvt->peercallno) { 06853 remove_by_peercallno(pvt); 06854 } 06855 pvt->peercallno = peercallno; 06856 /*this is where the transfering call swiches hash tables */ 06857 store_by_peercallno(pvt); 06858 pvt->transferring = TRANSFER_NONE; 06859 pvt->svoiceformat = -1; 06860 pvt->voiceformat = 0; 06861 pvt->svideoformat = -1; 06862 pvt->videoformat = 0; 06863 pvt->transfercallno = -1; 06864 memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); 06865 memset(&pvt->offset, 0, sizeof(pvt->offset)); 06866 /* reset jitterbuffer */ 06867 while(jb_getall(pvt->jb,&frame) == JB_OK) 06868 iax2_frame_free(frame.data); 06869 jb_reset(pvt->jb); 06870 pvt->lag = 0; 06871 pvt->last = 0; 06872 pvt->lastsent = 0; 06873 pvt->nextpred = 0; 06874 pvt->pingtime = DEFAULT_RETRY_TIME; 06875 AST_LIST_LOCK(&frame_queue); 06876 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 06877 /* We must cancel any packets that would have been transmitted 06878 because now we're talking to someone new. It's okay, they 06879 were transmitted to someone that didn't care anyway. */ 06880 if (callno == cur->callno) 06881 cur->retries = -1; 06882 } 06883 AST_LIST_UNLOCK(&frame_queue); 06884 return 0; 06885 }
static unsigned char compress_subclass | ( | int | subclass | ) | [static] |
Definition at line 1285 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().
01286 { 01287 int x; 01288 int power=-1; 01289 /* If it's 128 or smaller, just return it */ 01290 if (subclass < IAX_FLAG_SC_LOG) 01291 return subclass; 01292 /* Otherwise find its power */ 01293 for (x = 0; x < IAX_MAX_SHIFT; x++) { 01294 if (subclass & (1 << x)) { 01295 if (power > -1) { 01296 ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass); 01297 return 0; 01298 } else 01299 power = x; 01300 } 01301 } 01302 return power | IAX_FLAG_SC_LOG; 01303 }
static void construct_rr | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ie_data * | iep | |||
) | [static] |
Definition at line 7791 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().
07792 { 07793 jb_info stats; 07794 jb_getinfo(pvt->jb, &stats); 07795 07796 memset(iep, 0, sizeof(*iep)); 07797 07798 iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter); 07799 if(stats.frames_in == 0) stats.frames_in = 1; 07800 iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff))); 07801 iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in); 07802 iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min); 07803 iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped); 07804 iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo); 07805 }
static int create_addr | ( | const char * | peername, | |
struct ast_channel * | c, | |||
struct sockaddr_in * | sin, | |||
struct create_addr_info * | cai | |||
) | [static] |
Definition at line 3486 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_codec_pref_prepend(), ast_copy_flags, ast_copy_string(), ast_db_get(), ast_get_ip_or_srv(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, iax2_peer::context, create_addr_info::context, iax2_peer::dbsecret, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_DEBUG, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, iax2_peer::mohinterpret, create_addr_info::mohinterpret, iax2_peer::mohsuggest, create_addr_info::mohsuggest, ast_channel::nativeformats, iax2_peer::outkey, create_addr_info::outkey, peer_unref(), iax2_peer::peercontext, create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, iax2_peer::secret, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, iax2_peer::username, create_addr_info::username, and iax2_peer::zonetag.
03487 { 03488 struct iax2_peer *peer; 03489 int res = -1; 03490 struct ast_codec_pref ourprefs; 03491 03492 ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); 03493 cai->sockfd = defaultsockfd; 03494 cai->maxtime = 0; 03495 sin->sin_family = AF_INET; 03496 03497 if (!(peer = find_peer(peername, 1))) { 03498 cai->found = 0; 03499 if (ast_get_ip_or_srv(sin, peername, srvlookup ? "_iax._udp" : NULL)) { 03500 ast_log(LOG_WARNING, "No such host: %s\n", peername); 03501 return -1; 03502 } 03503 sin->sin_port = htons(IAX_DEFAULT_PORTNO); 03504 /* use global iax prefs for unknown peer/user */ 03505 /* But move the calling channel's native codec to the top of the preference list */ 03506 memcpy(&ourprefs, &prefs, sizeof(ourprefs)); 03507 if (c) 03508 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03509 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03510 return 0; 03511 } 03512 03513 cai->found = 1; 03514 03515 /* if the peer has no address (current or default), return failure */ 03516 if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) 03517 goto return_unref; 03518 03519 /* if the peer is being monitored and is currently unreachable, return failure */ 03520 if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) 03521 goto return_unref; 03522 03523 ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 03524 cai->maxtime = peer->maxms; 03525 cai->capability = peer->capability; 03526 cai->encmethods = peer->encmethods; 03527 cai->sockfd = peer->sockfd; 03528 cai->adsi = peer->adsi; 03529 memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); 03530 /* Move the calling channel's native codec to the top of the preference list */ 03531 if (c) { 03532 ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats); 03533 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03534 } 03535 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03536 ast_copy_string(cai->context, peer->context, sizeof(cai->context)); 03537 ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); 03538 ast_copy_string(cai->username, peer->username, sizeof(cai->username)); 03539 ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); 03540 ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); 03541 ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret)); 03542 ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest)); 03543 if (ast_strlen_zero(peer->dbsecret)) { 03544 ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); 03545 } else { 03546 char *family; 03547 char *key = NULL; 03548 03549 family = ast_strdupa(peer->dbsecret); 03550 key = strchr(family, '/'); 03551 if (key) 03552 *key++ = '\0'; 03553 if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { 03554 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); 03555 goto return_unref; 03556 } 03557 } 03558 03559 if (peer->addr.sin_addr.s_addr) { 03560 sin->sin_addr = peer->addr.sin_addr; 03561 sin->sin_port = peer->addr.sin_port; 03562 } else { 03563 sin->sin_addr = peer->defaddr.sin_addr; 03564 sin->sin_port = peer->defaddr.sin_port; 03565 } 03566 03567 res = 0; 03568 03569 return_unref: 03570 peer_unref(peer); 03571 03572 return res; 03573 }
static int decode_frame | ( | ast_aes_decrypt_key * | dcx, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4834 of file chan_iax2.c.
References ast_debug, AST_FRAME_VIDEO, ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, f, IAX_FLAG_FULL, memcpy_decrypt(), ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::type, and uncompress_subclass().
Referenced by decrypt_frame(), and update_packet().
04835 { 04836 int padding; 04837 unsigned char *workspace; 04838 04839 workspace = alloca(*datalen); 04840 memset(f, 0, sizeof(*f)); 04841 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04842 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04843 if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr)) 04844 return -1; 04845 /* Decrypt */ 04846 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx); 04847 04848 padding = 16 + (workspace[15] & 0x0f); 04849 if (iaxdebug) 04850 ast_debug(1, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]); 04851 if (*datalen < padding + sizeof(struct ast_iax2_full_hdr)) 04852 return -1; 04853 04854 *datalen -= padding; 04855 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04856 f->frametype = fh->type; 04857 if (f->frametype == AST_FRAME_VIDEO) { 04858 f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 04859 } else { 04860 f->subclass = uncompress_subclass(fh->csub); 04861 } 04862 } else { 04863 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04864 if (iaxdebug) 04865 ast_debug(1, "Decoding mini with length %d\n", *datalen); 04866 if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr)) 04867 return -1; 04868 /* Decrypt */ 04869 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx); 04870 padding = 16 + (workspace[15] & 0x0f); 04871 if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr)) 04872 return -1; 04873 *datalen -= padding; 04874 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04875 } 04876 return 0; 04877 }
static int decrypt_frame | ( | int | callno, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4920 of file chan_iax2.c.
References ast_set_flag, ast_strdupa, ast_test_flag, build_encryption_keys(), decode_frame(), f, IAX_KEYPOPULATED, md5(), MD5Final(), MD5Init(), MD5Update(), secret, and strsep().
Referenced by socket_process().
04921 { 04922 int res=-1; 04923 if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) { 04924 /* Search for possible keys, given secrets */ 04925 struct MD5Context md5; 04926 unsigned char digest[16]; 04927 char *tmppw, *stringp; 04928 04929 tmppw = ast_strdupa(iaxs[callno]->secret); 04930 stringp = tmppw; 04931 while ((tmppw = strsep(&stringp, ";"))) { 04932 MD5Init(&md5); 04933 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 04934 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 04935 MD5Final(digest, &md5); 04936 build_encryption_keys(digest, iaxs[callno]); 04937 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04938 if (!res) { 04939 ast_set_flag(iaxs[callno], IAX_KEYPOPULATED); 04940 break; 04941 } 04942 } 04943 } else 04944 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04945 return res; 04946 }
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 7938 of file chan_iax2.c.
References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), iax2_pkt_buf::buf, iax2_thread::buf, iax2_thread::buf_len, iax2_thread::full_frames, iax2_thread::lock, and ast_iax2_full_hdr::oseqno.
Referenced by socket_read().
07939 { 07940 struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf; 07941 struct ast_iax2_full_hdr *fh, *cur_fh; 07942 07943 if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len))) 07944 return; 07945 07946 pkt_buf->len = from_here->buf_len; 07947 memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len); 07948 07949 fh = (struct ast_iax2_full_hdr *) pkt_buf->buf; 07950 ast_mutex_lock(&to_here->lock); 07951 AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) { 07952 cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf; 07953 if (fh->oseqno < cur_fh->oseqno) { 07954 AST_LIST_INSERT_BEFORE_CURRENT(pkt_buf, entry); 07955 break; 07956 } 07957 } 07958 AST_LIST_TRAVERSE_SAFE_END 07959 07960 if (!cur_pkt_buf) 07961 AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry); 07962 07963 ast_mutex_unlock(&to_here->lock); 07964 }
static void delete_users | ( | void | ) | [static] |
Definition at line 11095 of file chan_iax2.c.
References ao2_callback, ast_dnsmgr_release(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::entry, iax2_registry::expire, iax2_destroy(), peer_delme_cb(), sched, and user_delme_cb().
11096 { 11097 struct iax2_registry *reg; 11098 11099 ao2_callback(users, 0, user_delme_cb, NULL); 11100 11101 AST_LIST_LOCK(®istrations); 11102 while ((reg = AST_LIST_REMOVE_HEAD(®istrations, entry))) { 11103 AST_SCHED_DEL(sched, reg->expire); 11104 if (reg->callno) { 11105 int callno = reg->callno; 11106 ast_mutex_lock(&iaxsl[callno]); 11107 if (iaxs[callno]) { 11108 iaxs[callno]->reg = NULL; 11109 iax2_destroy(callno); 11110 } 11111 ast_mutex_unlock(&iaxsl[callno]); 11112 } 11113 if (reg->dnsmgr) 11114 ast_dnsmgr_release(reg->dnsmgr); 11115 ast_free(reg); 11116 } 11117 AST_LIST_UNLOCK(®istrations); 11118 11119 ao2_callback(peers, 0, peer_delme_cb, NULL); 11120 }
static void destroy_firmware | ( | struct iax_firmware * | cur | ) | [static] |
Definition at line 2003 of file chan_iax2.c.
References ast_free, ast_iax2_firmware_header::datalen, iax_firmware::fd, and iax_firmware::fwh.
Referenced by reload_firmware().
02004 { 02005 /* Close firmware */ 02006 if (cur->fwh) { 02007 munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh))); 02008 } 02009 close(cur->fd); 02010 ast_free(cur); 02011 }
static void dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid, | |||
int | skiplock | |||
) | [static] |
Definition at line 7639 of file chan_iax2.c.
References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_IAX, ast_ignore_pattern(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), IAX_COMMAND_DPREP, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_NUMBER, IAX_IE_DPSTATUS, IAX_IE_REFRESH, and send_command().
Referenced by dp_lookup_thread(), and socket_process().
07640 { 07641 unsigned short dpstatus = 0; 07642 struct iax_ie_data ied1; 07643 int mm; 07644 07645 memset(&ied1, 0, sizeof(ied1)); 07646 mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); 07647 /* Must be started */ 07648 if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) { 07649 dpstatus = IAX_DPSTATUS_EXISTS; 07650 } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { 07651 dpstatus = IAX_DPSTATUS_CANEXIST; 07652 } else { 07653 dpstatus = IAX_DPSTATUS_NONEXISTENT; 07654 } 07655 if (ast_ignore_pattern(context, callednum)) 07656 dpstatus |= IAX_DPSTATUS_IGNOREPAT; 07657 if (mm) 07658 dpstatus |= IAX_DPSTATUS_MATCHMORE; 07659 if (!skiplock) 07660 ast_mutex_lock(&iaxsl[callno]); 07661 if (iaxs[callno]) { 07662 iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); 07663 iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); 07664 iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); 07665 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); 07666 } 07667 if (!skiplock) 07668 ast_mutex_unlock(&iaxsl[callno]); 07669 }
static void* dp_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 7671 of file chan_iax2.c.
References ast_free, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, and dp_lookup().
Referenced by spawn_dp_lookup().
07672 { 07673 /* Look up for dpreq */ 07674 struct dpreq_data *dpr = data; 07675 dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0); 07676 if (dpr->callerid) 07677 ast_free(dpr->callerid); 07678 ast_free(dpr); 07679 return NULL; 07680 }
static int encrypt_frame | ( | ast_aes_encrypt_key * | ecx, | |
struct ast_iax2_full_hdr * | fh, | |||
unsigned char * | poo, | |||
int * | datalen | |||
) | [static] |
Definition at line 4879 of file chan_iax2.c.
References ast_debug, ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, memcpy_encrypt(), ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.
Referenced by iax2_send(), and update_packet().
04880 { 04881 int padding; 04882 unsigned char *workspace; 04883 workspace = alloca(*datalen + 32); 04884 if (!workspace) 04885 return -1; 04886 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04887 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04888 if (iaxdebug) 04889 ast_debug(1, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen); 04890 padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16); 04891 padding = 16 + (padding & 0xf); 04892 memcpy(workspace, poo, padding); 04893 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04894 workspace[15] &= 0xf0; 04895 workspace[15] |= (padding & 0xf); 04896 if (iaxdebug) 04897 ast_debug(1, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]); 04898 *datalen += padding; 04899 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx); 04900 if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr)) 04901 memcpy(poo, workspace + *datalen - 32, 32); 04902 } else { 04903 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04904 if (iaxdebug) 04905 ast_debug(1, "Encoding mini frame with length %d\n", *datalen); 04906 padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16); 04907 padding = 16 + (padding & 0xf); 04908 memcpy(workspace, poo, padding); 04909 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04910 workspace[15] &= 0xf0; 04911 workspace[15] |= (padding & 0x0f); 04912 *datalen += padding; 04913 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx); 04914 if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr)) 04915 memcpy(poo, workspace + *datalen - 32, 32); 04916 } 04917 return 0; 04918 }
static int expire_registry | ( | const void * | data | ) | [static] |
Definition at line 7081 of file chan_iax2.c.
References __expire_registry(), and schedule_action.
Referenced by handle_cli_iax2_prune_realtime(), handle_cli_iax2_unregister(), reg_source_db(), and update_registry().
07082 { 07083 #ifdef SCHED_MULTITHREADED 07084 if (schedule_action(__expire_registry, data)) 07085 #endif 07086 __expire_registry(data); 07087 return 0; 07088 }
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 11698 of file chan_iax2.c.
References ARRAY_LEN, ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_copy_string(), ast_free, ast_frfree, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, chan, errno, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, iax2_dprequest(), IAX_STATE_STARTED, LOG_WARNING, iax2_dpcache::orig, iax2_dpcache::peercontext, and iax2_dpcache::waiters.
Referenced by iax2_canmatch(), iax2_exec(), iax2_exists(), and iax2_matchmore().
11699 { 11700 struct iax2_dpcache *dp = NULL; 11701 struct timeval now = ast_tvnow(); 11702 int x, com[2], timeout, old = 0, outfd, doabort, callno; 11703 struct ast_channel *c = NULL; 11704 struct ast_frame *f = NULL; 11705 11706 AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) { 11707 if (ast_tvcmp(now, dp->expiry) > 0) { 11708 AST_LIST_REMOVE_CURRENT(cache_list); 11709 if ((dp->flags & CACHE_FLAG_PENDING) || dp->callno) 11710 ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = blah, callno = %d)\n", dp->flags, dp->callno); 11711 else 11712 ast_free(dp); 11713 continue; 11714 } 11715 if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 11716 break; 11717 } 11718 AST_LIST_TRAVERSE_SAFE_END; 11719 11720 if (!dp) { 11721 /* No matching entry. Create a new one. */ 11722 /* First, can we make a callno? */ 11723 if ((callno = cache_get_callno_locked(data)) < 0) { 11724 ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data); 11725 return NULL; 11726 } 11727 if (!(dp = ast_calloc(1, sizeof(*dp)))) { 11728 ast_mutex_unlock(&iaxsl[callno]); 11729 return NULL; 11730 } 11731 ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext)); 11732 ast_copy_string(dp->exten, exten, sizeof(dp->exten)); 11733 dp->expiry = ast_tvnow(); 11734 dp->orig = dp->expiry; 11735 /* Expires in 30 mins by default */ 11736 dp->expiry.tv_sec += iaxdefaultdpcache; 11737 dp->flags = CACHE_FLAG_PENDING; 11738 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) 11739 dp->waiters[x] = -1; 11740 /* Insert into the lists */ 11741 AST_LIST_INSERT_TAIL(&dpcache, dp, cache_list); 11742 AST_LIST_INSERT_TAIL(&iaxs[callno]->dpentries, dp, peer_list); 11743 /* Send the request if we're already up */ 11744 if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 11745 iax2_dprequest(dp, callno); 11746 ast_mutex_unlock(&iaxsl[callno]); 11747 } 11748 11749 /* By here we must have a dp */ 11750 if (dp->flags & CACHE_FLAG_PENDING) { 11751 /* Okay, here it starts to get nasty. We need a pipe now to wait 11752 for a reply to come back so long as it's pending */ 11753 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 11754 /* Find an empty slot */ 11755 if (dp->waiters[x] < 0) 11756 break; 11757 } 11758 if (x >= ARRAY_LEN(dp->waiters)) { 11759 ast_log(LOG_WARNING, "No more waiter positions available\n"); 11760 return NULL; 11761 } 11762 if (pipe(com)) { 11763 ast_log(LOG_WARNING, "Unable to create pipe for comm\n"); 11764 return NULL; 11765 } 11766 dp->waiters[x] = com[1]; 11767 /* Okay, now we wait */ 11768 timeout = iaxdefaulttimeout * 1000; 11769 /* Temporarily unlock */ 11770 AST_LIST_UNLOCK(&dpcache); 11771 /* Defer any dtmf */ 11772 if (chan) 11773 old = ast_channel_defer_dtmf(chan); 11774 doabort = 0; 11775 while(timeout) { 11776 c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout); 11777 if (outfd > -1) 11778 break; 11779 if (!c) 11780 continue; 11781 if (!(f = ast_read(c))) { 11782 doabort = 1; 11783 break; 11784 } 11785 ast_frfree(f); 11786 } 11787 if (!timeout) { 11788 ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten); 11789 } 11790 AST_LIST_LOCK(&dpcache); 11791 dp->waiters[x] = -1; 11792 close(com[1]); 11793 close(com[0]); 11794 if (doabort) { 11795 /* Don't interpret anything, just abort. Not sure what th epoint 11796 of undeferring dtmf on a hung up channel is but hey whatever */ 11797 if (!old && chan) 11798 ast_channel_undefer_dtmf(chan); 11799 return NULL; 11800 } 11801 if (!(dp->flags & CACHE_FLAG_TIMEOUT)) { 11802 /* Now to do non-independent analysis the results of our wait */ 11803 if (dp->flags & CACHE_FLAG_PENDING) { 11804 /* Still pending... It's a timeout. Wake everybody up. Consider it no longer 11805 pending. Don't let it take as long to timeout. */ 11806 dp->flags &= ~CACHE_FLAG_PENDING; 11807 dp->flags |= CACHE_FLAG_TIMEOUT; 11808 /* Expire after only 60 seconds now. This is designed to help reduce backlog in heavily loaded 11809 systems without leaving it unavailable once the server comes back online */ 11810 dp->expiry.tv_sec = dp->orig.tv_sec + 60; 11811 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 11812 if (dp->waiters[x] > -1) { 11813 if (write(dp->waiters[x], "asdf", 4) < 0) { 11814 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 11815 } 11816 } 11817 } 11818 } 11819 } 11820 /* Our caller will obtain the rest */ 11821 if (!old && chan) 11822 ast_channel_undefer_dtmf(chan); 11823 } 11824 return dp; 11825 }
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 1903 of file chan_iax2.c.
References __find_callno().
Referenced by iax2_poke_peer(), and socket_process().
01903 { 01904 01905 return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame); 01906 }
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 1908 of file chan_iax2.c.
References __find_callno().
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_provision(), iax2_request(), and socket_process_meta().
01908 { 01909 01910 return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame); 01911 }
static struct iax2_thread* find_idle_thread | ( | void | ) | [static] |
Definition at line 1097 of file chan_iax2.c.
References ast_atomic_fetchadd_int(), ast_calloc, ast_cond_destroy(), ast_cond_init(), ast_cond_wait(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached_background, iax2_process_thread(), IAX_THREAD_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxdynamicthreadnum, iaxmaxthreadcount, iax2_trunk_peer::list, and thread.
Referenced by __schedule_action(), and socket_read().
01098 { 01099 struct iax2_thread *thread = NULL; 01100 01101 /* Pop the head of the idle list off */ 01102 AST_LIST_LOCK(&idle_list); 01103 thread = AST_LIST_REMOVE_HEAD(&idle_list, list); 01104 AST_LIST_UNLOCK(&idle_list); 01105 01106 /* If we popped a thread off the idle list, just return it */ 01107 if (thread) { 01108 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01109 return thread; 01110 } 01111 01112 /* Pop the head of the dynamic list off */ 01113 AST_LIST_LOCK(&dynamic_list); 01114 thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list); 01115 AST_LIST_UNLOCK(&dynamic_list); 01116 01117 /* If we popped a thread off the dynamic list, just return it */ 01118 if (thread) { 01119 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01120 return thread; 01121 } 01122 01123 /* If we can't create a new dynamic thread for any reason, return no thread at all */ 01124 if (iaxdynamicthreadcount >= iaxmaxthreadcount || !(thread = ast_calloc(1, sizeof(*thread)))) 01125 return NULL; 01126 01127 /* Set default values */ 01128 ast_atomic_fetchadd_int(&iaxdynamicthreadcount, 1); 01129 thread->threadnum = ast_atomic_fetchadd_int(&iaxdynamicthreadnum, 1); 01130 thread->type = IAX_THREAD_TYPE_DYNAMIC; 01131 01132 /* Initialize lock and condition */ 01133 ast_mutex_init(&thread->lock); 01134 ast_cond_init(&thread->cond, NULL); 01135 ast_mutex_init(&thread->init_lock); 01136 ast_cond_init(&thread->init_cond, NULL); 01137 ast_mutex_lock(&thread->init_lock); 01138 01139 /* Create thread and send it on it's way */ 01140 if (ast_pthread_create_detached_background(&thread->threadid, NULL, iax2_process_thread, thread)) { 01141 ast_cond_destroy(&thread->cond); 01142 ast_mutex_destroy(&thread->lock); 01143 ast_free(thread); 01144 return NULL; 01145 } 01146 01147 /* this thread is not processing a full frame (since it is idle), 01148 so ensure that the field for the full frame call number is empty */ 01149 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01150 01151 /* Wait for the thread to be ready before returning it to the caller */ 01152 ast_cond_wait(&thread->init_cond, &thread->init_lock); 01153 01154 /* Done with init_lock */ 01155 ast_mutex_unlock(&thread->init_lock); 01156 01157 return thread; 01158 }
static struct iax2_peer* find_peer | ( | const char * | name, | |
int | realtime | |||
) | [static] |
Definition at line 1363 of file chan_iax2.c.
References ao2_find, iax2_peer::name, OBJ_POINTER, and realtime_peer().
01364 { 01365 struct iax2_peer *peer = NULL; 01366 struct iax2_peer tmp_peer = { 01367 .name = name, 01368 }; 01369 01370 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 01371 01372 /* Now go for realtime if applicable */ 01373 if(!peer && realtime) 01374 peer = realtime_peer(name, NULL); 01375 01376 return peer; 01377 }
static struct iax2_trunk_peer* find_tpeer | ( | struct sockaddr_in * | sin, | |
int | fd | |||
) | [static] |
Definition at line 4652 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_calloc, ast_debug, ast_inet_ntoa(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_init(), ast_mutex_lock(), ast_tvnow(), inaddrcmp(), iax2_trunk_peer::list, and iax2_trunk_peer::lock.
Referenced by iax2_trunk_queue(), and socket_process_meta().
04653 { 04654 struct iax2_trunk_peer *tpeer = NULL; 04655 04656 /* Finds and locks trunk peer */ 04657 AST_LIST_LOCK(&tpeers); 04658 04659 AST_LIST_TRAVERSE(&tpeers, tpeer, list) { 04660 if (!inaddrcmp(&tpeer->addr, sin)) { 04661 ast_mutex_lock(&tpeer->lock); 04662 break; 04663 } 04664 } 04665 04666 if (!tpeer) { 04667 if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) { 04668 ast_mutex_init(&tpeer->lock); 04669 tpeer->lastsent = 9999; 04670 memcpy(&tpeer->addr, sin, sizeof(tpeer->addr)); 04671 tpeer->trunkact = ast_tvnow(); 04672 ast_mutex_lock(&tpeer->lock); 04673 tpeer->sockfd = fd; 04674 #ifdef SO_NO_CHECK 04675 setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 04676 #endif 04677 ast_debug(1, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 04678 AST_LIST_INSERT_TAIL(&tpeers, tpeer, list); 04679 } 04680 } 04681 04682 AST_LIST_UNLOCK(&tpeers); 04683 04684 return tpeer; 04685 }
static struct iax2_user* find_user | ( | const char * | name | ) | [static] |
Definition at line 1391 of file chan_iax2.c.
References ao2_find, iax2_user::name, and OBJ_POINTER.
01392 { 01393 struct iax2_user tmp_user = { 01394 .name = name, 01395 }; 01396 01397 return ao2_find(users, &tmp_user, OBJ_POINTER); 01398 }
static unsigned int fix_peerts | ( | struct timeval * | rxtrunktime, | |
int | callno, | |||
unsigned int | ts | |||
) | [static] |
Definition at line 4468 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvnow(), and ast_tvzero().
Referenced by socket_process_meta().
04469 { 04470 long ms; /* NOT unsigned */ 04471 if (ast_tvzero(iaxs[callno]->rxcore)) { 04472 /* Initialize rxcore time if appropriate */ 04473 iaxs[callno]->rxcore = ast_tvnow(); 04474 /* Round to nearest 20ms so traces look pretty */ 04475 iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000; 04476 } 04477 /* Calculate difference between trunk and channel */ 04478 ms = ast_tvdiff_ms(*rxtrunktime, iaxs[callno]->rxcore); 04479 /* Return as the sum of trunk time and the difference between trunk and real time */ 04480 return ms + ts; 04481 }
static void free_context | ( | struct iax2_context * | con | ) | [static] |
Definition at line 10266 of file chan_iax2.c.
References ast_free, and iax2_context::next.
Referenced by build_user(), and user_destructor().
10267 { 10268 struct iax2_context *conl; 10269 while(con) { 10270 conl = con; 10271 con = con->next; 10272 ast_free(conl); 10273 } 10274 }
static int function_iaxpeer | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 11948 of file chan_iax2.c.
References iax2_peer::addr, ast_codec_pref_index(), ast_copy_string(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_peer::capability, chan, iax2_peer::cid_name, iax2_peer::cid_num, iax2_peer::context, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iax2_peer::mailbox, peer_status(), peer_unref(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
11949 { 11950 struct iax2_peer *peer; 11951 char *peername, *colname; 11952 11953 peername = ast_strdupa(data); 11954 11955 /* if our channel, return the IP address of the endpoint of current channel */ 11956 if (!strcmp(peername,"CURRENTCHANNEL")) { 11957 unsigned short callno; 11958 if (chan->tech != &iax2_tech) 11959 return -1; 11960 callno = PTR_TO_CALLNO(chan->tech_pvt); 11961 ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len); 11962 return 0; 11963 } 11964 11965 if ((colname = strchr(peername, ','))) 11966 *colname++ = '\0'; 11967 else 11968 colname = "ip"; 11969 11970 if (!(peer = find_peer(peername, 1))) 11971 return -1; 11972 11973 if (!strcasecmp(colname, "ip")) { 11974 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 11975 } else if (!strcasecmp(colname, "status")) { 11976 peer_status(peer, buf, len); 11977 } else if (!strcasecmp(colname, "mailbox")) { 11978 ast_copy_string(buf, peer->mailbox, len); 11979 } else if (!strcasecmp(colname, "context")) { 11980 ast_copy_string(buf, peer->context, len); 11981 } else if (!strcasecmp(colname, "expire")) { 11982 snprintf(buf, len, "%d", peer->expire); 11983 } else if (!strcasecmp(colname, "dynamic")) { 11984 ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len); 11985 } else if (!strcasecmp(colname, "callerid_name")) { 11986 ast_copy_string(buf, peer->cid_name, len); 11987 } else if (!strcasecmp(colname, "callerid_num")) { 11988 ast_copy_string(buf, peer->cid_num, len); 11989 } else if (!strcasecmp(colname, "codecs")) { 11990 ast_getformatname_multiple(buf, len -1, peer->capability); 11991 } else if (!strncasecmp(colname, "codec[", 6)) { 11992 char *codecnum, *ptr; 11993 int codec = 0; 11994 11995 codecnum = strchr(colname, '['); 11996 *codecnum = '\0'; 11997 codecnum++; 11998 if ((ptr = strchr(codecnum, ']'))) { 11999 *ptr = '\0'; 12000 } 12001 if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { 12002 ast_copy_string(buf, ast_getformatname(codec), len); 12003 } else { 12004 buf[0] = '\0'; 12005 } 12006 } else { 12007 buf[0] = '\0'; 12008 } 12009 12010 peer_unref(peer); 12011 12012 return 0; 12013 }
static int get_auth_methods | ( | const char * | value | ) | [static] |
Definition at line 10486 of file chan_iax2.c.
References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.
Referenced by build_peer(), and build_user().
10487 { 10488 int methods = 0; 10489 if (strstr(value, "rsa")) 10490 methods |= IAX_AUTH_RSA; 10491 if (strstr(value, "md5")) 10492 methods |= IAX_AUTH_MD5; 10493 if (strstr(value, "plaintext")) 10494 methods |= IAX_AUTH_PLAINTEXT; 10495 return methods; 10496 }
static int get_encrypt_methods | ( | const char * | s | ) | [static] |
Definition at line 1240 of file chan_iax2.c.
References ast_true(), and IAX_ENCRYPT_AES128.
Referenced by build_peer(), build_user(), and set_config().
01241 { 01242 int e; 01243 if (!strcasecmp(s, "aes128")) 01244 e = IAX_ENCRYPT_AES128; 01245 else if (ast_true(s)) 01246 e = IAX_ENCRYPT_AES128; 01247 else 01248 e = 0; 01249 return e; 01250 }
static int get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 3104 of file chan_iax2.c.
References __get_from_jb(), and schedule_action.
Referenced by update_jbsched().
03105 { 03106 #ifdef SCHED_MULTITHREADED 03107 if (schedule_action(__get_from_jb, data)) 03108 #endif 03109 __get_from_jb(data); 03110 return 0; 03111 }
static char* handle_cli_iax2_provision | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 10122 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax2_provision(), iax_prov_complete_template(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
10123 { 10124 int force = 0; 10125 int res; 10126 10127 switch (cmd) { 10128 case CLI_INIT: 10129 e->command = "iax2 provision"; 10130 e->usage = 10131 "Usage: iax2 provision <host> <template> [forced]\n" 10132 " Provisions the given peer or IP address using a template\n" 10133 " matching either 'template' or '*' if the template is not\n" 10134 " found. If 'forced' is specified, even empty provisioning\n" 10135 " fields will be provisioned as empty fields.\n"; 10136 return NULL; 10137 case CLI_GENERATE: 10138 if (a->pos == 3) 10139 return iax_prov_complete_template(a->line, a->word, a->pos, a->n); 10140 return NULL; 10141 } 10142 10143 if (a->argc < 4) 10144 return CLI_SHOWUSAGE; 10145 if (a->argc > 4) { 10146 if (!strcasecmp(a->argv[4], "forced")) 10147 force = 1; 10148 else 10149 return CLI_SHOWUSAGE; 10150 } 10151 res = iax2_provision(NULL, -1, a->argv[2], a->argv[3], force); 10152 if (res < 0) 10153 ast_cli(a->fd, "Unable to find peer/address '%s'\n", a->argv[2]); 10154 else if (res < 1) 10155 ast_cli(a->fd, "No template (including wildcard) matching '%s'\n", a->argv[3]); 10156 else 10157 ast_cli(a->fd, "Provisioning '%s' with template '%s'%s\n", a->argv[2], a->argv[3], force ? ", forced" : ""); 10158 return CLI_SUCCESS; 10159 }
static char* handle_cli_iax2_prune_realtime | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2556 of file chan_iax2.c.
References ao2_unlink, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_set_flag, ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_peers(), expire_registry(), ast_cli_args::fd, find_peer(), find_user(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, ast_cli_args::line, ast_cli_args::n, peer_ref(), peer_unref(), ast_cli_args::pos, prune_peers(), prune_users(), ast_cli_entry::usage, user, user_unref(), and ast_cli_args::word.
02557 { 02558 struct iax2_peer *peer = NULL; 02559 struct iax2_user *user = NULL; 02560 02561 switch (cmd) { 02562 case CLI_INIT: 02563 e->command = "iax2 prune realtime"; 02564 e->usage = 02565 "Usage: iax2 prune realtime [<peername>|all]\n" 02566 " Prunes object(s) from the cache\n"; 02567 return NULL; 02568 case CLI_GENERATE: 02569 if (a->pos == 3) 02570 return complete_iax2_peers(a->line, a->word, a->pos, a->n); 02571 return NULL; 02572 } 02573 if (a->argc != 4) 02574 return CLI_SHOWUSAGE; 02575 if (!strcmp(a->argv[3], "all")) { 02576 prune_users(); 02577 prune_peers(); 02578 ast_cli(a->fd, "Cache flushed successfully.\n"); 02579 return CLI_SUCCESS; 02580 } 02581 peer = find_peer(a->argv[3], 0); 02582 user = find_user(a->argv[3]); 02583 if (peer || user) { 02584 if (peer) { 02585 if (ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 02586 ast_set_flag(peer, IAX_RTAUTOCLEAR); 02587 expire_registry(peer_ref(peer)); 02588 ast_cli(a->fd, "Peer %s was removed from the cache.\n", a->argv[3]); 02589 } else { 02590 ast_cli(a->fd, "Peer %s is not eligible for this operation.\n", a->argv[3]); 02591 } 02592 peer_unref(peer); 02593 } 02594 if (user) { 02595 if (ast_test_flag(user, IAX_RTCACHEFRIENDS)) { 02596 ast_set_flag(user, IAX_RTAUTOCLEAR); 02597 ast_cli(a->fd, "User %s was removed from the cache.\n", a->argv[3]); 02598 } else { 02599 ast_cli(a->fd, "User %s is not eligible for this operation.\n", a->argv[3]); 02600 } 02601 ao2_unlink(users,user); 02602 user_unref(user); 02603 } 02604 } else { 02605 ast_cli(a->fd, "%s was not found in the cache.\n", a->argv[3]); 02606 } 02607 02608 return CLI_SUCCESS; 02609 }
static char* handle_cli_iax2_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 11603 of file chan_iax2.c.
References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, reload_config(), and ast_cli_entry::usage.
11604 { 11605 switch (cmd) { 11606 case CLI_INIT: 11607 e->command = "iax2 reload"; 11608 e->usage = 11609 "Usage: iax2 reload\n" 11610 " Reloads IAX configuration from iax.conf\n"; 11611 return NULL; 11612 case CLI_GENERATE: 11613 return NULL; 11614 } 11615 11616 reload_config(); 11617 11618 return CLI_SUCCESS; 11619 }
static char* handle_cli_iax2_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5821 of file chan_iax2.c.
References iax2_peer::addr, ao2_ref, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_inet_ntoa(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_peers(), debugaddr, ast_cli_args::fd, find_peer(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
05822 { 05823 switch (cmd) { 05824 case CLI_INIT: 05825 e->command = "iax2 set debug {on|off|peer}"; 05826 e->usage = 05827 "Usage: iax2 set debug {on|off|peer peername}\n" 05828 " Enables/Disables dumping of IAX packets for debugging purposes.\n"; 05829 return NULL; 05830 case CLI_GENERATE: 05831 if (a->pos == 4) 05832 return complete_iax2_peers(a->line, a->word, a->pos, a->n); 05833 return NULL; 05834 } 05835 05836 if (a->argc < e->args || a->argc > e->args + 1) 05837 return CLI_SHOWUSAGE; 05838 05839 if (!strcasecmp(a->argv[3], "peer")) { 05840 struct iax2_peer *peer; 05841 05842 if (a->argc != e->args + 1) 05843 return CLI_SHOWUSAGE; 05844 05845 peer = find_peer(a->argv[4], 1); 05846 05847 if (!peer) { 05848 ast_cli(a->fd, "IAX2 peer '%s' does not exist\n", a->argv[e->args-1]); 05849 return CLI_FAILURE; 05850 } 05851 05852 debugaddr.sin_addr = peer->addr.sin_addr; 05853 debugaddr.sin_port = peer->addr.sin_port; 05854 05855 ast_cli(a->fd, "IAX2 Debugging Enabled for IP: %s:%d\n", 05856 ast_inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port)); 05857 05858 ao2_ref(peer, -1); 05859 } else if (!strncasecmp(a->argv[3], "on", 2)) { 05860 iaxdebug = 1; 05861 ast_cli(a->fd, "IAX2 Debugging Enabled\n"); 05862 } else { 05863 iaxdebug = 0; 05864 memset(&debugaddr, 0, sizeof(debugaddr)); 05865 ast_cli(a->fd, "IAX2 Debugging Disabled\n"); 05866 } 05867 return CLI_SUCCESS; 05868 }
static char* handle_cli_iax2_set_debug_jb | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5896 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), and ast_cli_entry::usage.
05897 { 05898 switch (cmd) { 05899 case CLI_INIT: 05900 e->command = "iax2 set debug jb {on|off}"; 05901 e->usage = 05902 "Usage: iax2 set debug jb {on|off}\n" 05903 " Enables/Disables jitterbuffer debugging information\n"; 05904 return NULL; 05905 case CLI_GENERATE: 05906 return NULL; 05907 } 05908 05909 if (a->argc != e->args) 05910 return CLI_SHOWUSAGE; 05911 05912 if (!strncasecmp(a->argv[e->args -1], "on", 2)) { 05913 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 05914 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 05915 } else { 05916 jb_setoutput(jb_error_output, jb_warning_output, NULL); 05917 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 05918 } 05919 return CLI_SUCCESS; 05920 }
static char* handle_cli_iax2_set_debug_trunk | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5870 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
05871 { 05872 switch (cmd) { 05873 case CLI_INIT: 05874 e->command = "iax2 set debug trunk {on|off}"; 05875 e->usage = 05876 "Usage: iax2 set debug trunk {on|off}\n" 05877 " Enables/Disables debugging of IAX trunking\n"; 05878 return NULL; 05879 case CLI_GENERATE: 05880 return NULL; 05881 } 05882 05883 if (a->argc != e->args) 05884 return CLI_SHOWUSAGE; 05885 05886 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 05887 iaxtrunkdebug = 1; 05888 ast_cli(a->fd, "IAX2 Trunk Debugging Enabled\n"); 05889 } else { 05890 iaxtrunkdebug = 0; 05891 ast_cli(a->fd, "IAX2 Trunk Debugging Disabled\n"); 05892 } 05893 return CLI_SUCCESS; 05894 }
static char* handle_cli_iax2_set_mtu | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Set trunk MTU from CLI.
Definition at line 2863 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, MAX_TRUNK_MTU, and ast_cli_entry::usage.
02864 { 02865 int mtuv; 02866 02867 switch (cmd) { 02868 case CLI_INIT: 02869 e->command = "iax2 set mtu"; 02870 e->usage = 02871 "Usage: iax2 set mtu <value>\n" 02872 " Set the system-wide IAX IP mtu to <value> bytes net or\n" 02873 " zero to disable. Disabling means that the operating system\n" 02874 " must handle fragmentation of UDP packets when the IAX2 trunk\n" 02875 " packet exceeds the UDP payload size. This is substantially\n" 02876 " below the IP mtu. Try 1240 on ethernets. Must be 172 or\n" 02877 " greater for G.711 samples.\n"; 02878 return NULL; 02879 case CLI_GENERATE: 02880 return NULL; 02881 } 02882 02883 if (a->argc != 4) 02884 return CLI_SHOWUSAGE; 02885 if (strncasecmp(a->argv[3], "default", strlen(a->argv[3])) == 0) 02886 mtuv = MAX_TRUNK_MTU; 02887 else 02888 mtuv = atoi(a->argv[3]); 02889 02890 if (mtuv == 0) { 02891 ast_cli(a->fd, "Trunk MTU control disabled (mtu was %d)\n", global_max_trunk_mtu); 02892 global_max_trunk_mtu = 0; 02893 return CLI_SUCCESS; 02894 } 02895 if (mtuv < 172 || mtuv > 4000) { 02896 ast_cli(a->fd, "Trunk MTU must be between 172 and 4000\n"); 02897 return CLI_SHOWUSAGE; 02898 } 02899 ast_cli(a->fd, "Trunk MTU changed from %d to %d\n", global_max_trunk_mtu, mtuv); 02900 global_max_trunk_mtu = mtuv; 02901 return CLI_SUCCESS; 02902 }
static char* handle_cli_iax2_show_cache | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2904 of file chan_iax2.c.
References ARRAY_LEN, ast_cli(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_tvnow(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, CACHE_FLAG_TRANSMITTED, CACHE_FLAG_UNKNOWN, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, iax2_dpcache::expiry, iax2_dpcache::exten, ast_cli_args::fd, iax2_dpcache::flags, iax2_dpcache::peercontext, s, ast_cli_entry::usage, and iax2_dpcache::waiters.
02905 { 02906 struct iax2_dpcache *dp = NULL; 02907 char tmp[1024], *pc = NULL; 02908 int s, x, y; 02909 struct timeval now = ast_tvnow(); 02910 02911 switch (cmd) { 02912 case CLI_INIT: 02913 e->command = "iax2 show cache"; 02914 e->usage = 02915 "Usage: iax2 show cache\n" 02916 " Display currently cached IAX Dialplan results.\n"; 02917 return NULL; 02918 case CLI_GENERATE: 02919 return NULL; 02920 } 02921 02922 AST_LIST_LOCK(&dpcache); 02923 02924 ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags"); 02925 02926 AST_LIST_TRAVERSE(&dpcache, dp, cache_list) { 02927 s = dp->expiry.tv_sec - now.tv_sec; 02928 tmp[0] = '\0'; 02929 if (dp->flags & CACHE_FLAG_EXISTS) 02930 strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1); 02931 if (dp->flags & CACHE_FLAG_NONEXISTENT) 02932 strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1); 02933 if (dp->flags & CACHE_FLAG_CANEXIST) 02934 strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1); 02935 if (dp->flags & CACHE_FLAG_PENDING) 02936 strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1); 02937 if (dp->flags & CACHE_FLAG_TIMEOUT) 02938 strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1); 02939 if (dp->flags & CACHE_FLAG_TRANSMITTED) 02940 strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1); 02941 if (dp->flags & CACHE_FLAG_MATCHMORE) 02942 strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1); 02943 if (dp->flags & CACHE_FLAG_UNKNOWN) 02944 strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1); 02945 /* Trim trailing pipe */ 02946 if (!ast_strlen_zero(tmp)) { 02947 tmp[strlen(tmp) - 1] = '\0'; 02948 } else { 02949 ast_copy_string(tmp, "(none)", sizeof(tmp)); 02950 } 02951 y = 0; 02952 pc = strchr(dp->peercontext, '@'); 02953 if (!pc) { 02954 pc = dp->peercontext; 02955 } else { 02956 pc++; 02957 } 02958 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 02959 if (dp->waiters[x] > -1) 02960 y++; 02961 } 02962 if (s > 0) { 02963 ast_cli(a->fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp); 02964 } else { 02965 ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp); 02966 } 02967 } 02968 02969 AST_LIST_LOCK(&dpcache); 02970 02971 return CLI_SUCCESS; 02972 }
static char* handle_cli_iax2_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5664 of file chan_iax2.c.
References ast_cli_args::argc, ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, jb_info::current, ast_cli_args::fd, FORMAT, FORMAT2, IAX_USEJITTERBUF, jb_getinfo(), jb_info::jitter, jb_info::min, S_OR, and ast_cli_entry::usage.
05665 { 05666 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" 05667 #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" 05668 #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" 05669 int x; 05670 int numchans = 0; 05671 05672 switch (cmd) { 05673 case CLI_INIT: 05674 e->command = "iax2 show channels"; 05675 e->usage = 05676 "Usage: iax2 show channels\n" 05677 " Lists all currently active IAX channels.\n"; 05678 return NULL; 05679 case CLI_GENERATE: 05680 return NULL; 05681 } 05682 05683 if (a->argc != 3) 05684 return CLI_SHOWUSAGE; 05685 ast_cli(a->fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format"); 05686 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 05687 ast_mutex_lock(&iaxsl[x]); 05688 if (iaxs[x]) { 05689 int lag, jitter, localdelay; 05690 jb_info jbinfo; 05691 05692 if (ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 05693 jb_getinfo(iaxs[x]->jb, &jbinfo); 05694 jitter = jbinfo.jitter; 05695 localdelay = jbinfo.current - jbinfo.min; 05696 } else { 05697 jitter = -1; 05698 localdelay = 0; 05699 } 05700 lag = iaxs[x]->remote_rr.delay; 05701 ast_cli(a->fd, FORMAT, 05702 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 05703 ast_inet_ntoa(iaxs[x]->addr.sin_addr), 05704 S_OR(iaxs[x]->username, "(None)"), 05705 iaxs[x]->callno, iaxs[x]->peercallno, 05706 iaxs[x]->oseqno, iaxs[x]->iseqno, 05707 lag, 05708 jitter, 05709 localdelay, 05710 ast_getformatname(iaxs[x]->voiceformat) ); 05711 numchans++; 05712 } 05713 ast_mutex_unlock(&iaxsl[x]); 05714 } 05715 ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 05716 return CLI_SUCCESS; 05717 #undef FORMAT 05718 #undef FORMAT2 05719 #undef FORMATB 05720 }
static char* handle_cli_iax2_show_firmware | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5515 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, ast_cli_args::fd, iax_firmware::fwh, iax_firmware::list, ast_cli_entry::usage, and ast_iax2_firmware_header::version.
05516 { 05517 struct iax_firmware *cur = NULL; 05518 05519 switch (cmd) { 05520 case CLI_INIT: 05521 e->command = "iax2 show firmware"; 05522 e->usage = 05523 "Usage: iax2 show firmware\n" 05524 " Lists all known IAX firmware images.\n"; 05525 return NULL; 05526 case CLI_GENERATE: 05527 return NULL; 05528 } 05529 05530 if (a->argc != 3 && a->argc != 4) 05531 return CLI_SHOWUSAGE; 05532 05533 ast_cli(a->fd, "%-15.15s %-15.15s %-15.15s\n", "Device", "Version", "Size"); 05534 AST_LIST_LOCK(&firmwares); 05535 AST_LIST_TRAVERSE(&firmwares, cur, list) { 05536 if ((a->argc == 3) || (!strcasecmp(a->argv[3], (char *) cur->fwh->devname))) { 05537 ast_cli(a->fd, "%-15.15s %-15d %-15d\n", cur->fwh->devname, 05538 ntohs(cur->fwh->version), (int)ntohl(cur->fwh->datalen)); 05539 } 05540 } 05541 AST_LIST_UNLOCK(&firmwares); 05542 05543 return CLI_SUCCESS; 05544 }
static char* handle_cli_iax2_show_netstats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5796 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), ast_cli_netstats(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
05797 { 05798 int numchans = 0; 05799 05800 switch (cmd) { 05801 case CLI_INIT: 05802 e->command = "iax2 show netstats"; 05803 e->usage = 05804 "Usage: iax2 show netstats\n" 05805 " Lists network status for all currently active IAX channels.\n"; 05806 return NULL; 05807 case CLI_GENERATE: 05808 return NULL; 05809 } 05810 if (a->argc != 3) 05811 return CLI_SHOWUSAGE; 05812 ast_cli(a->fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); 05813 ast_cli(a->fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n"); 05814 numchans = ast_cli_netstats(NULL, a->fd, 1); 05815 ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 05816 return CLI_SUCCESS; 05817 }
static char* handle_cli_iax2_show_peer | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show one peer in detail.
Definition at line 2725 of file chan_iax2.c.
References iax2_peer::addr, ast_cli_args::argc, ast_cli_args::argv, ast_callerid_merge(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, iax2_peer::capability, iax2_peer::cid_name, iax2_peer::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_peers(), iax2_peer::context, iax2_peer::defaddr, iax2_peer::expire, ast_cli_args::fd, find_peer(), iax2_peer::ha, IAX_DYNAMIC, ast_cli_args::line, iax2_peer::mailbox, ast_cli_args::n, iax2_peer::name, iax2_peer::parkinglot, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, ast_cli_args::pos, iax2_peer::prefs, iax2_peer::secret, iax2_peer::smoothing, status, ast_cli_entry::usage, iax2_peer::username, and ast_cli_args::word.
02726 { 02727 char status[30]; 02728 char cbuf[256]; 02729 struct iax2_peer *peer; 02730 char codec_buf[512]; 02731 int x = 0, codec = 0, load_realtime = 0; 02732 02733 switch (cmd) { 02734 case CLI_INIT: 02735 e->command = "iax2 show peer"; 02736 e->usage = 02737 "Usage: iax2 show peer <name>\n" 02738 " Display details on specific IAX peer\n"; 02739 return NULL; 02740 case CLI_GENERATE: 02741 if (a->pos == 3) 02742 return complete_iax2_peers(a->line, a->word, a->pos, a->n); 02743 return NULL; 02744 } 02745 02746 if (a->argc < 4) 02747 return CLI_SHOWUSAGE; 02748 02749 load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? 1 : 0; 02750 02751 peer = find_peer(a->argv[3], load_realtime); 02752 if (peer) { 02753 ast_cli(a->fd, "\n\n"); 02754 ast_cli(a->fd, " * Name : %s\n", peer->name); 02755 ast_cli(a->fd, " Secret : %s\n", ast_strlen_zero(peer->secret) ? "<Not set>" : "<Set>"); 02756 ast_cli(a->fd, " Context : %s\n", peer->context); 02757 ast_cli(a->fd, " Parking lot : %s\n", peer->parkinglot); 02758 ast_cli(a->fd, " Mailbox : %s\n", peer->mailbox); 02759 ast_cli(a->fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No"); 02760 ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 02761 ast_cli(a->fd, " Expire : %d\n", peer->expire); 02762 ast_cli(a->fd, " ACL : %s\n", (peer->ha ? "Yes" : "No")); 02763 ast_cli(a->fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port)); 02764 ast_cli(a->fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 02765 ast_cli(a->fd, " Username : %s\n", peer->username); 02766 ast_cli(a->fd, " Codecs : "); 02767 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 02768 ast_cli(a->fd, "%s\n", codec_buf); 02769 02770 ast_cli(a->fd, " Codec Order : ("); 02771 for(x = 0; x < 32 ; x++) { 02772 codec = ast_codec_pref_index(&peer->prefs,x); 02773 if(!codec) 02774 break; 02775 ast_cli(a->fd, "%s", ast_getformatname(codec)); 02776 if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) 02777 ast_cli(a->fd, "|"); 02778 } 02779 02780 if (!x) 02781 ast_cli(a->fd, "none"); 02782 ast_cli(a->fd, ")\n"); 02783 02784 ast_cli(a->fd, " Status : "); 02785 peer_status(peer, status, sizeof(status)); 02786 ast_cli(a->fd, "%s\n",status); 02787 ast_cli(a->fd, " Qualify : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off"); 02788 ast_cli(a->fd, "\n"); 02789 peer_unref(peer); 02790 } else { 02791 ast_cli(a->fd, "Peer %s not found.\n", a->argv[3]); 02792 ast_cli(a->fd, "\n"); 02793 } 02794 02795 return CLI_SUCCESS; 02796 }
static char* handle_cli_iax2_show_peers | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5483 of file chan_iax2.c.
References __iax2_show_peers(), ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and ast_cli_entry::usage.
05484 { 05485 switch (cmd) { 05486 case CLI_INIT: 05487 e->command = "iax2 show peers"; 05488 e->usage = 05489 "Usage: iax2 show peers [registered] [like <pattern>]\n" 05490 " Lists all known IAX2 peers.\n" 05491 " Optional 'registered' argument lists only peers with known addresses.\n" 05492 " Optional regular expression pattern is used to filter the peer list.\n"; 05493 return NULL; 05494 case CLI_GENERATE: 05495 return NULL; 05496 } 05497 05498 switch (__iax2_show_peers(0, a->fd, NULL, a->argc, a->argv)) { 05499 case RESULT_SHOWUSAGE: 05500 return CLI_SHOWUSAGE; 05501 case RESULT_FAILURE: 05502 return CLI_FAILURE; 05503 default: 05504 return CLI_SUCCESS; 05505 } 05506 }
static char* handle_cli_iax2_show_registry | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5623 of file chan_iax2.c.
References iax2_registry::addr, ast_cli_args::argc, ast_cli(), ast_copy_string(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, iax2_registry::dnsmgr, iax2_registry::entry, ast_cli_args::fd, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), iax2_registry::us, ast_cli_entry::usage, and iax2_registry::username.
05624 { 05625 #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" 05626 #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" 05627 struct iax2_registry *reg = NULL; 05628 char host[80]; 05629 char perceived[80]; 05630 int counter = 0; 05631 05632 switch (cmd) { 05633 case CLI_INIT: 05634 e->command = "iax2 show registry"; 05635 e->usage = 05636 "Usage: iax2 show registry\n" 05637 " Lists all registration requests and status.\n"; 05638 return NULL; 05639 case CLI_GENERATE: 05640 return NULL; 05641 } 05642 if (a->argc != 3) 05643 return CLI_SHOWUSAGE; 05644 ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); 05645 AST_LIST_LOCK(®istrations); 05646 AST_LIST_TRAVERSE(®istrations, reg, entry) { 05647 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); 05648 if (reg->us.sin_addr.s_addr) 05649 snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 05650 else 05651 ast_copy_string(perceived, "<Unregistered>", sizeof(perceived)); 05652 ast_cli(a->fd, FORMAT, host, 05653 (reg->dnsmgr) ? "Y" : "N", 05654 reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); 05655 counter++; 05656 } 05657 AST_LIST_UNLOCK(®istrations); 05658 ast_cli(a->fd, "%d IAX2 registrations.\n", counter); 05659 return CLI_SUCCESS; 05660 #undef FORMAT 05661 #undef FORMAT2 05662 }
static char* handle_cli_iax2_show_stats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2819 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax_frame::final, iax_get_frames(), iax_get_iframes(), iax_get_oframes(), iax2_trunk_peer::list, iax_frame::retries, and ast_cli_entry::usage.
02820 { 02821 struct iax_frame *cur; 02822 int cnt = 0, dead = 0, final = 0; 02823 02824 switch (cmd) { 02825 case CLI_INIT: 02826 e->command = "iax2 show stats"; 02827 e->usage = 02828 "Usage: iax2 show stats\n" 02829 " Display statistics on IAX channel driver.\n"; 02830 return NULL; 02831 case CLI_GENERATE: 02832 return NULL; 02833 } 02834 02835 if (a->argc != 3) 02836 return CLI_SHOWUSAGE; 02837 02838 AST_LIST_LOCK(&frame_queue); 02839 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 02840 if (cur->retries < 0) 02841 dead++; 02842 if (cur->final) 02843 final++; 02844 cnt++; 02845 } 02846 AST_LIST_UNLOCK(&frame_queue); 02847 02848 ast_cli(a->fd, " IAX Statistics\n"); 02849 ast_cli(a->fd, "---------------------\n"); 02850 ast_cli(a->fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); 02851 ast_cli(a->fd, "%d timed and %d untimed transmits; MTU %d/%d/%d\n", trunk_timed, trunk_untimed, 02852 trunk_maxmtu, trunk_nmaxmtu, global_max_trunk_mtu); 02853 ast_cli(a->fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); 02854 02855 trunk_timed = trunk_untimed = 0; 02856 if (trunk_maxmtu > trunk_nmaxmtu) 02857 trunk_nmaxmtu = trunk_maxmtu; 02858 02859 return CLI_SUCCESS; 02860 }
static char* handle_cli_iax2_show_threads | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5347 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, IAX_THREAD_TYPE_DYNAMIC, iaxthreadcount, iax2_thread::list, thread, and ast_cli_entry::usage.
05348 { 05349 struct iax2_thread *thread = NULL; 05350 time_t t; 05351 int threadcount = 0, dynamiccount = 0; 05352 char type; 05353 05354 switch (cmd) { 05355 case CLI_INIT: 05356 e->command = "iax2 show threads"; 05357 e->usage = 05358 "Usage: iax2 show threads\n" 05359 " Lists status of IAX helper threads\n"; 05360 return NULL; 05361 case CLI_GENERATE: 05362 return NULL; 05363 } 05364 if (a->argc != 3) 05365 return CLI_SHOWUSAGE; 05366 05367 ast_cli(a->fd, "IAX2 Thread Information\n"); 05368 time(&t); 05369 ast_cli(a->fd, "Idle Threads:\n"); 05370 AST_LIST_LOCK(&idle_list); 05371 AST_LIST_TRAVERSE(&idle_list, thread, list) { 05372 #ifdef DEBUG_SCHED_MULTITHREAD 05373 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n", 05374 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 05375 #else 05376 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n", 05377 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 05378 #endif 05379 threadcount++; 05380 } 05381 AST_LIST_UNLOCK(&idle_list); 05382 ast_cli(a->fd, "Active Threads:\n"); 05383 AST_LIST_LOCK(&active_list); 05384 AST_LIST_TRAVERSE(&active_list, thread, list) { 05385 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) 05386 type = 'D'; 05387 else 05388 type = 'P'; 05389 #ifdef DEBUG_SCHED_MULTITHREAD 05390 ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d, func='%s'\n", 05391 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 05392 #else 05393 ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 05394 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 05395 #endif 05396 threadcount++; 05397 } 05398 AST_LIST_UNLOCK(&active_list); 05399 ast_cli(a->fd, "Dynamic Threads:\n"); 05400 AST_LIST_LOCK(&dynamic_list); 05401 AST_LIST_TRAVERSE(&dynamic_list, thread, list) { 05402 #ifdef DEBUG_SCHED_MULTITHREAD 05403 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n", 05404 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 05405 #else 05406 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n", 05407 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 05408 #endif 05409 dynamiccount++; 05410 } 05411 AST_LIST_UNLOCK(&dynamic_list); 05412 ast_cli(a->fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount); 05413 return CLI_SUCCESS; 05414 }
static char* handle_cli_iax2_show_users | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5146 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_strlen_zero(), ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DEFAULT_CONTEXT, ast_cli_args::fd, FORMAT, FORMAT2, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, ast_cli_entry::usage, user, and user_unref().
05147 { 05148 regex_t regexbuf; 05149 int havepattern = 0; 05150 05151 #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" 05152 #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" 05153 05154 struct iax2_user *user = NULL; 05155 char auth[90]; 05156 char *pstr = ""; 05157 struct ao2_iterator i; 05158 05159 switch (cmd) { 05160 case CLI_INIT: 05161 e->command = "iax2 show users [like]"; 05162 e->usage = 05163 "Usage: iax2 show users [like <pattern>]\n" 05164 " Lists all known IAX2 users.\n" 05165 " Optional regular expression pattern is used to filter the user list.\n"; 05166 return NULL; 05167 case CLI_GENERATE: 05168 return NULL; 05169 } 05170 05171 switch (a->argc) { 05172 case 5: 05173 if (!strcasecmp(a->argv[3], "like")) { 05174 if (regcomp(®exbuf, a->argv[4], REG_EXTENDED | REG_NOSUB)) 05175 return CLI_SHOWUSAGE; 05176 havepattern = 1; 05177 } else 05178 return CLI_SHOWUSAGE; 05179 case 3: 05180 break; 05181 default: 05182 return CLI_SHOWUSAGE; 05183 } 05184 05185 ast_cli(a->fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); 05186 i = ao2_iterator_init(users, 0); 05187 for (user = ao2_iterator_next(&i); user; 05188 user_unref(user), user = ao2_iterator_next(&i)) { 05189 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) 05190 continue; 05191 05192 if (!ast_strlen_zero(user->secret)) { 05193 ast_copy_string(auth,user->secret, sizeof(auth)); 05194 } else if (!ast_strlen_zero(user->inkeys)) { 05195 snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys); 05196 } else 05197 ast_copy_string(auth, "-no secret-", sizeof(auth)); 05198 05199 if(ast_test_flag(user,IAX_CODEC_NOCAP)) 05200 pstr = "REQ Only"; 05201 else if(ast_test_flag(user,IAX_CODEC_NOPREFS)) 05202 pstr = "Disabled"; 05203 else 05204 pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host"; 05205 05206 ast_cli(a->fd, FORMAT2, user->name, auth, user->authmethods, 05207 user->contexts ? user->contexts->context : DEFAULT_CONTEXT, 05208 user->ha ? "Yes" : "No", pstr); 05209 } 05210 05211 if (havepattern) 05212 regfree(®exbuf); 05213 05214 return CLI_SUCCESS; 05215 #undef FORMAT 05216 #undef FORMAT2 05217 }
static char* handle_cli_iax2_test_losspct | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2611 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
02612 { 02613 switch (cmd) { 02614 case CLI_INIT: 02615 e->command = "iax2 test losspct"; 02616 e->usage = 02617 "Usage: iax2 test losspct <percentage>\n" 02618 " For testing, throws away <percentage> percent of incoming packets\n"; 02619 return NULL; 02620 case CLI_GENERATE: 02621 return NULL; 02622 } 02623 if (a->argc != 4) 02624 return CLI_SHOWUSAGE; 02625 02626 test_losspct = atoi(a->argv[3]); 02627 02628 return CLI_SUCCESS; 02629 }
static char* handle_cli_iax2_unregister | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5416 of file chan_iax2.c.
References ao2_find, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_unregister(), iax2_peer::expire, expire_registry(), ast_cli_args::fd, find_peer(), ast_cli_args::line, ast_cli_args::n, iax2_peer::name, OBJ_POINTER, peer_ref(), peer_unref(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
05417 { 05418 struct iax2_peer *p; 05419 05420 switch (cmd) { 05421 case CLI_INIT: 05422 e->command = "iax2 unregister"; 05423 e->usage = 05424 "Usage: iax2 unregister <peername>\n" 05425 " Unregister (force expiration) an IAX2 peer from the registry.\n"; 05426 return NULL; 05427 case CLI_GENERATE: 05428 return complete_iax2_unregister(a->line, a->word, a->pos, a->n); 05429 } 05430 05431 if (a->argc != 3) 05432 return CLI_SHOWUSAGE; 05433 05434 p = find_peer(a->argv[2], 1); 05435 if (p) { 05436 if (p->expire > 0) { 05437 struct iax2_peer tmp_peer = { 05438 .name = a->argv[2], 05439 }; 05440 struct iax2_peer *peer; 05441 05442 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 05443 if (peer) { 05444 expire_registry(peer_ref(peer)); /* will release its own reference when done */ 05445 peer_unref(peer); /* ref from ao2_find() */ 05446 ast_cli(a->fd, "Peer %s unregistered\n", a->argv[2]); 05447 } else { 05448 ast_cli(a->fd, "Peer %s not found\n", a->argv[2]); 05449 } 05450 } else { 05451 ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]); 05452 } 05453 } else { 05454 ast_cli(a->fd, "Peer unknown: %s. Not unregistered\n", a->argv[2]); 05455 } 05456 return CLI_SUCCESS; 05457 }
static void handle_deferred_full_frames | ( | struct iax2_thread * | thread | ) | [static] |
Handle any deferred full frames for this thread.
Definition at line 7908 of file chan_iax2.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), iax2_pkt_buf::buf, iax2_pkt_buf::entry, iax2_pkt_buf::len, socket_process(), and thread.
07909 { 07910 struct iax2_pkt_buf *pkt_buf; 07911 07912 ast_mutex_lock(&thread->lock); 07913 07914 while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) { 07915 ast_mutex_unlock(&thread->lock); 07916 07917 thread->buf = pkt_buf->buf; 07918 thread->buf_len = pkt_buf->len; 07919 thread->buf_size = pkt_buf->len + 1; 07920 07921 socket_process(thread); 07922 07923 thread->buf = NULL; 07924 ast_free(pkt_buf); 07925 07926 ast_mutex_lock(&thread->lock); 07927 } 07928 07929 ast_mutex_unlock(&thread->lock); 07930 }
static int handle_error | ( | void | ) | [static] |
Definition at line 2277 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().
02278 { 02279 /* XXX Ideally we should figure out why an error occurred and then abort those 02280 rather than continuing to try. Unfortunately, the published interface does 02281 not seem to work XXX */ 02282 #if 0 02283 struct sockaddr_in *sin; 02284 int res; 02285 struct msghdr m; 02286 struct sock_extended_err e; 02287 m.msg_name = NULL; 02288 m.msg_namelen = 0; 02289 m.msg_iov = NULL; 02290 m.msg_control = &e; 02291 m.msg_controllen = sizeof(e); 02292 m.msg_flags = 0; 02293 res = recvmsg(netsocket, &m, MSG_ERRQUEUE); 02294 if (res < 0) 02295 ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno)); 02296 else { 02297 if (m.msg_controllen) { 02298 sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e); 02299 if (sin) 02300 ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr)); 02301 else 02302 ast_log(LOG_WARNING, "No address detected??\n"); 02303 } else { 02304 ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno)); 02305 } 02306 } 02307 #endif 02308 return 0; 02309 }
static int iax2_ack_registry | ( | struct iax_ies * | ies, | |
struct sockaddr_in * | sin, | |||
int | callno | |||
) | [static] |
Acknowledgment received for OUR registration.
Definition at line 6888 of file chan_iax2.c.
References iax2_registry::addr, iax_ies::apparent_addr, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_verb, iax_ies::calling_number, EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_replace(), inaddrcmp(), LOG_WARNING, manager_event, iax2_registry::messages, iax_ies::msgcount, iax_ies::refresh, iax2_registry::refresh, REG_STATE_REGISTERED, iax2_registry::regstate, sched, iax2_registry::us, and iax_ies::username.
Referenced by socket_process().
06889 { 06890 struct iax2_registry *reg; 06891 /* Start pessimistic */ 06892 char peer[256] = ""; 06893 char msgstatus[60]; 06894 int refresh = 60; 06895 char ourip[256] = "<Unspecified>"; 06896 struct sockaddr_in oldus; 06897 struct sockaddr_in us; 06898 int oldmsgs; 06899 06900 memset(&us, 0, sizeof(us)); 06901 if (ies->apparent_addr) 06902 memmove(&us, ies->apparent_addr, sizeof(us)); 06903 if (ies->username) 06904 ast_copy_string(peer, ies->username, sizeof(peer)); 06905 if (ies->refresh) 06906 refresh = ies->refresh; 06907 if (ies->calling_number) { 06908 /* We don't do anything with it really, but maybe we should */ 06909 } 06910 reg = iaxs[callno]->reg; 06911 if (!reg) { 06912 ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer); 06913 return -1; 06914 } 06915 memcpy(&oldus, ®->us, sizeof(oldus)); 06916 oldmsgs = reg->messages; 06917 if (inaddrcmp(®->addr, sin)) { 06918 ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 06919 return -1; 06920 } 06921 memcpy(®->us, &us, sizeof(reg->us)); 06922 if (ies->msgcount >= 0) 06923 reg->messages = ies->msgcount & 0xffff; /* only low 16 bits are used in the transmission of the IE */ 06924 /* always refresh the registration at the interval requested by the server 06925 we are registering to 06926 */ 06927 reg->refresh = refresh; 06928 reg->expire = iax2_sched_replace(reg->expire, sched, 06929 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 06930 if (inaddrcmp(&oldus, ®->us) || (reg->messages != oldmsgs)) { 06931 if (reg->messages > 255) 06932 snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8); 06933 else if (reg->messages > 1) 06934 snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages); 06935 else if (reg->messages > 0) 06936 ast_copy_string(msgstatus, " with 1 new message waiting\n", sizeof(msgstatus)); 06937 else 06938 ast_copy_string(msgstatus, " with no messages waiting\n", sizeof(msgstatus)); 06939 snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 06940 ast_verb(3, "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); 06941 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); 06942 } 06943 reg->regstate = REG_STATE_REGISTERED; 06944 return 0; 06945 }
static void iax2_ami_channelupdate | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers.
Definition at line 1025 of file chan_iax2.c.
References chan_iax2_pvt::callno, EVENT_FLAG_SYSTEM, manager_event, ast_channel::name, chan_iax2_pvt::owner, chan_iax2_pvt::peer, and chan_iax2_pvt::peercallno.
Referenced by ast_iax2_new(), and iax2_answer().
01026 { 01027 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 01028 "Channel: %s\r\nChanneltype: IAX2\r\nIAX2-callno-local: %d\r\nIAX2-callno-remote: %d\r\nIAX2-peer: %s\r\n", 01029 pvt->owner ? pvt->owner->name : "", 01030 pvt->callno, pvt->peercallno, pvt->peer ? pvt->peer : ""); 01031 }
static int iax2_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 4233 of file chan_iax2.c.
References AST_CONTROL_ANSWER, ast_debug, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), iax2_ami_channelupdate(), PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
04234 { 04235 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04236 ast_debug(1, "Answering IAX2 call\n"); 04237 ast_mutex_lock(&iaxsl[callno]); 04238 if (iaxs[callno]) 04239 iax2_ami_channelupdate(iaxs[callno]); 04240 ast_mutex_unlock(&iaxsl[callno]); 04241 return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); 04242 }
static int iax2_append_register | ( | const char * | hostname, | |
const char * | username, | |||
const char * | secret, | |||
const char * | porta | |||
) | [static] |
Definition at line 6947 of file chan_iax2.c.
References ast_calloc, ast_copy_string(), ast_dnsmgr_lookup(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, iax2_registry::entry, IAX_DEFAULT_PORTNO, and IAX_DEFAULT_REG_EXPIRE.
Referenced by iax2_register().
06949 { 06950 struct iax2_registry *reg; 06951 06952 if (!(reg = ast_calloc(1, sizeof(*reg)))) 06953 return -1; 06954 06955 if (ast_dnsmgr_lookup(hostname, ®->addr, ®->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) { 06956 ast_free(reg); 06957 return -1; 06958 } 06959 06960 ast_copy_string(reg->username, username, sizeof(reg->username)); 06961 06962 if (secret) 06963 ast_copy_string(reg->secret, secret, sizeof(reg->secret)); 06964 06965 reg->expire = -1; 06966 reg->refresh = IAX_DEFAULT_REG_EXPIRE; 06967 reg->addr.sin_family = AF_INET; 06968 reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); 06969 06970 AST_LIST_LOCK(®istrations); 06971 AST_LIST_INSERT_HEAD(®istrations, reg, entry); 06972 AST_LIST_UNLOCK(®istrations); 06973 06974 return 0; 06975 }
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 4078 of file chan_iax2.c.
References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_mutex_lock(), ast_mutex_unlock(), ast_verb, f, iax2_tech, lock_both(), PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, and unlock_both().
04079 { 04080 struct ast_channel *cs[3]; 04081 struct ast_channel *who, *other; 04082 int to = -1; 04083 int res = -1; 04084 int transferstarted=0; 04085 struct ast_frame *f; 04086 unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt); 04087 unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt); 04088 struct timeval waittimer = {0, 0}; 04089 04090 /* We currently do not support native bridging if a timeoutms value has been provided */ 04091 if (timeoutms > 0) { 04092 return AST_BRIDGE_FAILED; 04093 } 04094 04095 timeoutms = 0; 04096 04097 lock_both(callno0, callno1); 04098 if (!iaxs[callno0] || !iaxs[callno1]) { 04099 unlock_both(callno0, callno1); 04100 return AST_BRIDGE_FAILED; 04101 } 04102 /* Put them in native bridge mode */ 04103 if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) { 04104 iaxs[callno0]->bridgecallno = callno1; 04105 iaxs[callno1]->bridgecallno = callno0; 04106 } 04107 unlock_both(callno0, callno1); 04108 04109 /* If not, try to bridge until we can execute a transfer, if we can */ 04110 cs[0] = c0; 04111 cs[1] = c1; 04112 for (/* ever */;;) { 04113 /* Check in case we got masqueraded into */ 04114 if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) { 04115 ast_verb(3, "Can't masquerade, we're different...\n"); 04116 /* Remove from native mode */ 04117 if (c0->tech == &iax2_tech) { 04118 ast_mutex_lock(&iaxsl[callno0]); 04119 iaxs[callno0]->bridgecallno = 0; 04120 ast_mutex_unlock(&iaxsl[callno0]); 04121 } 04122 if (c1->tech == &iax2_tech) { 04123 ast_mutex_lock(&iaxsl[callno1]); 04124 iaxs[callno1]->bridgecallno = 0; 04125 ast_mutex_unlock(&iaxsl[callno1]); 04126 } 04127 return AST_BRIDGE_FAILED_NOWARN; 04128 } 04129 if (c0->nativeformats != c1->nativeformats) { 04130 char buf0[255]; 04131 char buf1[255]; 04132 ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats); 04133 ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats); 04134 ast_verb(3, "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1); 04135 /* Remove from native mode */ 04136 lock_both(callno0, callno1); 04137 if (iaxs[callno0]) 04138 iaxs[callno0]->bridgecallno = 0; 04139 if (iaxs[callno1]) 04140 iaxs[callno1]->bridgecallno = 0; 04141 unlock_both(callno0, callno1); 04142 return AST_BRIDGE_FAILED_NOWARN; 04143 } 04144 /* check if transfered and if we really want native bridging */ 04145 if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) { 04146 /* Try the transfer */ 04147 if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) || 04148 ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA))) 04149 ast_log(LOG_WARNING, "Unable to start the transfer\n"); 04150 transferstarted = 1; 04151 } 04152 if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) { 04153 /* Call has been transferred. We're no longer involved */ 04154 struct timeval now = ast_tvnow(); 04155 if (ast_tvzero(waittimer)) { 04156 waittimer = now; 04157 } else if (now.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { 04158 c0->_softhangup |= AST_SOFTHANGUP_DEV; 04159 c1->_softhangup |= AST_SOFTHANGUP_DEV; 04160 *fo = NULL; 04161 *rc = c0; 04162 res = AST_BRIDGE_COMPLETE; 04163 break; 04164 } 04165 } 04166 to = 1000; 04167 who = ast_waitfor_n(cs, 2, &to); 04168 if (timeoutms > -1) { 04169 timeoutms -= (1000 - to); 04170 if (timeoutms < 0) 04171 timeoutms = 0; 04172 } 04173 if (!who) { 04174 if (!timeoutms) { 04175 res = AST_BRIDGE_RETRY; 04176 break; 04177 } 04178 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 04179 res = AST_BRIDGE_FAILED; 04180 break; 04181 } 04182 continue; 04183 } 04184 f = ast_read(who); 04185 if (!f) { 04186 *fo = NULL; 04187 *rc = who; 04188 res = AST_BRIDGE_COMPLETE; 04189 break; 04190 } 04191 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS) && (f->subclass != AST_CONTROL_SRCUPDATE)) { 04192 *fo = f; 04193 *rc = who; 04194 res = AST_BRIDGE_COMPLETE; 04195 break; 04196 } 04197 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 04198 if ((f->frametype == AST_FRAME_VOICE) || 04199 (f->frametype == AST_FRAME_TEXT) || 04200 (f->frametype == AST_FRAME_VIDEO) || 04201 (f->frametype == AST_FRAME_IMAGE) || 04202 (f->frametype == AST_FRAME_DTMF) || 04203 (f->frametype == AST_FRAME_CONTROL)) { 04204 /* monitored dtmf take out of the bridge. 04205 * check if we monitor the specific source. 04206 */ 04207 int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1; 04208 if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) { 04209 *rc = who; 04210 *fo = f; 04211 res = AST_BRIDGE_COMPLETE; 04212 /* Remove from native mode */ 04213 break; 04214 } 04215 /* everything else goes to the other side */ 04216 ast_write(other, f); 04217 } 04218 ast_frfree(f); 04219 /* Swap who gets priority */ 04220 cs[2] = cs[0]; 04221 cs[0] = cs[1]; 04222 cs[1] = cs[2]; 04223 } 04224 lock_both(callno0, callno1); 04225 if(iaxs[callno0]) 04226 iaxs[callno0]->bridgecallno = 0; 04227 if(iaxs[callno1]) 04228 iaxs[callno1]->bridgecallno = 0; 04229 unlock_both(callno0, callno1); 04230 return res; 04231 }
static int iax2_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 3690 of file chan_iax2.c.
References ast_channel::_state, ast_channel::adsicpe, ast_channel_datastore_find(), ast_copy_string(), ast_debug, AST_FRAME_IAX, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PRES_NUMBER_NOT_AVAILABLE, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_var_name(), ast_var_value(), auto_congest(), CALLNO_TO_PTR, capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, context, ast_channel::context, create_addr(), ast_datastore::data, iax2_datetime(), iax2_sched_add(), iax2_variable_datastore_info, IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_raw(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_OSPTOKEN, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VARIABLE, IAX_IE_VERSION, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPTOKEN_SIZE, IAX_PROTO_VERSION, IAX_SENDANI, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, parse_dial_string(), PTR_TO_CALLNO, sched, secret, send_command(), ast_channel::tech_pvt, and var.
03691 { 03692 struct sockaddr_in sin; 03693 char *l=NULL, *n=NULL, *tmpstr; 03694 struct iax_ie_data ied; 03695 char *defaultrdest = "s"; 03696 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03697 struct parsed_dial_string pds; 03698 struct create_addr_info cai; 03699 struct ast_var_t *var; 03700 struct ast_datastore *variablestore = ast_channel_datastore_find(c, &iax2_variable_datastore_info, NULL); 03701 const char* osp_token_ptr; 03702 unsigned int osp_token_length; 03703 unsigned char osp_block_index; 03704 unsigned int osp_block_length; 03705 unsigned char osp_buffer[256]; 03706 03707 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 03708 ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); 03709 return -1; 03710 } 03711 03712 memset(&cai, 0, sizeof(cai)); 03713 cai.encmethods = iax2_encryption; 03714 03715 memset(&pds, 0, sizeof(pds)); 03716 tmpstr = ast_strdupa(dest); 03717 parse_dial_string(tmpstr, &pds); 03718 03719 if (ast_strlen_zero(pds.peer)) { 03720 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest); 03721 return -1; 03722 } 03723 03724 if (!pds.exten) { 03725 pds.exten = defaultrdest; 03726 } 03727 03728 if (create_addr(pds.peer, c, &sin, &cai)) { 03729 ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); 03730 return -1; 03731 } 03732 03733 if (!pds.username && !ast_strlen_zero(cai.username)) 03734 pds.username = cai.username; 03735 if (!pds.password && !ast_strlen_zero(cai.secret)) 03736 pds.password = cai.secret; 03737 if (!pds.key && !ast_strlen_zero(cai.outkey)) 03738 pds.key = cai.outkey; 03739 if (!pds.context && !ast_strlen_zero(cai.peercontext)) 03740 pds.context = cai.peercontext; 03741 03742 /* Keep track of the context for outgoing calls too */ 03743 ast_copy_string(c->context, cai.context, sizeof(c->context)); 03744 03745 if (pds.port) 03746 sin.sin_port = htons(atoi(pds.port)); 03747 03748 l = c->cid.cid_num; 03749 n = c->cid.cid_name; 03750 03751 /* Now build request */ 03752 memset(&ied, 0, sizeof(ied)); 03753 03754 /* On new call, first IE MUST be IAX version of caller */ 03755 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 03756 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); 03757 if (pds.options && strchr(pds.options, 'a')) { 03758 /* Request auto answer */ 03759 iax_ie_append(&ied, IAX_IE_AUTOANSWER); 03760 } 03761 03762 iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); 03763 03764 if (l) { 03765 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); 03766 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03767 } else { 03768 if (n) 03769 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03770 else 03771 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); 03772 } 03773 03774 iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); 03775 iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); 03776 03777 if (n) 03778 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); 03779 if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) 03780 iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); 03781 03782 if (!ast_strlen_zero(c->language)) 03783 iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); 03784 if (!ast_strlen_zero(c->cid.cid_dnid)) 03785 iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); 03786 if (!ast_strlen_zero(c->cid.cid_rdnis)) 03787 iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis); 03788 03789 if (pds.context) 03790 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); 03791 03792 if (pds.username) 03793 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 03794 03795 if (cai.encmethods) 03796 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); 03797 03798 ast_mutex_lock(&iaxsl[callno]); 03799 03800 if (!ast_strlen_zero(c->context)) 03801 ast_string_field_set(iaxs[callno], context, c->context); 03802 03803 if (pds.username) 03804 ast_string_field_set(iaxs[callno], username, pds.username); 03805 03806 iaxs[callno]->encmethods = cai.encmethods; 03807 03808 iaxs[callno]->adsi = cai.adsi; 03809 03810 ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret); 03811 ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest); 03812 03813 if (pds.key) 03814 ast_string_field_set(iaxs[callno], outkey, pds.key); 03815 if (pds.password) 03816 ast_string_field_set(iaxs[callno], secret, pds.password); 03817 03818 iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); 03819 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); 03820 iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); 03821 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); 03822 03823 if (iaxs[callno]->maxtime) { 03824 /* Initialize pingtime and auto-congest time */ 03825 iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; 03826 iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno)); 03827 } else if (autokill) { 03828 iaxs[callno]->pingtime = autokill / 2; 03829 iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); 03830 } 03831 03832 /* Check if there is an OSP token set by IAXCHANINFO function */ 03833 osp_token_ptr = iaxs[callno]->osptoken; 03834 if (!ast_strlen_zero(osp_token_ptr)) { 03835 if ((osp_token_length = strlen(osp_token_ptr)) <= IAX_MAX_OSPTOKEN_SIZE) { 03836 osp_block_index = 0; 03837 while (osp_token_length > 0) { 03838 osp_block_length = IAX_MAX_OSPBLOCK_SIZE < osp_token_length ? IAX_MAX_OSPBLOCK_SIZE : osp_token_length; 03839 osp_buffer[0] = osp_block_index; 03840 memcpy(osp_buffer + 1, osp_token_ptr, osp_block_length); 03841 iax_ie_append_raw(&ied, IAX_IE_OSPTOKEN, osp_buffer, osp_block_length + 1); 03842 osp_block_index++; 03843 osp_token_ptr += osp_block_length; 03844 osp_token_length -= osp_block_length; 03845 } 03846 } else 03847 ast_log(LOG_WARNING, "OSP token is too long\n"); 03848 } else if (iaxdebug) 03849 ast_debug(1, "OSP token is undefined\n"); 03850 03851 /* send the command using the appropriate socket for this peer */ 03852 iaxs[callno]->sockfd = cai.sockfd; 03853 03854 /* Add remote vars */ 03855 if (variablestore) { 03856 AST_LIST_HEAD(, ast_var_t) *variablelist = variablestore->data; 03857 ast_debug(1, "Found an IAX variable store on this channel\n"); 03858 AST_LIST_LOCK(variablelist); 03859 AST_LIST_TRAVERSE(variablelist, var, entries) { 03860 char tmp[256]; 03861 int i; 03862 ast_debug(1, "Found IAXVAR '%s' with value '%s' (to transmit)\n", ast_var_name(var), ast_var_value(var)); 03863 /* Automatically divide the value up into sized chunks */ 03864 for (i = 0; i < strlen(ast_var_value(var)); i += 255 - (strlen(ast_var_name(var)) + 1)) { 03865 snprintf(tmp, sizeof(tmp), "%s=%s", ast_var_name(var), ast_var_value(var) + i); 03866 iax_ie_append_str(&ied, IAX_IE_VARIABLE, tmp); 03867 } 03868 } 03869 AST_LIST_UNLOCK(variablelist); 03870 } 03871 03872 /* Transmit the string in a "NEW" request */ 03873 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 03874 03875 ast_mutex_unlock(&iaxsl[callno]); 03876 ast_setstate(c, AST_STATE_RINGING); 03877 03878 return 0; 03879 }
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 11851 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_CANEXIST, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
11852 { 11853 int res = 0; 11854 struct iax2_dpcache *dp = NULL; 11855 #if 0 11856 ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 11857 #endif 11858 if ((priority != 1) && (priority != 2)) 11859 return 0; 11860 11861 AST_LIST_LOCK(&dpcache); 11862 if ((dp = find_cache(chan, data, context, exten, priority))) { 11863 if (dp->flags & CACHE_FLAG_CANEXIST) 11864 res = 1; 11865 } else { 11866 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 11867 } 11868 AST_LIST_UNLOCK(&dpcache); 11869 11870 return res; 11871 }
static unsigned int iax2_datetime | ( | const char * | tz | ) | [static] |
Definition at line 3597 of file chan_iax2.c.
References ast_localtime(), ast_strlen_zero(), ast_tvnow(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.
Referenced by iax2_call(), and update_registry().
03598 { 03599 struct timeval t = ast_tvnow(); 03600 struct ast_tm tm; 03601 unsigned int tmp; 03602 ast_localtime(&t, &tm, ast_strlen_zero(tz) ? NULL : tz); 03603 tmp = (tm.tm_sec >> 1) & 0x1f; /* 5 bits of seconds */ 03604 tmp |= (tm.tm_min & 0x3f) << 5; /* 6 bits of minutes */ 03605 tmp |= (tm.tm_hour & 0x1f) << 11; /* 5 bits of hours */ 03606 tmp |= (tm.tm_mday & 0x1f) << 16; /* 5 bits of day of month */ 03607 tmp |= ((tm.tm_mon + 1) & 0xf) << 21; /* 4 bits of month */ 03608 tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */ 03609 return tmp; 03610 }
static void iax2_destroy | ( | int | callno | ) | [static] |
Definition at line 2383 of file chan_iax2.c.
References ao2_ref, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_queue_hangup(), ast_tvnow(), DEADLOCK_AVOIDANCE, iax2_destroy_helper(), chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), remove_by_transfercallno(), chan_iax2_pvt::transfercallno, and update_max_trunk().
Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __unload_module(), delete_users(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), peer_destructor(), scheduled_destroy(), and socket_process().
02384 { 02385 struct chan_iax2_pvt *pvt = NULL; 02386 struct ast_channel *owner = NULL; 02387 02388 retry: 02389 if ((pvt = iaxs[callno])) { 02390 iax2_destroy_helper(pvt); 02391 } 02392 02393 lastused[callno] = ast_tvnow(); 02394 02395 owner = pvt ? pvt->owner : NULL; 02396 02397 if (owner) { 02398 if (ast_channel_trylock(owner)) { 02399 ast_debug(3, "Avoiding IAX destroy deadlock\n"); 02400 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 02401 goto retry; 02402 } 02403 } 02404 02405 if (!owner) { 02406 iaxs[callno] = NULL; 02407 } 02408 02409 if (pvt) { 02410 if (!owner) { 02411 pvt->owner = NULL; 02412 } else { 02413 /* If there's an owner, prod it to give up */ 02414 /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup() 02415 * because we already hold the owner channel lock. */ 02416 ast_queue_hangup(owner); 02417 } 02418 02419 if (pvt->peercallno) { 02420 remove_by_peercallno(pvt); 02421 } 02422 02423 if (pvt->transfercallno) { 02424 remove_by_transfercallno(pvt); 02425 } 02426 02427 if (!owner) { 02428 ao2_ref(pvt, -1); 02429 pvt = NULL; 02430 } 02431 } 02432 02433 if (owner) { 02434 ast_channel_unlock(owner); 02435 } 02436 02437 if (callno & 0x4000) { 02438 update_max_trunk(); 02439 } 02440 }
static void iax2_destroy_helper | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1443 of file chan_iax2.c.
References ao2_find, ast_atomic_fetchadd_int(), ast_clear_flag, AST_SCHED_DEL, AST_SCHED_DEL_SPINLOCK, ast_test_flag, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, chan_iax2_pvt::callno, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::keyrotateid, chan_iax2_pvt::lagid, iax2_user::name, OBJ_POINTER, chan_iax2_pvt::pingid, sched, user, user_unref(), and chan_iax2_pvt::username.
Referenced by iax2_destroy(), iax2_predestroy(), pvt_destructor(), and stop_stuff().
01444 { 01445 /* Decrement AUTHREQ count if needed */ 01446 if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) { 01447 struct iax2_user *user; 01448 struct iax2_user tmp_user = { 01449 .name = pvt->username, 01450 }; 01451 01452 user = ao2_find(users, &tmp_user, OBJ_POINTER); 01453 if (user) { 01454 ast_atomic_fetchadd_int(&user->curauthreq, -1); 01455 user_unref(user); 01456 } 01457 01458 ast_clear_flag(pvt, IAX_MAXAUTHREQ); 01459 } 01460 /* No more pings or lagrq's */ 01461 AST_SCHED_DEL_SPINLOCK(sched, pvt->pingid, &iaxsl[pvt->callno]); 01462 AST_SCHED_DEL_SPINLOCK(sched, pvt->lagid, &iaxsl[pvt->callno]); 01463 AST_SCHED_DEL(sched, pvt->autoid); 01464 AST_SCHED_DEL(sched, pvt->authid); 01465 AST_SCHED_DEL(sched, pvt->initid); 01466 AST_SCHED_DEL(sched, pvt->jbid); 01467 AST_SCHED_DEL(sched, pvt->keyrotateid); 01468 }
static int iax2_devicestate | ( | void * | data | ) | [static] |
Part of the device state notification system ---.
Definition at line 12098 of file chan_iax2.c.
References iax2_peer::addr, ast_debug, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::defaddr, find_peer(), iax2_peer::historicms, iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, parse_dial_string(), and peer_unref().
12099 { 12100 struct parsed_dial_string pds; 12101 char *tmp = ast_strdupa(data); 12102 struct iax2_peer *p; 12103 int res = AST_DEVICE_INVALID; 12104 12105 memset(&pds, 0, sizeof(pds)); 12106 parse_dial_string(tmp, &pds); 12107 12108 if (ast_strlen_zero(pds.peer)) { 12109 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 12110 return res; 12111 } 12112 12113 ast_debug(3, "Checking device state for device %s\n", pds.peer); 12114 12115 /* SLD: FIXME: second call to find_peer during registration */ 12116 if (!(p = find_peer(pds.peer, 1))) 12117 return res; 12118 12119 res = AST_DEVICE_UNAVAILABLE; 12120 ast_debug(3, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", 12121 pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); 12122 12123 if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && 12124 (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { 12125 /* Peer is registered, or have default IP address 12126 and a valid registration */ 12127 if (p->historicms == 0 || p->historicms <= p->maxms) 12128 /* let the core figure out whether it is in use or not */ 12129 res = AST_DEVICE_UNKNOWN; 12130 } 12131 12132 peer_unref(p); 12133 12134 return res; 12135 }
static int iax2_digit_begin | ( | struct ast_channel * | c, | |
char | digit | |||
) | [static] |
Definition at line 3221 of file chan_iax2.c.
References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03222 { 03223 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); 03224 }
static int iax2_digit_end | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 3226 of file chan_iax2.c.
References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03227 { 03228 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); 03229 }
static int iax2_do_register | ( | struct iax2_registry * | reg | ) | [static] |
Definition at line 9981 of file chan_iax2.c.
References iax2_registry::addr, ast_debug, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_replace(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, LOG_WARNING, NEW_FORCE, iax2_registry::refresh, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), and iax2_registry::username.
Referenced by __iax2_do_register_s(), load_module(), and reload_config().
09982 { 09983 struct iax_ie_data ied; 09984 if (iaxdebug) 09985 ast_debug(1, "Sending registration request for '%s'\n", reg->username); 09986 09987 if (reg->dnsmgr && 09988 ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { 09989 /* Maybe the IP has changed, force DNS refresh */ 09990 ast_dnsmgr_refresh(reg->dnsmgr); 09991 } 09992 09993 /* 09994 * if IP has Changed, free allocated call to create a new one with new IP 09995 * call has the pointer to IP and must be updated to the new one 09996 */ 09997 if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) { 09998 int callno = reg->callno; 09999 ast_mutex_lock(&iaxsl[callno]); 10000 iax2_destroy(callno); 10001 ast_mutex_unlock(&iaxsl[callno]); 10002 reg->callno = 0; 10003 } 10004 if (!reg->addr.sin_addr.s_addr) { 10005 if (iaxdebug) 10006 ast_debug(1, "Unable to send registration request for '%s' without IP address\n", reg->username); 10007 /* Setup the next registration attempt */ 10008 reg->expire = iax2_sched_replace(reg->expire, sched, 10009 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 10010 return -1; 10011 } 10012 10013 if (!reg->callno) { 10014 ast_debug(3, "Allocate call number\n"); 10015 reg->callno = find_callno_locked(0, 0, ®->addr, NEW_FORCE, defaultsockfd, 0); 10016 if (reg->callno < 1) { 10017 ast_log(LOG_WARNING, "Unable to create call for registration\n"); 10018 return -1; 10019 } else 10020 ast_debug(3, "Registration created on call %d\n", reg->callno); 10021 iaxs[reg->callno]->reg = reg; 10022 ast_mutex_unlock(&iaxsl[reg->callno]); 10023 } 10024 /* Setup the next registration a little early */ 10025 reg->expire = iax2_sched_replace(reg->expire, sched, 10026 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 10027 /* Send the request */ 10028 memset(&ied, 0, sizeof(ied)); 10029 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 10030 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 10031 send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 10032 reg->regstate = REG_STATE_REGSENT; 10033 return 0; 10034 }
static int iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 6743 of file chan_iax2.c.
References __iax2_do_register_s(), and schedule_action.
Referenced by iax2_ack_registry(), and iax2_do_register().
06744 { 06745 #ifdef SCHED_MULTITHREADED 06746 if (schedule_action(__iax2_do_register_s, data)) 06747 #endif 06748 __iax2_do_register_s(data); 06749 return 0; 06750 }
static void iax2_dprequest | ( | struct iax2_dpcache * | dp, | |
int | callno | |||
) | [static] |
Definition at line 7469 of file chan_iax2.c.
References AST_FRAME_IAX, auto_hangup(), CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_replace(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, sched, and send_command().
Referenced by find_cache(), and socket_process().
07470 { 07471 struct iax_ie_data ied; 07472 /* Auto-hangup with 30 seconds of inactivity */ 07473 iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 07474 sched, 30000, auto_hangup, (void *)(long)callno); 07475 memset(&ied, 0, sizeof(ied)); 07476 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten); 07477 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); 07478 dp->flags |= CACHE_FLAG_TRANSMITTED; 07479 }
static void * iax2_dup_variable_datastore | ( | void * | ) | [static] |
Definition at line 1040 of file chan_iax2.c.
References ast_calloc, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_name(), ast_var_value(), ast_var_t::entries, and LOG_ERROR.
01041 { 01042 AST_LIST_HEAD(, ast_var_t) *oldlist = old, *newlist; 01043 struct ast_var_t *oldvar, *newvar; 01044 01045 newlist = ast_calloc(sizeof(*newlist), 1); 01046 if (!newlist) { 01047 ast_log(LOG_ERROR, "Unable to duplicate iax2 variables\n"); 01048 return NULL; 01049 } 01050 01051 AST_LIST_HEAD_INIT(newlist); 01052 AST_LIST_LOCK(oldlist); 01053 AST_LIST_TRAVERSE(oldlist, oldvar, entries) { 01054 newvar = ast_var_assign(ast_var_name(oldvar), ast_var_value(oldvar)); 01055 if (newvar) 01056 AST_LIST_INSERT_TAIL(newlist, newvar, entries); 01057 else 01058 ast_log(LOG_ERROR, "Unable to duplicate iax2 variable '%s'\n", ast_var_name(oldvar)); 01059 } 01060 AST_LIST_UNLOCK(oldlist); 01061 return newlist; 01062 }
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 11897 of file chan_iax2.c.
References ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_verb, CACHE_FLAG_EXISTS, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_exec(), and pbx_findapp().
11898 { 11899 char odata[256]; 11900 char req[256]; 11901 char *ncontext; 11902 struct iax2_dpcache *dp = NULL; 11903 struct ast_app *dial = NULL; 11904 #if 0 11905 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); 11906 #endif 11907 if (priority == 2) { 11908 /* Indicate status, can be overridden in dialplan */ 11909 const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS"); 11910 if (dialstatus) { 11911 dial = pbx_findapp(dialstatus); 11912 if (dial) 11913 pbx_exec(chan, dial, ""); 11914 } 11915 return -1; 11916 } else if (priority != 1) 11917 return -1; 11918 11919 AST_LIST_LOCK(&dpcache); 11920 if ((dp = find_cache(chan, data, context, exten, priority))) { 11921 if (dp->flags & CACHE_FLAG_EXISTS) { 11922 ast_copy_string(odata, data, sizeof(odata)); 11923 ncontext = strchr(odata, '/'); 11924 if (ncontext) { 11925 *ncontext = '\0'; 11926 ncontext++; 11927 snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext); 11928 } else { 11929 snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten); 11930 } 11931 ast_verb(3, "Executing Dial('%s')\n", req); 11932 } else { 11933 AST_LIST_UNLOCK(&dpcache); 11934 ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data); 11935 return -1; 11936 } 11937 } 11938 AST_LIST_UNLOCK(&dpcache); 11939 11940 if ((dial = pbx_findapp("Dial"))) 11941 return pbx_exec(chan, dial, req); 11942 else 11943 ast_log(LOG_WARNING, "No dial application registered\n"); 11944 11945 return -1; 11946 }
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 11828 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_EXISTS, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
11829 { 11830 int res = 0; 11831 struct iax2_dpcache *dp = NULL; 11832 #if 0 11833 ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 11834 #endif 11835 if ((priority != 1) && (priority != 2)) 11836 return 0; 11837 11838 AST_LIST_LOCK(&dpcache); 11839 if ((dp = find_cache(chan, data, context, exten, priority))) { 11840 if (dp->flags & CACHE_FLAG_EXISTS) 11841 res = 1; 11842 } else { 11843 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 11844 } 11845 AST_LIST_UNLOCK(&dpcache); 11846 11847 return res; 11848 }
static int iax2_fixup | ( | struct ast_channel * | oldchannel, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 3248 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, PTR_TO_CALLNO, and ast_channel::tech_pvt.
03249 { 03250 unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt); 03251 ast_mutex_lock(&iaxsl[callno]); 03252 if (iaxs[callno]) 03253 iaxs[callno]->owner = newchan; 03254 else 03255 ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n"); 03256 ast_mutex_unlock(&iaxsl[callno]); 03257 return 0; 03258 }
static void iax2_frame_free | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 1470 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().
01471 { 01472 AST_SCHED_DEL(sched, fr->retrans); 01473 iax_frame_free(fr); 01474 }
static void iax2_free_variable_datastore | ( | void * | ) | [static] |
Definition at line 1064 of file chan_iax2.c.
References ast_free, AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and ast_var_t::entries.
01065 { 01066 AST_LIST_HEAD(, ast_var_t) *oldlist = old; 01067 struct ast_var_t *oldvar; 01068 01069 AST_LIST_LOCK(oldlist); 01070 while ((oldvar = AST_LIST_REMOVE_HEAD(oldlist, entries))) { 01071 ast_free(oldvar); 01072 } 01073 AST_LIST_UNLOCK(oldlist); 01074 AST_LIST_HEAD_DESTROY(oldlist); 01075 ast_free(oldlist); 01076 }
static int iax2_getpeername | ( | struct sockaddr_in | sin, | |
char * | host, | |||
int | len | |||
) | [static] |
Definition at line 1411 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_copy_string(), iax2_peer::name, peer_unref(), and realtime_peer().
Referenced by __find_callno().
01412 { 01413 struct iax2_peer *peer = NULL; 01414 int res = 0; 01415 struct ao2_iterator i; 01416 01417 i = ao2_iterator_init(peers, 0); 01418 while ((peer = ao2_iterator_next(&i))) { 01419 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 01420 (peer->addr.sin_port == sin.sin_port)) { 01421 ast_copy_string(host, peer->name, len); 01422 peer_unref(peer); 01423 res = 1; 01424 break; 01425 } 01426 peer_unref(peer); 01427 } 01428 01429 if (!peer) { 01430 peer = realtime_peer(NULL, &sin); 01431 if (peer) { 01432 ast_copy_string(host, peer->name, len); 01433 peer_unref(peer); 01434 res = 1; 01435 } 01436 } 01437 01438 return res; 01439 }
static int iax2_getpeertrunk | ( | struct sockaddr_in | sin | ) | [static] |
Definition at line 4301 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_test_flag, IAX_TRUNK, and peer_unref().
Referenced by check_access().
04302 { 04303 struct iax2_peer *peer; 04304 int res = 0; 04305 struct ao2_iterator i; 04306 04307 i = ao2_iterator_init(peers, 0); 04308 while ((peer = ao2_iterator_next(&i))) { 04309 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 04310 (peer->addr.sin_port == sin.sin_port)) { 04311 res = ast_test_flag(peer, IAX_TRUNK); 04312 peer_unref(peer); 04313 break; 04314 } 04315 peer_unref(peer); 04316 } 04317 04318 return res; 04319 }
static int iax2_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3881 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_test_flag, ast_verb, CALLNO_TO_PTR, ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, LOG_ERROR, LOG_WARNING, ast_channel::name, PTR_TO_CALLNO, sched, scheduled_destroy(), send_command_final(), and ast_channel::tech_pvt.
03882 { 03883 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03884 struct iax_ie_data ied; 03885 int alreadygone; 03886 memset(&ied, 0, sizeof(ied)); 03887 ast_mutex_lock(&iaxsl[callno]); 03888 if (callno && iaxs[callno]) { 03889 ast_debug(1, "We're hanging up %s now...\n", c->name); 03890 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE); 03891 /* Send the hangup unless we have had a transmission error or are already gone */ 03892 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); 03893 if (!iaxs[callno]->error && !alreadygone) { 03894 if (send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1)) { 03895 ast_log(LOG_WARNING, "No final packet could be sent for callno %d\n", callno); 03896 } 03897 if (!iaxs[callno]) { 03898 ast_mutex_unlock(&iaxsl[callno]); 03899 return 0; 03900 } 03901 } 03902 /* Explicitly predestroy it */ 03903 iax2_predestroy(callno); 03904 /* If we were already gone to begin with, destroy us now */ 03905 if (iaxs[callno] && alreadygone) { 03906 ast_debug(1, "Really destroying %s now...\n", c->name); 03907 iax2_destroy(callno); 03908 } else if (iaxs[callno]) { 03909 if (ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) { 03910 ast_log(LOG_ERROR, "Unable to schedule iax2 callno %d destruction?!! Destroying immediately.\n", callno); 03911 iax2_destroy(callno); 03912 } 03913 } 03914 } else if (c->tech_pvt) { 03915 /* If this call no longer exists, but the channel still 03916 * references it we need to set the channel's tech_pvt to null 03917 * to avoid ast_channel_free() trying to free it. 03918 */ 03919 c->tech_pvt = NULL; 03920 } 03921 ast_mutex_unlock(&iaxsl[callno]); 03922 ast_verb(3, "Hungup '%s'\n", c->name); 03923 return 0; 03924 }
static int iax2_indicate | ( | struct ast_channel * | c, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 4244 of file chan_iax2.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_CONTROL, ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::mohinterpret, PTR_TO_CALLNO, send_command(), ast_channel::tech_pvt, and wait_for_peercallno().
04245 { 04246 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04247 struct chan_iax2_pvt *pvt; 04248 int res = 0; 04249 04250 if (iaxdebug) 04251 ast_debug(1, "Indicating condition %d\n", condition); 04252 04253 ast_mutex_lock(&iaxsl[callno]); 04254 pvt = iaxs[callno]; 04255 04256 if (wait_for_peercallno(pvt)) { 04257 res = -1; 04258 goto done; 04259 } 04260 04261 switch (condition) { 04262 case AST_CONTROL_HOLD: 04263 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 04264 ast_moh_start(c, data, pvt->mohinterpret); 04265 goto done; 04266 } 04267 break; 04268 case AST_CONTROL_UNHOLD: 04269 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 04270 ast_moh_stop(c); 04271 goto done; 04272 } 04273 } 04274 04275 res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); 04276 04277 done: 04278 ast_mutex_unlock(&iaxsl[callno]); 04279 04280 return res; 04281 }
static int iax2_key_rotate | ( | const void * | vpvt | ) | [static] |
Definition at line 3996 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_sched_add(), iax_ie_data::buf, build_ecx_key(), chan_iax2_pvt::callno, IAX_COMMAND_RTKEY, IAX_DEBUGDIGEST, iax_ie_append_raw(), IAX_IE_CHALLENGE, chan_iax2_pvt::keyrotateid, md5(), MD5Final(), MD5Init(), MD5Update(), iax_ie_data::pos, sched, and send_command().
Referenced by iax2_send().
03997 { 03998 int res = 0; 03999 struct chan_iax2_pvt *pvt = (void *) vpvt; 04000 struct MD5Context md5; 04001 char key[17] = ""; 04002 struct iax_ie_data ied = { 04003 .pos = 0, 04004 }; 04005 04006 ast_mutex_lock(&iaxsl[pvt->callno]); 04007 pvt->keyrotateid = 04008 ast_sched_add(sched, 120000 + (ast_random() % 180001), iax2_key_rotate, vpvt); 04009 04010 snprintf(key, sizeof(key), "%lX", ast_random()); 04011 04012 MD5Init(&md5); 04013 MD5Update(&md5, (unsigned char *) key, strlen(key)); 04014 MD5Final((unsigned char *) key, &md5); 04015 04016 IAX_DEBUGDIGEST("Sending", key); 04017 04018 iax_ie_append_raw(&ied, IAX_IE_CHALLENGE, key, 16); 04019 04020 res = send_command(pvt, AST_FRAME_IAX, IAX_COMMAND_RTKEY, 0, ied.buf, ied.pos, -1); 04021 04022 build_ecx_key((unsigned char *) key, pvt); 04023 04024 ast_mutex_unlock(&iaxsl[pvt->callno]); 04025 04026 return res; 04027 }
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 11874 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_MATCHMORE, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
11875 { 11876 int res = 0; 11877 struct iax2_dpcache *dp = NULL; 11878 #if 0 11879 ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 11880 #endif 11881 if ((priority != 1) && (priority != 2)) 11882 return 0; 11883 11884 AST_LIST_LOCK(&dpcache); 11885 if ((dp = find_cache(chan, data, context, exten, priority))) { 11886 if (dp->flags & CACHE_FLAG_MATCHMORE) 11887 res = 1; 11888 } else { 11889 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 11890 } 11891 AST_LIST_UNLOCK(&dpcache); 11892 11893 return res; 11894 }
static int iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 10184 of file chan_iax2.c.
References __iax2_poke_noanswer(), peer_unref(), iax2_peer::pokeexpire, and schedule_action.
Referenced by iax2_poke_peer().
10185 { 10186 struct iax2_peer *peer = (struct iax2_peer *)data; 10187 peer->pokeexpire = -1; 10188 #ifdef SCHED_MULTITHREADED 10189 if (schedule_action(__iax2_poke_noanswer, data)) 10190 #endif 10191 __iax2_poke_noanswer(data); 10192 peer_unref(peer); 10193 return 0; 10194 }
static int iax2_poke_peer | ( | struct iax2_peer * | peer, | |
int | heldcall | |||
) | [static] |
Definition at line 10205 of file chan_iax2.c.
References iax2_peer::addr, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax2_peer::callno, DEFAULT_MAXMS, iax2_peer::dnsmgr, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), iax2_sched_add(), IAX_COMMAND_POKE, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, iax2_peer::name, NEW_FORCE, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, sched, send_command(), and iax2_peer::sockfd.
Referenced by __iax2_poke_peer_s(), iax2_poke_peer_cb(), poke_all_peers(), reg_source_db(), and update_registry().
10206 { 10207 int callno; 10208 if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) { 10209 /* IF we have no IP without dnsmgr, or this isn't to be monitored, return 10210 immediately after clearing things out */ 10211 peer->lastms = 0; 10212 peer->historicms = 0; 10213 peer->pokeexpire = -1; 10214 peer->callno = 0; 10215 return 0; 10216 } 10217 10218 /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */ 10219 if ((callno = peer->callno) > 0) { 10220 ast_log(LOG_NOTICE, "Still have a callno...\n"); 10221 ast_mutex_lock(&iaxsl[callno]); 10222 iax2_destroy(callno); 10223 ast_mutex_unlock(&iaxsl[callno]); 10224 } 10225 if (heldcall) 10226 ast_mutex_unlock(&iaxsl[heldcall]); 10227 callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0); 10228 if (heldcall) 10229 ast_mutex_lock(&iaxsl[heldcall]); 10230 if (peer->callno < 1) { 10231 ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); 10232 return -1; 10233 } 10234 10235 /* Speed up retransmission times for this qualify call */ 10236 iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1; 10237 iaxs[peer->callno]->peerpoke = peer; 10238 10239 if (peer->pokeexpire > -1) { 10240 if (!ast_sched_del(sched, peer->pokeexpire)) { 10241 peer->pokeexpire = -1; 10242 peer_unref(peer); 10243 } 10244 } 10245 10246 /* Queue up a new task to handle no reply */ 10247 /* If the host is already unreachable then use the unreachable interval instead */ 10248 if (peer->lastms < 0) 10249 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer)); 10250 else 10251 peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer)); 10252 10253 if (peer->pokeexpire == -1) 10254 peer_unref(peer); 10255 10256 /* And send the poke */ 10257 ast_mutex_lock(&iaxsl[callno]); 10258 if (iaxs[callno]) { 10259 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1); 10260 } 10261 ast_mutex_unlock(&iaxsl[callno]); 10262 10263 return 0; 10264 }
static int iax2_poke_peer_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 10196 of file chan_iax2.c.
References iax2_poke_peer().
Referenced by load_module().
10197 { 10198 struct iax2_peer *peer = obj; 10199 10200 iax2_poke_peer(peer, 0); 10201 10202 return 0; 10203 }
static int iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 7509 of file chan_iax2.c.
References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.
Referenced by __iax2_poke_noanswer(), and socket_process().
07510 { 07511 struct iax2_peer *peer = (struct iax2_peer *)data; 07512 peer->pokeexpire = -1; 07513 #ifdef SCHED_MULTITHREADED 07514 if (schedule_action(__iax2_poke_peer_s, data)) 07515 #endif 07516 __iax2_poke_peer_s(data); 07517 return 0; 07518 }
static int iax2_predestroy | ( | int | callno | ) | [static] |
Definition at line 2360 of file chan_iax2.c.
References ast_module_unref(), ast_set_flag, ast_test_flag, iax2_destroy_helper(), iax2_queue_hangup(), IAX_ALREADYGONE, chan_iax2_pvt::owner, and ast_channel::tech_pvt.
Referenced by iax2_hangup(), and send_command_final().
02361 { 02362 struct ast_channel *c = NULL; 02363 struct chan_iax2_pvt *pvt = iaxs[callno]; 02364 02365 if (!pvt) 02366 return -1; 02367 02368 if (!ast_test_flag(pvt, IAX_ALREADYGONE)) { 02369 iax2_destroy_helper(pvt); 02370 ast_set_flag(pvt, IAX_ALREADYGONE); 02371 } 02372 02373 if ((c = pvt->owner)) { 02374 c->tech_pvt = NULL; 02375 iax2_queue_hangup(callno); 02376 pvt->owner = NULL; 02377 ast_module_unref(ast_module_info->self); 02378 } 02379 02380 return 0; 02381 }
static void * iax2_process_thread | ( | void * | data | ) | [static] |
Definition at line 9852 of file chan_iax2.c.
References ast_atomic_fetchadd_int(), ast_cond_timedwait(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_tvadd(), ast_tvnow(), iax2_process_thread_cleanup(), IAX_THREAD_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), signal_condition(), and thread.
Referenced by find_idle_thread(), and start_network_thread().
09853 { 09854 struct iax2_thread *thread = data; 09855 struct timeval wait; 09856 struct timespec ts; 09857 int put_into_idle = 0; 09858 int first_time = 1; 09859 09860 ast_atomic_fetchadd_int(&iaxactivethreadcount,1); 09861 pthread_cleanup_push(iax2_process_thread_cleanup, data); 09862 for(;;) { 09863 /* Wait for something to signal us to be awake */ 09864 ast_mutex_lock(&thread->lock); 09865 09866 /* Flag that we're ready to accept signals */ 09867 if (first_time) { 09868 signal_condition(&thread->init_lock, &thread->init_cond); 09869 first_time = 0; 09870 } 09871 09872 /* Put into idle list if applicable */ 09873 if (put_into_idle) 09874 insert_idle_thread(thread); 09875 09876 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) { 09877 struct iax2_thread *t = NULL; 09878 /* Wait to be signalled or time out */ 09879 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 09880 ts.tv_sec = wait.tv_sec; 09881 ts.tv_nsec = wait.tv_usec * 1000; 09882 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) { 09883 /* This thread was never put back into the available dynamic 09884 * thread list, so just go away. */ 09885 if (!put_into_idle) { 09886 ast_mutex_unlock(&thread->lock); 09887 break; 09888 } 09889 AST_LIST_LOCK(&dynamic_list); 09890 /* Account for the case where this thread is acquired *right* after a timeout */ 09891 if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list))) 09892 ast_atomic_fetchadd_int(&iaxdynamicthreadcount, -1); 09893 AST_LIST_UNLOCK(&dynamic_list); 09894 if (t) { 09895 /* This dynamic thread timed out waiting for a task and was 09896 * not acquired immediately after the timeout, 09897 * so it's time to go away. */ 09898 ast_mutex_unlock(&thread->lock); 09899 break; 09900 } 09901 /* Someone grabbed our thread *right* after we timed out. 09902 * Wait for them to set us up with something to do and signal 09903 * us to continue. */ 09904 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 09905 ts.tv_sec = wait.tv_sec; 09906 ts.tv_nsec = wait.tv_usec * 1000; 09907 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) 09908 { 09909 ast_mutex_unlock(&thread->lock); 09910 break; 09911 } 09912 } 09913 } else { 09914 ast_cond_wait(&thread->cond, &thread->lock); 09915 } 09916 09917 /* Go back into our respective list */ 09918 put_into_idle = 1; 09919 09920 ast_mutex_unlock(&thread->lock); 09921 09922 if (thread->iostate == IAX_IOSTATE_IDLE) 09923 continue; 09924 09925 /* Add ourselves to the active list now */ 09926 AST_LIST_LOCK(&active_list); 09927 AST_LIST_INSERT_HEAD(&active_list, thread, list); 09928 AST_LIST_UNLOCK(&active_list); 09929 09930 /* See what we need to do */ 09931 switch(thread->iostate) { 09932 case IAX_IOSTATE_READY: 09933 thread->actions++; 09934 thread->iostate = IAX_IOSTATE_PROCESSING; 09935 socket_process(thread); 09936 handle_deferred_full_frames(thread); 09937 break; 09938 case IAX_IOSTATE_SCHEDREADY: 09939 thread->actions++; 09940 thread->iostate = IAX_IOSTATE_PROCESSING; 09941 #ifdef SCHED_MULTITHREADED 09942 thread->schedfunc(thread->scheddata); 09943 #endif 09944 default: 09945 break; 09946 } 09947 time(&thread->checktime); 09948 thread->iostate = IAX_IOSTATE_IDLE; 09949 #ifdef DEBUG_SCHED_MULTITHREAD 09950 thread->curfunc[0]='\0'; 09951 #endif 09952 09953 /* Now... remove ourselves from the active list, and return to the idle list */ 09954 AST_LIST_LOCK(&active_list); 09955 AST_LIST_REMOVE(&active_list, thread, list); 09956 AST_LIST_UNLOCK(&active_list); 09957 09958 /* Make sure another frame didn't sneak in there after we thought we were done. */ 09959 handle_deferred_full_frames(thread); 09960 } 09961 09962 /*!\note For some reason, idle threads are exiting without being removed 09963 * from an idle list, which is causing memory corruption. Forcibly remove 09964 * it from the list, if it's there. 09965 */ 09966 AST_LIST_LOCK(&idle_list); 09967 AST_LIST_REMOVE(&idle_list, thread, list); 09968 AST_LIST_UNLOCK(&idle_list); 09969 09970 AST_LIST_LOCK(&dynamic_list); 09971 AST_LIST_REMOVE(&dynamic_list, thread, list); 09972 AST_LIST_UNLOCK(&dynamic_list); 09973 09974 /* I am exiting here on my own volition, I need to clean up my own data structures 09975 * Assume that I am no longer in any of the lists (idle, active, or dynamic) 09976 */ 09977 pthread_cleanup_pop(1); 09978 return NULL; 09979 }
static void iax2_process_thread_cleanup | ( | void * | data | ) | [static] |
Definition at line 9841 of file chan_iax2.c.
References ast_atomic_dec_and_test(), ast_cond_destroy(), ast_free, ast_mutex_destroy(), iaxactivethreadcount, and thread.
Referenced by iax2_process_thread().
09842 { 09843 struct iax2_thread *thread = data; 09844 ast_mutex_destroy(&thread->lock); 09845 ast_cond_destroy(&thread->cond); 09846 ast_mutex_destroy(&thread->init_lock); 09847 ast_cond_destroy(&thread->init_cond); 09848 ast_free(thread); 09849 ast_atomic_dec_and_test(&iaxactivethreadcount); 09850 }
static int iax2_provision | ( | struct sockaddr_in * | end, | |
int | sockfd, | |||
char * | dest, | |||
const char * | template, | |||
int | force | |||
) | [static] |
Definition at line 10036 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_mutex_unlock(), ast_set_flag, auto_hangup(), iax_ie_data::buf, create_addr(), find_callno_locked(), iax2_sched_replace(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), NEW_FORCE, iax_ie_data::pos, sched, and send_command().
Referenced by check_provisioning(), handle_cli_iax2_provision(), and iax2_prov_app().
10037 { 10038 /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning 10039 is found for template */ 10040 struct iax_ie_data provdata; 10041 struct iax_ie_data ied; 10042 unsigned int sig; 10043 struct sockaddr_in sin; 10044 int callno; 10045 struct create_addr_info cai; 10046 10047 memset(&cai, 0, sizeof(cai)); 10048 10049 ast_debug(1, "Provisioning '%s' from template '%s'\n", dest, template); 10050 10051 if (iax_provision_build(&provdata, &sig, template, force)) { 10052 ast_debug(1, "No provisioning found for template '%s'\n", template); 10053 return 0; 10054 } 10055 10056 if (end) { 10057 memcpy(&sin, end, sizeof(sin)); 10058 cai.sockfd = sockfd; 10059 } else if (create_addr(dest, NULL, &sin, &cai)) 10060 return -1; 10061 10062 /* Build the rest of the message */ 10063 memset(&ied, 0, sizeof(ied)); 10064 iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); 10065 10066 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 10067 if (!callno) 10068 return -1; 10069 10070 if (iaxs[callno]) { 10071 /* Schedule autodestruct in case they don't ever give us anything back */ 10072 iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 10073 sched, 15000, auto_hangup, (void *)(long)callno); 10074 ast_set_flag(iaxs[callno], IAX_PROVISION); 10075 /* Got a call number now, so go ahead and send the provisioning information */ 10076 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); 10077 } 10078 ast_mutex_unlock(&iaxsl[callno]); 10079 10080 return 1; 10081 }
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 1985 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_control_data(), DEADLOCK_AVOIDANCE, and chan_iax2_pvt::owner.
Referenced by socket_process().
01987 { 01988 for (;;) { 01989 if (iaxs[callno] && iaxs[callno]->owner) { 01990 if (ast_channel_trylock(iaxs[callno]->owner)) { 01991 /* Avoid deadlock by pausing and trying again */ 01992 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01993 } else { 01994 ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); 01995 ast_channel_unlock(iaxs[callno]->owner); 01996 break; 01997 } 01998 } else 01999 break; 02000 } 02001 return 0; 02002 }
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 1923 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, and chan_iax2_pvt::owner.
Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), __get_from_jb(), and socket_process().
01924 { 01925 for (;;) { 01926 if (iaxs[callno] && iaxs[callno]->owner) { 01927 if (ast_channel_trylock(iaxs[callno]->owner)) { 01928 /* Avoid deadlock by pausing and trying again */ 01929 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01930 } else { 01931 ast_queue_frame(iaxs[callno]->owner, f); 01932 ast_channel_unlock(iaxs[callno]->owner); 01933 break; 01934 } 01935 } else 01936 break; 01937 } 01938 return 0; 01939 }
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 1954 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, and chan_iax2_pvt::owner.
Referenced by iax2_predestroy().
01955 { 01956 for (;;) { 01957 if (iaxs[callno] && iaxs[callno]->owner) { 01958 if (ast_channel_trylock(iaxs[callno]->owner)) { 01959 /* Avoid deadlock by pausing and trying again */ 01960 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01961 } else { 01962 ast_queue_hangup(iaxs[callno]->owner); 01963 ast_channel_unlock(iaxs[callno]->owner); 01964 break; 01965 } 01966 } else 01967 break; 01968 } 01969 return 0; 01970 }
static struct ast_frame * iax2_read | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3990 of file chan_iax2.c.
References ast_log(), ast_null_frame, and LOG_NOTICE.
03991 { 03992 ast_log(LOG_NOTICE, "I should never be called!\n"); 03993 return &ast_null_frame; 03994 }
static int iax2_register | ( | const char * | value, | |
int | lineno | |||
) | [static] |
Definition at line 6977 of file chan_iax2.c.
References ast_copy_string(), ast_log(), copy(), hostname, iax2_append_register(), LOG_WARNING, secret, and strsep().
Referenced by set_config().
06978 { 06979 char copy[256]; 06980 char *username, *hostname, *secret; 06981 char *porta; 06982 char *stringp=NULL; 06983 06984 if (!value) 06985 return -1; 06986 06987 ast_copy_string(copy, value, sizeof(copy)); 06988 stringp = copy; 06989 username = strsep(&stringp, "@"); 06990 hostname = strsep(&stringp, "@"); 06991 06992 if (!hostname) { 06993 ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno); 06994 return -1; 06995 } 06996 06997 stringp = username; 06998 username = strsep(&stringp, ":"); 06999 secret = strsep(&stringp, ":"); 07000 stringp = hostname; 07001 hostname = strsep(&stringp, ":"); 07002 porta = strsep(&stringp, ":"); 07003 07004 if (porta && !atoi(porta)) { 07005 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 07006 return -1; 07007 } 07008 07009 return iax2_append_register(hostname, username, secret, porta); 07010 }
static struct ast_channel * iax2_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 10276 of file chan_iax2.c.
References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_translator_best_choice(), create_addr(), find_callno_locked(), globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, LOG_WARNING, make_trunk(), ast_channel::name, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), ast_channel::readformat, and ast_channel::writeformat.
10277 { 10278 int callno; 10279 int res; 10280 int fmt, native; 10281 struct sockaddr_in sin; 10282 struct ast_channel *c; 10283 struct parsed_dial_string pds; 10284 struct create_addr_info cai; 10285 char *tmpstr; 10286 10287 memset(&pds, 0, sizeof(pds)); 10288 tmpstr = ast_strdupa(data); 10289 parse_dial_string(tmpstr, &pds); 10290 10291 if (ast_strlen_zero(pds.peer)) { 10292 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 10293 return NULL; 10294 } 10295 10296 memset(&cai, 0, sizeof(cai)); 10297 cai.capability = iax2_capability; 10298 10299 ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 10300 10301 /* Populate our address from the given */ 10302 if (create_addr(pds.peer, NULL, &sin, &cai)) { 10303 *cause = AST_CAUSE_UNREGISTERED; 10304 return NULL; 10305 } 10306 10307 if (pds.port) 10308 sin.sin_port = htons(atoi(pds.port)); 10309 10310 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 10311 if (callno < 1) { 10312 ast_log(LOG_WARNING, "Unable to create call\n"); 10313 *cause = AST_CAUSE_CONGESTION; 10314 return NULL; 10315 } 10316 10317 /* If this is a trunk, update it now */ 10318 ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 10319 if (ast_test_flag(&cai, IAX_TRUNK)) { 10320 int new_callno; 10321 if ((new_callno = make_trunk(callno, 1)) != -1) 10322 callno = new_callno; 10323 } 10324 iaxs[callno]->maxtime = cai.maxtime; 10325 if (cai.found) 10326 ast_string_field_set(iaxs[callno], host, pds.peer); 10327 10328 c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability); 10329 10330 ast_mutex_unlock(&iaxsl[callno]); 10331 10332 if (c) { 10333 /* Choose a format we can live with */ 10334 if (c->nativeformats & format) 10335 c->nativeformats &= format; 10336 else { 10337 native = c->nativeformats; 10338 fmt = format; 10339 res = ast_translator_best_choice(&fmt, &native); 10340 if (res < 0) { 10341 ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", 10342 ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); 10343 ast_hangup(c); 10344 return NULL; 10345 } 10346 c->nativeformats = native; 10347 } 10348 c->readformat = ast_best_codec(c->nativeformats); 10349 c->writeformat = c->readformat; 10350 } 10351 10352 return c; 10353 }
static int iax2_sched_add | ( | struct sched_context * | con, | |
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) | [static] |
Definition at line 1197 of file chan_iax2.c.
References ast_sched_add(), sched_lock, and signal_condition().
Referenced by __attempt_transmit(), __find_callno(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), iax2_call(), iax2_poke_peer(), make_trunk(), network_thread(), reg_source_db(), socket_process(), and update_registry().
01198 { 01199 int res; 01200 01201 res = ast_sched_add(con, when, callback, data); 01202 signal_condition(&sched_lock, &sched_cond); 01203 01204 return res; 01205 }
static int iax2_sched_replace | ( | int | id, | |
struct sched_context * | con, | |||
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) | [static] |
Definition at line 1189 of file chan_iax2.c.
References AST_SCHED_REPLACE, sched_lock, and signal_condition().
Referenced by auth_fail(), iax2_ack_registry(), iax2_do_register(), iax2_dprequest(), iax2_provision(), and update_jbsched().
01190 { 01191 AST_SCHED_REPLACE(id, con, when, callback, data); 01192 signal_condition(&sched_lock, &sched_cond); 01193 01194 return id; 01195 }
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 4948 of file chan_iax2.c.
References iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, ast_frame::datalen, iax_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, iax_frame::encmethods, encrypt_frame(), f, iax_frame::final, ast_frame::frametype, iax2_key_rotate(), iax2_transmit(), iax2_trunk_queue(), IAX_CALLENCRYPTED, IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_outputframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::keyrotateid, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, LOG_NOTICE, 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, ast_frame::ptr, 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().
04949 { 04950 /* Queue a packet for delivery on a given private structure. Use "ts" for 04951 timestamp, or calculate if ts is 0. Send immediately without retransmission 04952 or delayed, with retransmission */ 04953 struct ast_iax2_full_hdr *fh; 04954 struct ast_iax2_mini_hdr *mh; 04955 struct ast_iax2_video_hdr *vh; 04956 struct { 04957 struct iax_frame fr2; 04958 unsigned char buffer[4096]; 04959 } frb; 04960 struct iax_frame *fr; 04961 int res; 04962 int sendmini=0; 04963 unsigned int lastsent; 04964 unsigned int fts; 04965 04966 frb.fr2.afdatalen = sizeof(frb.buffer); 04967 04968 if (!pvt) { 04969 ast_log(LOG_WARNING, "No private structure for packet?\n"); 04970 return -1; 04971 } 04972 04973 lastsent = pvt->lastsent; 04974 04975 /* Calculate actual timestamp */ 04976 fts = calc_timestamp(pvt, ts, f); 04977 04978 /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out 04979 * (the endpoint should detect the lost packet itself). But, we want to do this here, so that we 04980 * increment the "predicted timestamps" for voice, if we're predicting */ 04981 if(f->frametype == AST_FRAME_VOICE && f->datalen == 0) 04982 return 0; 04983 #if 0 04984 ast_log(LOG_NOTICE, 04985 "f->frametype %c= AST_FRAME_VOICE, %sencrypted, %srotation scheduled...\n", 04986 *("=!" + (f->frametype == AST_FRAME_VOICE)), 04987 IAX_CALLENCRYPTED(pvt) ? "" : "not ", 04988 pvt->keyrotateid != -1 ? "" : "no " 04989 ); 04990 #endif 04991 if (pvt->keyrotateid == -1 && f->frametype == AST_FRAME_VOICE && IAX_CALLENCRYPTED(pvt)) { 04992 iax2_key_rotate(pvt); 04993 } 04994 04995 if ((ast_test_flag(pvt, IAX_TRUNK) || 04996 (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) || 04997 ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L)))) 04998 /* High two bytes are the same on timestamp, or sending on a trunk */ && 04999 (f->frametype == AST_FRAME_VOICE) 05000 /* is a voice frame */ && 05001 (f->subclass == pvt->svoiceformat) 05002 /* is the same type */ ) { 05003 /* Force immediate rather than delayed transmission */ 05004 now = 1; 05005 /* Mark that mini-style frame is appropriate */ 05006 sendmini = 1; 05007 } 05008 if ( f->frametype == AST_FRAME_VIDEO ) { 05009 /* 05010 * If the lower 15 bits of the timestamp roll over, or if 05011 * the video format changed then send a full frame. 05012 * Otherwise send a mini video frame 05013 */ 05014 if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) && 05015 ((f->subclass & ~0x1) == pvt->svideoformat) 05016 ) { 05017 now = 1; 05018 sendmini = 1; 05019 } else { 05020 now = 0; 05021 sendmini = 0; 05022 } 05023 pvt->lastvsent = fts; 05024 } 05025 /* Allocate an iax_frame */ 05026 if (now) { 05027 fr = &frb.fr2; 05028 } else 05029 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)); 05030 if (!fr) { 05031 ast_log(LOG_WARNING, "Out of memory\n"); 05032 return -1; 05033 } 05034 /* Copy our prospective frame into our immediate or retransmitted wrapper */ 05035 iax_frame_wrap(fr, f); 05036 05037 fr->ts = fts; 05038 fr->callno = pvt->callno; 05039 fr->transfer = transfer; 05040 fr->final = final; 05041 fr->encmethods = 0; 05042 if (!sendmini) { 05043 /* We need a full frame */ 05044 if (seqno > -1) 05045 fr->oseqno = seqno; 05046 else 05047 fr->oseqno = pvt->oseqno++; 05048 fr->iseqno = pvt->iseqno; 05049 fh = (struct ast_iax2_full_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_full_hdr)); 05050 fh->scallno = htons(fr->callno | IAX_FLAG_FULL); 05051 fh->ts = htonl(fr->ts); 05052 fh->oseqno = fr->oseqno; 05053 if (transfer) { 05054 fh->iseqno = 0; 05055 } else 05056 fh->iseqno = fr->iseqno; 05057 /* Keep track of the last thing we've acknowledged */ 05058 if (!transfer) 05059 pvt->aseqno = fr->iseqno; 05060 fh->type = fr->af.frametype & 0xFF; 05061 if (fr->af.frametype == AST_FRAME_VIDEO) 05062 fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6); 05063 else 05064 fh->csub = compress_subclass(fr->af.subclass); 05065 if (transfer) { 05066 fr->dcallno = pvt->transfercallno; 05067 } else 05068 fr->dcallno = pvt->peercallno; 05069 fh->dcallno = htons(fr->dcallno); 05070 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); 05071 fr->data = fh; 05072 fr->retries = 0; 05073 /* Retry after 2x the ping time has passed */ 05074 fr->retrytime = pvt->pingtime * 2; 05075 if (fr->retrytime < MIN_RETRY_TIME) 05076 fr->retrytime = MIN_RETRY_TIME; 05077 if (fr->retrytime > MAX_RETRY_TIME) 05078 fr->retrytime = MAX_RETRY_TIME; 05079 /* Acks' don't get retried */ 05080 if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) 05081 fr->retries = -1; 05082 else if (f->frametype == AST_FRAME_VOICE) 05083 pvt->svoiceformat = f->subclass; 05084 else if (f->frametype == AST_FRAME_VIDEO) 05085 pvt->svideoformat = f->subclass & ~0x1; 05086 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 05087 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 05088 if (fr->transfer) 05089 iax_outputframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 05090 else 05091 iax_outputframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 05092 encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen); 05093 fr->encmethods = pvt->encmethods; 05094 fr->ecx = pvt->ecx; 05095 fr->mydcx = pvt->mydcx; 05096 memcpy(fr->semirand, pvt->semirand, sizeof(fr->semirand)); 05097 } else 05098 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 05099 } 05100 05101 if (now) { 05102 res = send_packet(fr); 05103 } else 05104 res = iax2_transmit(fr); 05105 } else { 05106 if (ast_test_flag(pvt, IAX_TRUNK)) { 05107 iax2_trunk_queue(pvt, fr); 05108 res = 0; 05109 } else if (fr->af.frametype == AST_FRAME_VIDEO) { 05110 /* Video frame have no sequence number */ 05111 fr->oseqno = -1; 05112 fr->iseqno = -1; 05113 vh = (struct ast_iax2_video_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_video_hdr)); 05114 vh->zeros = 0; 05115 vh->callno = htons(0x8000 | fr->callno); 05116 vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); 05117 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); 05118 fr->data = vh; 05119 fr->retries = -1; 05120 res = send_packet(fr); 05121 } else { 05122 /* Mini-frames have no sequence number */ 05123 fr->oseqno = -1; 05124 fr->iseqno = -1; 05125 /* Mini frame will do */ 05126 mh = (struct ast_iax2_mini_hdr *)(fr->af.data.ptr - sizeof(struct ast_iax2_mini_hdr)); 05127 mh->callno = htons(fr->callno); 05128 mh->ts = htons(fr->ts & 0xFFFF); 05129 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); 05130 fr->data = mh; 05131 fr->retries = -1; 05132 if (pvt->transferring == TRANSFER_MEDIAPASS) 05133 fr->transfer = 1; 05134 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 05135 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 05136 encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen); 05137 } else 05138 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 05139 } 05140 res = send_packet(fr); 05141 } 05142 } 05143 return res; 05144 }
static int iax2_sendhtml | ( | struct ast_channel * | c, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3243 of file chan_iax2.c.
References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03244 { 03245 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1); 03246 }
static int iax2_sendimage | ( | struct ast_channel * | c, | |
struct ast_frame * | img | |||
) | [static] |
Definition at line 3238 of file chan_iax2.c.
References AST_FRAME_IMAGE, ast_frame::data, ast_frame::datalen, ast_frame::ptr, PTR_TO_CALLNO, send_command_locked(), ast_frame::subclass, and ast_channel::tech_pvt.
03239 { 03240 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data.ptr, img->datalen, -1); 03241 }
static int iax2_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 3231 of file chan_iax2.c.
References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03232 { 03233 03234 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT, 03235 0, 0, (unsigned char *)text, strlen(text) + 1, -1); 03236 }
static int iax2_setoption | ( | struct ast_channel * | c, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3948 of file chan_iax2.c.
References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_free, ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, errno, PTR_TO_CALLNO, send_command_locked(), ast_channel::tech_pvt, and wait_for_peercallno().
03949 { 03950 struct ast_option_header *h; 03951 int res; 03952 03953 switch (option) { 03954 case AST_OPTION_TXGAIN: 03955 case AST_OPTION_RXGAIN: 03956 /* these two cannot be sent, because they require a result */ 03957 errno = ENOSYS; 03958 return -1; 03959 default: 03960 { 03961 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03962 struct chan_iax2_pvt *pvt; 03963 03964 ast_mutex_lock(&iaxsl[callno]); 03965 pvt = iaxs[callno]; 03966 03967 if (wait_for_peercallno(pvt)) { 03968 ast_mutex_unlock(&iaxsl[callno]); 03969 return -1; 03970 } 03971 03972 ast_mutex_unlock(&iaxsl[callno]); 03973 03974 if (!(h = ast_malloc(datalen + sizeof(*h)))) { 03975 return -1; 03976 } 03977 03978 h->flag = AST_OPTION_FLAG_REQUEST; 03979 h->option = htons(option); 03980 memcpy(h->data, data, datalen); 03981 res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL, 03982 AST_CONTROL_OPTION, 0, (unsigned char *) h, 03983 datalen + sizeof(*h), -1); 03984 ast_free(h); 03985 return res; 03986 } 03987 } 03988 }
static int iax2_start_transfer | ( | unsigned short | callno0, | |
unsigned short | callno1, | |||
int | mediaonly | |||
) | [static] |
Definition at line 4029 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_random(), ast_set_flag, IAX_CALLENCRYPTED, 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, IAX_NOTRANSFER, send_command(), TRANSFER_BEGIN, and TRANSFER_MBEGIN.
04030 { 04031 int res; 04032 struct iax_ie_data ied0; 04033 struct iax_ie_data ied1; 04034 unsigned int transferid = (unsigned int)ast_random(); 04035 04036 if (IAX_CALLENCRYPTED(iaxs[callno0]) || IAX_CALLENCRYPTED(iaxs[callno1])) { 04037 ast_debug(1, "transfers are not supported for encrypted calls at this time"); 04038 ast_set_flag(iaxs[callno0], IAX_NOTRANSFER); 04039 ast_set_flag(iaxs[callno1], IAX_NOTRANSFER); 04040 return 0; 04041 } 04042 04043 memset(&ied0, 0, sizeof(ied0)); 04044 iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr); 04045 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno); 04046 iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); 04047 04048 memset(&ied1, 0, sizeof(ied1)); 04049 iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr); 04050 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno); 04051 iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); 04052 04053 res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); 04054 if (res) 04055 return -1; 04056 res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); 04057 if (res) 04058 return -1; 04059 iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 04060 iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 04061 return 0; 04062 }
static int iax2_transfer | ( | struct ast_channel * | c, | |
const char * | dest | |||
) | [static] |
Definition at line 4283 of file chan_iax2.c.
References ast_copy_string(), ast_debug, AST_FRAME_IAX, chan_iax2_pvt::callno, context, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, ast_channel::name, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
04284 { 04285 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04286 struct iax_ie_data ied = { "", }; 04287 char tmp[256], *context; 04288 ast_copy_string(tmp, dest, sizeof(tmp)); 04289 context = strchr(tmp, '@'); 04290 if (context) { 04291 *context = '\0'; 04292 context++; 04293 } 04294 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp); 04295 if (context) 04296 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); 04297 ast_debug(1, "Transferring '%s' to '%s'\n", c->name, dest); 04298 return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); 04299 }
static int iax2_transmit | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 3203 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, iax2_trunk_peer::list, sched_lock, iax_frame::sentyet, and signal_condition().
Referenced by iax2_send().
03204 { 03205 /* Lock the queue and place this packet at the end */ 03206 /* By setting this to 0, the network thread will send it for us, and 03207 queue retransmission if necessary */ 03208 fr->sentyet = 0; 03209 AST_LIST_LOCK(&frame_queue); 03210 AST_LIST_INSERT_TAIL(&frame_queue, fr, list); 03211 AST_LIST_UNLOCK(&frame_queue); 03212 /* Wake up the network and scheduler thread */ 03213 if (netthreadid != AST_PTHREADT_NULL) 03214 pthread_kill(netthreadid, SIGURG); 03215 signal_condition(&sched_lock, &sched_cond); 03216 return 0; 03217 }
static int iax2_trunk_expired | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [inline, static] |
Definition at line 7563 of file chan_iax2.c.
References iax2_trunk_peer::trunkact.
Referenced by timing_read().
07564 { 07565 /* Drop when trunk is about 5 seconds idle */ 07566 if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 07567 return 1; 07568 return 0; 07569 }
static int iax2_trunk_queue | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_frame * | fr | |||
) | [static] |
Definition at line 4687 of file chan_iax2.c.
References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_tvnow(), ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, DEFAULT_TRUNKDATA, f, find_tpeer(), globalflags, IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, ast_iax2_meta_trunk_mini::mini, send_trunk(), chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.
Referenced by iax2_send().
04688 { 04689 struct ast_frame *f; 04690 struct iax2_trunk_peer *tpeer; 04691 void *tmp, *ptr; 04692 struct timeval now; 04693 int res; 04694 struct ast_iax2_meta_trunk_entry *met; 04695 struct ast_iax2_meta_trunk_mini *mtm; 04696 04697 f = &fr->af; 04698 tpeer = find_tpeer(&pvt->addr, pvt->sockfd); 04699 if (tpeer) { 04700 if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) { 04701 /* Need to reallocate space */ 04702 if (tpeer->trunkdataalloc < trunkmaxsize) { 04703 if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) { 04704 ast_mutex_unlock(&tpeer->lock); 04705 return -1; 04706 } 04707 04708 tpeer->trunkdataalloc += DEFAULT_TRUNKDATA; 04709 tpeer->trunkdata = tmp; 04710 ast_debug(1, "Expanded trunk '%s:%d' to %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), tpeer->trunkdataalloc); 04711 } else { 04712 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)); 04713 ast_mutex_unlock(&tpeer->lock); 04714 return -1; 04715 } 04716 } 04717 04718 /* Append to meta frame */ 04719 ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen; 04720 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) { 04721 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 04722 mtm->len = htons(f->datalen); 04723 mtm->mini.callno = htons(pvt->callno); 04724 mtm->mini.ts = htons(0xffff & fr->ts); 04725 ptr += sizeof(struct ast_iax2_meta_trunk_mini); 04726 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini); 04727 } else { 04728 met = (struct ast_iax2_meta_trunk_entry *)ptr; 04729 /* Store call number and length in meta header */ 04730 met->callno = htons(pvt->callno); 04731 met->len = htons(f->datalen); 04732 /* Advance pointers/decrease length past trunk entry header */ 04733 ptr += sizeof(struct ast_iax2_meta_trunk_entry); 04734 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry); 04735 } 04736 /* Copy actual trunk data */ 04737 memcpy(ptr, f->data.ptr, f->datalen); 04738 tpeer->trunkdatalen += f->datalen; 04739 04740 tpeer->calls++; 04741 04742 /* track the largest mtu we actually have sent */ 04743 if (tpeer->trunkdatalen + f->datalen + 4 > trunk_maxmtu) 04744 trunk_maxmtu = tpeer->trunkdatalen + f->datalen + 4 ; 04745 04746 /* if we have enough for a full MTU, ship it now without waiting */ 04747 if (global_max_trunk_mtu > 0 && tpeer->trunkdatalen + f->datalen + 4 >= global_max_trunk_mtu) { 04748 now = ast_tvnow(); 04749 res = send_trunk(tpeer, &now); 04750 trunk_untimed ++; 04751 } 04752 04753 ast_mutex_unlock(&tpeer->lock); 04754 } 04755 return 0; 04756 }
static int iax2_vnak | ( | int | callno | ) | [static] |
Definition at line 7481 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_VNAK, and send_command_immediate().
Referenced by socket_process(), and socket_process_meta().
07482 { 07483 return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno); 07484 }
static int iax2_write | ( | struct ast_channel * | c, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 5922 of file chan_iax2.c.
References ast_debug, AST_FRAME_NULL, AST_FRAME_VOICE, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_peer::callno, errno, f, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, PTR_TO_CALLNO, and ast_channel::tech_pvt.
05923 { 05924 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 05925 int res = -1; 05926 ast_mutex_lock(&iaxsl[callno]); 05927 if (iaxs[callno]) { 05928 /* If there's an outstanding error, return failure now */ 05929 if (!iaxs[callno]->error) { 05930 if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) 05931 res = 0; 05932 /* Don't waste bandwidth sending null frames */ 05933 else if (f->frametype == AST_FRAME_NULL) 05934 res = 0; 05935 else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH)) 05936 res = 0; 05937 else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 05938 res = 0; 05939 else 05940 /* Simple, just queue for transmission */ 05941 res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0); 05942 } else { 05943 ast_debug(1, "Write error: %s\n", strerror(errno)); 05944 } 05945 } 05946 /* If it's already gone, just return */ 05947 ast_mutex_unlock(&iaxsl[callno]); 05948 return res; 05949 }
static int iax_check_version | ( | char * | dev | ) | [static] |
Definition at line 2152 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_iax2_firmware_header::devname, iax_firmware::fwh, iax2_trunk_peer::list, and ast_iax2_firmware_header::version.
Referenced by update_registry().
02153 { 02154 int res = 0; 02155 struct iax_firmware *cur = NULL; 02156 02157 if (ast_strlen_zero(dev)) 02158 return 0; 02159 02160 AST_LIST_LOCK(&firmwares); 02161 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02162 if (!strcmp(dev, (char *)cur->fwh->devname)) { 02163 res = ntohs(cur->fwh->version); 02164 break; 02165 } 02166 } 02167 AST_LIST_UNLOCK(&firmwares); 02168 02169 return res; 02170 }
static void iax_debug_output | ( | const char * | data | ) | [static] |
Definition at line 896 of file chan_iax2.c.
References ast_verbose.
Referenced by load_module().
00897 { 00898 if (iaxdebug) 00899 ast_verbose("%s", data); 00900 }
static void iax_error_output | ( | const char * | data | ) | [static] |
Definition at line 902 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00903 { 00904 ast_log(LOG_WARNING, "%s", data); 00905 }
static int iax_firmware_append | ( | struct iax_ie_data * | ied, | |
const unsigned char * | dev, | |||
unsigned int | desc | |||
) | [static] |
Definition at line 2172 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, iax_firmware::fwh, iax_ie_append(), iax_ie_append_int(), iax_ie_append_raw(), IAX_IE_FWBLOCKDATA, IAX_IE_FWBLOCKDESC, and iax2_trunk_peer::list.
Referenced by socket_process().
02173 { 02174 int res = -1; 02175 unsigned int bs = desc & 0xff; 02176 unsigned int start = (desc >> 8) & 0xffffff; 02177 unsigned int bytes; 02178 struct iax_firmware *cur; 02179 02180 if (ast_strlen_zero((char *)dev) || !bs) 02181 return -1; 02182 02183 start *= bs; 02184 02185 AST_LIST_LOCK(&firmwares); 02186 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02187 if (strcmp((char *)dev, (char *)cur->fwh->devname)) 02188 continue; 02189 iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc); 02190 if (start < ntohl(cur->fwh->datalen)) { 02191 bytes = ntohl(cur->fwh->datalen) - start; 02192 if (bytes > bs) 02193 bytes = bs; 02194 iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes); 02195 } else { 02196 bytes = 0; 02197 iax_ie_append(ied, IAX_IE_FWBLOCKDATA); 02198 } 02199 if (bytes == bs) 02200 res = 0; 02201 else 02202 res = 1; 02203 break; 02204 } 02205 AST_LIST_UNLOCK(&firmwares); 02206 02207 return res; 02208 }
static void iax_outputframe | ( | struct iax_frame * | f, | |
struct ast_iax2_full_hdr * | fhi, | |||
int | rx, | |||
struct sockaddr_in * | sin, | |||
int | datalen | |||
) | [static] |
Definition at line 879 of file chan_iax2.c.
References debugaddr, f, and iax_showframe().
Referenced by iax2_send(), raw_hangup(), and socket_process().
00880 { 00881 if (iaxdebug || 00882 (sin && debugaddr.sin_addr.s_addr && 00883 (!ntohs(debugaddr.sin_port) || 00884 debugaddr.sin_port == sin->sin_port) && 00885 debugaddr.sin_addr.s_addr == sin->sin_addr.s_addr)) { 00886 if (iaxdebug) { 00887 iax_showframe(f, fhi, rx, sin, datalen); 00888 } else { 00889 iaxdebug = 1; 00890 iax_showframe(f, fhi, rx, sin, datalen); 00891 iaxdebug = 0; 00892 } 00893 } 00894 }
static int iax_park | ( | struct ast_channel * | chan1, | |
struct ast_channel * | chan2 | |||
) | [static] |
Definition at line 7725 of file chan_iax2.c.
References ast_channel::accountcode, ast_channel::amaflags, ast_calloc, ast_channel_alloc(), ast_channel_masquerade(), ast_copy_string(), ast_do_masquerade(), ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached_background, AST_STATE_DOWN, ast_channel::context, ast_channel::exten, iax_park_thread(), LOG_WARNING, ast_channel::name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by socket_process().
07726 { 07727 struct iax_dual *d; 07728 struct ast_channel *chan1m, *chan2m; 07729 pthread_t th; 07730 chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 07731 chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name); 07732 if (chan2m && chan1m) { 07733 /* Make formats okay */ 07734 chan1m->readformat = chan1->readformat; 07735 chan1m->writeformat = chan1->writeformat; 07736 ast_channel_masquerade(chan1m, chan1); 07737 /* Setup the extensions and such */ 07738 ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context)); 07739 ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten)); 07740 chan1m->priority = chan1->priority; 07741 07742 /* We make a clone of the peer channel too, so we can play 07743 back the announcement */ 07744 /* Make formats okay */ 07745 chan2m->readformat = chan2->readformat; 07746 chan2m->writeformat = chan2->writeformat; 07747 ast_channel_masquerade(chan2m, chan2); 07748 /* Setup the extensions and such */ 07749 ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context)); 07750 ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten)); 07751 chan2m->priority = chan2->priority; 07752 if (ast_do_masquerade(chan2m)) { 07753 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 07754 ast_hangup(chan2m); 07755 return -1; 07756 } 07757 } else { 07758 if (chan1m) 07759 ast_hangup(chan1m); 07760 if (chan2m) 07761 ast_hangup(chan2m); 07762 return -1; 07763 } 07764 if ((d = ast_calloc(1, sizeof(*d)))) { 07765 d->chan1 = chan1m; 07766 d->chan2 = chan2m; 07767 if (!ast_pthread_create_detached_background(&th, NULL, iax_park_thread, d)) { 07768 return 0; 07769 } 07770 ast_free(d); 07771 } 07772 return -1; 07773 }
static void* iax_park_thread | ( | void * | stuff | ) | [static] |
Definition at line 7705 of file chan_iax2.c.
References ast_free, ast_frfree, ast_hangup(), ast_log(), ast_park_call(), ast_read(), iax_dual::chan1, iax_dual::chan2, ext, f, and LOG_NOTICE.
Referenced by iax_park().
07706 { 07707 struct ast_channel *chan1, *chan2; 07708 struct iax_dual *d; 07709 struct ast_frame *f; 07710 int ext; 07711 int res; 07712 d = stuff; 07713 chan1 = d->chan1; 07714 chan2 = d->chan2; 07715 ast_free(d); 07716 f = ast_read(chan1); 07717 if (f) 07718 ast_frfree(f); 07719 res = ast_park_call(chan1, chan2, 0, &ext); 07720 ast_hangup(chan2); 07721 ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext); 07722 return NULL; 07723 }
Definition at line 1570 of file chan_iax2.c.
References iax_frame::af, iax_frame::afdatalen, iax_frame::cacheable, ast_frame::datalen, DIRECTION_INGRESS, iax_frame_new(), and iax_frame_wrap().
Referenced by socket_process(), and socket_process_meta().
01571 { 01572 struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable); 01573 if (new) { 01574 size_t afdatalen = new->afdatalen; 01575 memcpy(new, fr, sizeof(*new)); 01576 iax_frame_wrap(new, &fr->af); 01577 new->afdatalen = afdatalen; 01578 new->data = NULL; 01579 new->datalen = 0; 01580 new->direction = DIRECTION_INGRESS; 01581 new->retrans = -1; 01582 } 01583 return new; 01584 }
static void insert_idle_thread | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 1082 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, IAX_THREAD_TYPE_DYNAMIC, iax2_trunk_peer::list, and thread.
Referenced by iax2_process_thread().
01083 { 01084 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) { 01085 AST_LIST_LOCK(&dynamic_list); 01086 AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); 01087 AST_LIST_UNLOCK(&dynamic_list); 01088 } else { 01089 AST_LIST_LOCK(&idle_list); 01090 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 01091 AST_LIST_UNLOCK(&idle_list); 01092 } 01093 01094 return; 01095 }
static void jb_debug_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 931 of file chan_iax2.c.
References ast_verbose.
Referenced by handle_cli_iax2_set_debug_jb().
00932 { 00933 va_list args; 00934 char buf[1024]; 00935 00936 va_start(args, fmt); 00937 vsnprintf(buf, sizeof(buf), fmt, args); 00938 va_end(args); 00939 00940 ast_verbose("%s", buf); 00941 }
static void jb_error_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 907 of file chan_iax2.c.
References ast_log(), and LOG_ERROR.
Referenced by handle_cli_iax2_set_debug_jb(), and load_module().
00908 { 00909 va_list args; 00910 char buf[1024]; 00911 00912 va_start(args, fmt); 00913 vsnprintf(buf, sizeof(buf), fmt, args); 00914 va_end(args); 00915 00916 ast_log(LOG_ERROR, "%s", buf); 00917 }
static void jb_warning_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 919 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by handle_cli_iax2_set_debug_jb(), and load_module().
00920 { 00921 va_list args; 00922 char buf[1024]; 00923 00924 va_start(args, fmt); 00925 vsnprintf(buf, sizeof(buf), fmt, args); 00926 va_end(args); 00927 00928 ast_log(LOG_WARNING, "%s", buf); 00929 }
static int load_module | ( | void | ) | [static] |
Load IAX2 module, load configuraiton ---.
Definition at line 12416 of file chan_iax2.c.
References __unload_module(), ao2_callback, ao2_container_alloc, ao2_ref, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_realtime_require_field(), ast_register_application, ast_register_switch(), ast_timer_open(), ast_timer_set_rate(), ast_verb, cli_iax2, config, iax2_registry::entry, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, iax2_do_register(), iax2_poke_peer_cb(), iax2_prov_app(), iax2_switch, iax2_tech, iax_debug_output(), iax_error_output(), IAX_MAX_CALLS, iax_peercallno_pvts, iax_provision_reload(), iax_set_error(), iax_set_output(), iax_transfercallno_pvts, iaxpeer_function, iaxvar_function, io, io_context_create(), io_context_destroy(), jb_error_output(), jb_setoutput(), jb_warning_output(), LOG_ERROR, manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, netsock, outsock, papp, pdescrip, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), psyn, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), RQ_CHAR, RQ_UINTEGER2, sched, sched_context_create(), sched_context_destroy(), SENTINEL, set_config(), start_network_thread(), timer, transfercallno_pvt_cmp_cb(), transfercallno_pvt_hash_cb(), user_cmp_cb(), and user_hash_cb().
12417 { 12418 char *config = "iax.conf"; 12419 int x = 0; 12420 struct iax2_registry *reg = NULL; 12421 12422 peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb); 12423 if (!peers) 12424 return AST_MODULE_LOAD_FAILURE; 12425 users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb); 12426 if (!users) { 12427 ao2_ref(peers, -1); 12428 return AST_MODULE_LOAD_FAILURE; 12429 } 12430 iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb); 12431 if (!iax_peercallno_pvts) { 12432 ao2_ref(peers, -1); 12433 ao2_ref(users, -1); 12434 return AST_MODULE_LOAD_FAILURE; 12435 } 12436 iax_transfercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, transfercallno_pvt_hash_cb, transfercallno_pvt_cmp_cb); 12437 if (!iax_transfercallno_pvts) { 12438 ao2_ref(peers, -1); 12439 ao2_ref(users, -1); 12440 ao2_ref(iax_peercallno_pvts, -1); 12441 return AST_MODULE_LOAD_FAILURE; 12442 } 12443 ast_custom_function_register(&iaxpeer_function); 12444 ast_custom_function_register(&iaxvar_function); 12445 12446 iax_set_output(iax_debug_output); 12447 iax_set_error(iax_error_output); 12448 jb_setoutput(jb_error_output, jb_warning_output, NULL); 12449 12450 memset(iaxs, 0, sizeof(iaxs)); 12451 12452 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 12453 ast_mutex_init(&iaxsl[x]); 12454 } 12455 12456 ast_cond_init(&sched_cond, NULL); 12457 12458 if (!(sched = sched_context_create())) { 12459 ast_log(LOG_ERROR, "Failed to create scheduler context\n"); 12460 return AST_MODULE_LOAD_FAILURE; 12461 } 12462 12463 if (!(io = io_context_create())) { 12464 ast_log(LOG_ERROR, "Failed to create I/O context\n"); 12465 sched_context_destroy(sched); 12466 return AST_MODULE_LOAD_FAILURE; 12467 } 12468 12469 if (!(netsock = ast_netsock_list_alloc())) { 12470 ast_log(LOG_ERROR, "Failed to create netsock list\n"); 12471 io_context_destroy(io); 12472 sched_context_destroy(sched); 12473 return AST_MODULE_LOAD_FAILURE; 12474 } 12475 ast_netsock_init(netsock); 12476 12477 outsock = ast_netsock_list_alloc(); 12478 if (!outsock) { 12479 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 12480 io_context_destroy(io); 12481 sched_context_destroy(sched); 12482 return AST_MODULE_LOAD_FAILURE; 12483 } 12484 ast_netsock_init(outsock); 12485 12486 ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 12487 12488 ast_register_application(papp, iax2_prov_app, psyn, pdescrip); 12489 12490 ast_manager_register( "IAXpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peers, "List IAX Peers" ); 12491 ast_manager_register( "IAXpeerlist", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peer_list, "List IAX Peers" ); 12492 ast_manager_register( "IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats, "Show IAX Netstats" ); 12493 12494 if ((timer = ast_timer_open())) { 12495 ast_timer_set_rate(timer, trunkfreq); 12496 } 12497 12498 if (set_config(config, 0) == -1) { 12499 return AST_MODULE_LOAD_DECLINE; 12500 } 12501 12502 if (ast_channel_register(&iax2_tech)) { 12503 ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2"); 12504 __unload_module(); 12505 return AST_MODULE_LOAD_FAILURE; 12506 } 12507 12508 if (ast_register_switch(&iax2_switch)) 12509 ast_log(LOG_ERROR, "Unable to register IAX switch\n"); 12510 12511 if (start_network_thread()) { 12512 ast_log(LOG_ERROR, "Unable to start network thread\n"); 12513 __unload_module(); 12514 return AST_MODULE_LOAD_FAILURE; 12515 } else 12516 ast_verb(2, "IAX Ready and Listening\n"); 12517 12518 AST_LIST_LOCK(®istrations); 12519 AST_LIST_TRAVERSE(®istrations, reg, entry) 12520 iax2_do_register(reg); 12521 AST_LIST_UNLOCK(®istrations); 12522 12523 ao2_callback(peers, 0, peer_set_sock_cb, NULL); 12524 ao2_callback(peers, 0, iax2_poke_peer_cb, NULL); 12525 12526 12527 reload_firmware(0); 12528 iax_provision_reload(0); 12529 12530 ast_realtime_require_field("iaxpeers", "name", RQ_CHAR, 10, "ipaddr", RQ_CHAR, 15, "port", RQ_UINTEGER2, 5, "regseconds", RQ_UINTEGER2, 6, SENTINEL); 12531 12532 return AST_MODULE_LOAD_SUCCESS; 12533 }
static void lock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 4064 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), and DEADLOCK_AVOIDANCE.
Referenced by iax2_bridge().
04065 { 04066 ast_mutex_lock(&iaxsl[callno0]); 04067 while (ast_mutex_trylock(&iaxsl[callno1])) { 04068 DEADLOCK_AVOIDANCE(&iaxsl[callno0]); 04069 } 04070 }
static void log_jitterstats | ( | unsigned short | callno | ) | [static] |
Definition at line 7848 of file chan_iax2.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, jb_info::current, EVENT_FLAG_REPORTING, jb_info::frames_dropped, jb_info::frames_in, jb_info::frames_lost, jb_info::frames_ooo, IAX_USEJITTERBUF, ast_channel::jb, jb_getinfo(), jb_info::jitter, jb_info::losspct, manager_event, and jb_info::min.
Referenced by socket_process().
07849 { 07850 int localjitter = -1, localdelay = 0, locallost = -1, locallosspct = -1, localdropped = 0, localooo = -1, localpackets = -1; 07851 jb_info jbinfo; 07852 07853 ast_mutex_lock(&iaxsl[callno]); 07854 if (iaxs[callno] && iaxs[callno]->owner && iaxs[callno]->owner->name) { 07855 if(ast_test_flag(iaxs[callno], IAX_USEJITTERBUF)) { 07856 jb_getinfo(iaxs[callno]->jb, &jbinfo); 07857 localjitter = jbinfo.jitter; 07858 localdelay = jbinfo.current - jbinfo.min; 07859 locallost = jbinfo.frames_lost; 07860 locallosspct = jbinfo.losspct/1000; 07861 localdropped = jbinfo.frames_dropped; 07862 localooo = jbinfo.frames_ooo; 07863 localpackets = jbinfo.frames_in; 07864 } 07865 ast_debug(3, "JB STATS:%s ping=%d ljitterms=%d ljbdelayms=%d ltotlost=%d lrecentlosspct=%d ldropped=%d looo=%d lrecvd=%d rjitterms=%d rjbdelayms=%d rtotlost=%d rrecentlosspct=%d rdropped=%d rooo=%d rrecvd=%d\n", 07866 iaxs[callno]->owner->name, 07867 iaxs[callno]->pingtime, 07868 localjitter, 07869 localdelay, 07870 locallost, 07871 locallosspct, 07872 localdropped, 07873 localooo, 07874 localpackets, 07875 iaxs[callno]->remote_rr.jitter, 07876 iaxs[callno]->remote_rr.delay, 07877 iaxs[callno]->remote_rr.losscnt, 07878 iaxs[callno]->remote_rr.losspct/1000, 07879 iaxs[callno]->remote_rr.dropped, 07880 iaxs[callno]->remote_rr.ooo, 07881 iaxs[callno]->remote_rr.packets); 07882 manager_event(EVENT_FLAG_REPORTING, "JitterBufStats", "Owner: %s\r\nPing: %d\r\nLocalJitter: %d\r\nLocalJBDelay: %d\r\nLocalTotalLost: %d\r\nLocalLossPercent: %d\r\nLocalDropped: %d\r\nLocalooo: %d\r\nLocalReceived: %d\r\nRemoteJitter: %d\r\nRemoteJBDelay: %d\r\nRemoteTotalLost: %d\r\nRemoteLossPercent: %d\r\nRemoteDropped: %d\r\nRemoteooo: %d\r\nRemoteReceived: %d\r\n", 07883 iaxs[callno]->owner->name, 07884 iaxs[callno]->pingtime, 07885 localjitter, 07886 localdelay, 07887 locallost, 07888 locallosspct, 07889 localdropped, 07890 localooo, 07891 localpackets, 07892 iaxs[callno]->remote_rr.jitter, 07893 iaxs[callno]->remote_rr.delay, 07894 iaxs[callno]->remote_rr.losscnt, 07895 iaxs[callno]->remote_rr.losspct/1000, 07896 iaxs[callno]->remote_rr.dropped, 07897 iaxs[callno]->remote_rr.ooo, 07898 iaxs[callno]->remote_rr.packets); 07899 } 07900 ast_mutex_unlock(&iaxsl[callno]); 07901 }
static int make_trunk | ( | unsigned short | callno, | |
int | locked | |||
) | [static] |
Definition at line 1641 of file chan_iax2.c.
References ARRAY_LEN, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, ast_tvnow(), iax2_sched_add(), LOG_WARNING, MIN_REUSE_TIME, sched, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().
Referenced by iax2_request(), and socket_process().
01642 { 01643 int x; 01644 int res= 0; 01645 struct timeval now = ast_tvnow(); 01646 if (iaxs[callno]->oseqno) { 01647 ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n"); 01648 return -1; 01649 } 01650 if (callno & TRUNK_CALL_START) { 01651 ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno); 01652 return -1; 01653 } 01654 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01655 ast_mutex_lock(&iaxsl[x]); 01656 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01657 /*! 01658 * \note We delete these before switching the slot, because if 01659 * they fire in the meantime, they will generate a warning. 01660 */ 01661 AST_SCHED_DEL(sched, iaxs[callno]->pingid); 01662 AST_SCHED_DEL(sched, iaxs[callno]->lagid); 01663 iaxs[x] = iaxs[callno]; 01664 iaxs[x]->callno = x; 01665 iaxs[callno] = NULL; 01666 /* Update the two timers that should have been started */ 01667 iaxs[x]->pingid = iax2_sched_add(sched, 01668 ping_time * 1000, send_ping, (void *)(long)x); 01669 iaxs[x]->lagid = iax2_sched_add(sched, 01670 lagrq_time * 1000, send_lagrq, (void *)(long)x); 01671 if (locked) 01672 ast_mutex_unlock(&iaxsl[callno]); 01673 res = x; 01674 if (!locked) 01675 ast_mutex_unlock(&iaxsl[x]); 01676 break; 01677 } 01678 ast_mutex_unlock(&iaxsl[x]); 01679 } 01680 if (x >= ARRAY_LEN(iaxs) - 1) { 01681 ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n"); 01682 return -1; 01683 } 01684 ast_debug(1, "Made call %d into trunk call %d\n", callno, x); 01685 /* We move this call from a non-trunked to a trunked call */ 01686 update_max_trunk(); 01687 update_max_nontrunk(); 01688 return res; 01689 }
static int manager_iax2_show_netstats | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5508 of file chan_iax2.c.
References ast_cli_netstats(), astman_append(), RESULT_SUCCESS, and s.
Referenced by load_module().
05509 { 05510 ast_cli_netstats(s, -1, 0); 05511 astman_append(s, "\r\n"); 05512 return RESULT_SUCCESS; 05513 }
static int manager_iax2_show_peer_list | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
callback to display iax peers in manager format
Definition at line 5560 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next, ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), IAX_DYNAMIC, iax2_peer::mask, iax2_peer::name, peer_status(), peer_unref(), RESULT_SUCCESS, s, status, and iax2_peer::username.
Referenced by load_module().
05561 { 05562 struct iax2_peer *peer = NULL; 05563 int peer_count = 0; 05564 char nm[20]; 05565 char status[20]; 05566 const char *id = astman_get_header(m,"ActionID"); 05567 char idtext[256] = ""; 05568 struct ao2_iterator i; 05569 05570 if (!ast_strlen_zero(id)) 05571 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05572 05573 astman_append(s, "Response: Success\r\n%sMessage: IAX Peer status list will follow\r\n\r\n", idtext); 05574 05575 05576 i = ao2_iterator_init(peers, 0); 05577 for (peer = ao2_iterator_next(&i); peer; peer_unref(peer), peer = ao2_iterator_next(&i)) { 05578 05579 astman_append(s, "Event: PeerEntry\r\n%sChanneltype: IAX\r\n", idtext); 05580 if (!ast_strlen_zero(peer->username)) { 05581 astman_append(s, "ObjectName: %s\r\nObjectUsername: %s\r\n", peer->name, peer->username); 05582 } else { 05583 astman_append(s, "ObjectName: %s\r\n", peer->name); 05584 } 05585 astman_append(s, "ChanObjectType: peer\r\n"); 05586 astman_append(s, "IPaddress: %s\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-"); 05587 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 05588 astman_append(s, "Mask: %s\r\n", nm); 05589 astman_append(s, "Port: %d\r\n", ntohs(peer->addr.sin_port)); 05590 astman_append(s, "Dynamic: %s\r\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No"); 05591 peer_status(peer, status, sizeof(status)); 05592 astman_append(s, "Status: %s\r\n\r\n", status); 05593 peer_count++; 05594 } 05595 05596 astman_append(s, "Event: PeerlistComplete\r\n%sListItems: %d\r\n\r\n", idtext, peer_count); 05597 return RESULT_SUCCESS; 05598 }
static int manager_iax2_show_peers | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
callback to display iax peers in manager
Definition at line 5547 of file chan_iax2.c.
References __iax2_show_peers(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), and s.
Referenced by load_module().
05548 { 05549 char *a[] = { "iax2", "show", "users" }; 05550 const char *id = astman_get_header(m,"ActionID"); 05551 char idtext[256] = ""; 05552 05553 if (!ast_strlen_zero(id)) 05554 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05555 astman_send_ack(s, m, "Peer status list will follow"); 05556 return __iax2_show_peers(1, -1, s, 3, a ); 05557 }
static int match | ( | struct sockaddr_in * | sin, | |
unsigned short | callno, | |||
unsigned short | dcallno, | |||
const struct chan_iax2_pvt * | cur, | |||
int | check_dcallno | |||
) | [static] |
Definition at line 1590 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 __ao2_callback(), __find_callno(), ast_parse_device_state(), check_blacklist(), find_command(), handle_updates(), lua_find_extension(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and transfercallno_pvt_cmp_cb().
01591 { 01592 if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && 01593 (cur->addr.sin_port == sin->sin_port)) { 01594 /* This is the main host */ 01595 if ( (cur->peercallno == 0 || cur->peercallno == callno) && 01596 (check_dcallno ? dcallno == cur->callno : 1) ) { 01597 /* That's us. Be sure we keep track of the peer call number */ 01598 return 1; 01599 } 01600 } 01601 if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && 01602 (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { 01603 /* We're transferring */ 01604 if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno)) 01605 return 1; 01606 } 01607 return 0; 01608 }
static void memcpy_decrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
ast_aes_decrypt_key * | dcx | |||
) | [static] |
Definition at line 4786 of file chan_iax2.c.
References ast_aes_decrypt, ast_log(), and LOG_WARNING.
Referenced by decode_frame().
04787 { 04788 #if 0 04789 /* Debug with "fake encryption" */ 04790 int x; 04791 if (len % 16) 04792 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04793 for (x=0;x<len;x++) 04794 dst[x] = src[x] ^ 0xff; 04795 #else 04796 unsigned char lastblock[16] = { 0 }; 04797 int x; 04798 while(len > 0) { 04799 ast_aes_decrypt(src, dst, dcx); 04800 for (x=0;x<16;x++) 04801 dst[x] ^= lastblock[x]; 04802 memcpy(lastblock, src, sizeof(lastblock)); 04803 dst += 16; 04804 src += 16; 04805 len -= 16; 04806 } 04807 #endif 04808 }
static void memcpy_encrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
ast_aes_encrypt_key * | ecx | |||
) | [static] |
Definition at line 4810 of file chan_iax2.c.
References ast_aes_encrypt, ast_log(), and LOG_WARNING.
Referenced by encrypt_frame().
04811 { 04812 #if 0 04813 /* Debug with "fake encryption" */ 04814 int x; 04815 if (len % 16) 04816 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04817 for (x=0;x<len;x++) 04818 dst[x] = src[x] ^ 0xff; 04819 #else 04820 unsigned char curblock[16] = { 0 }; 04821 int x; 04822 while(len > 0) { 04823 for (x=0;x<16;x++) 04824 curblock[x] ^= src[x]; 04825 ast_aes_encrypt(curblock, dst, ecx); 04826 memcpy(curblock, dst, sizeof(curblock)); 04827 dst += 16; 04828 src += 16; 04829 len -= 16; 04830 } 04831 #endif 04832 }
static void merge_encryption | ( | struct chan_iax2_pvt * | p, | |
unsigned int | enc | |||
) | [static] |
Definition at line 6258 of file chan_iax2.c.
References chan_iax2_pvt::encmethods, IAX_ENCRYPT_AES128, IAX_ENCRYPT_KEYROTATE, and chan_iax2_pvt::keyrotateid.
Referenced by authenticate_reply(), and socket_process().
06259 { 06260 /* Select exactly one common encryption if there are any */ 06261 p->encmethods &= enc; 06262 if (p->encmethods) { 06263 if (!(p->encmethods & IAX_ENCRYPT_KEYROTATE)){ /* if key rotation is not supported, turn off keyrotation. */ 06264 p->keyrotateid = -2; 06265 } 06266 if (p->encmethods & IAX_ENCRYPT_AES128) 06267 p->encmethods = IAX_ENCRYPT_AES128; 06268 else 06269 p->encmethods = 0; 06270 } 06271 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 1016 of file chan_iax2.c.
01017 { 01018 /* The MWI subscriptions exist just so the core knows we care about those 01019 * mailboxes. However, we just grab the events out of the cache when it 01020 * is time to send MWI, since it is only sent with a REGACK. */ 01021 }
static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 10383 of file chan_iax2.c.
References ast_debug, ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_mutex_trylock(), ast_mutex_unlock(), ast_timer_fd(), attempt_transmit(), f, iax2_sched_add(), iax_frame_free(), io, iax_frame::list, sched, send_packet(), timer, and timing_read().
Referenced by start_network_thread().
10384 { 10385 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 10386 from the network, and queue them for delivery to the channels */ 10387 int res, count, wakeup; 10388 struct iax_frame *f; 10389 10390 if (timer) 10391 ast_io_add(io, ast_timer_fd(timer), timing_read, AST_IO_IN | AST_IO_PRI, NULL); 10392 10393 for(;;) { 10394 pthread_testcancel(); 10395 10396 /* Go through the queue, sending messages which have not yet been 10397 sent, and scheduling retransmissions if appropriate */ 10398 AST_LIST_LOCK(&frame_queue); 10399 count = 0; 10400 wakeup = -1; 10401 AST_LIST_TRAVERSE_SAFE_BEGIN(&frame_queue, f, list) { 10402 if (f->sentyet) 10403 continue; 10404 10405 /* Try to lock the pvt, if we can't... don't fret - defer it till later */ 10406 if (ast_mutex_trylock(&iaxsl[f->callno])) { 10407 wakeup = 1; 10408 continue; 10409 } 10410 10411 f->sentyet = 1; 10412 10413 if (iaxs[f->callno]) { 10414 send_packet(f); 10415 count++; 10416 } 10417 10418 ast_mutex_unlock(&iaxsl[f->callno]); 10419 10420 if (f->retries < 0) { 10421 /* This is not supposed to be retransmitted */ 10422 AST_LIST_REMOVE_CURRENT(list); 10423 /* Free the iax frame */ 10424 iax_frame_free(f); 10425 } else { 10426 /* We need reliable delivery. Schedule a retransmission */ 10427 f->retries++; 10428 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 10429 } 10430 } 10431 AST_LIST_TRAVERSE_SAFE_END; 10432 AST_LIST_UNLOCK(&frame_queue); 10433 10434 pthread_testcancel(); 10435 if (count >= 20) 10436 ast_debug(1, "chan_iax2: Sent %d queued outbound frames all at once\n", count); 10437 10438 /* Now do the IO, and run scheduled tasks */ 10439 res = ast_io_wait(io, wakeup); 10440 if (res >= 0) { 10441 if (res >= 20) 10442 ast_debug(1, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res); 10443 } 10444 } 10445 return NULL; 10446 }
static struct chan_iax2_pvt* new_iax | ( | struct sockaddr_in * | sin, | |
const char * | host | |||
) | [static] |
Definition at line 1531 of file chan_iax2.c.
References ao2_alloc, ao2_ref, AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, ast_string_field_set, exten, jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, prefs, pvt_destructor(), jb_conf::resync_threshold, and jb_conf::target_extra.
Referenced by __find_callno().
01532 { 01533 struct chan_iax2_pvt *tmp; 01534 jb_conf jbconf; 01535 01536 if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) { 01537 return NULL; 01538 } 01539 01540 if (ast_string_field_init(tmp, 32)) { 01541 ao2_ref(tmp, -1); 01542 tmp = NULL; 01543 return NULL; 01544 } 01545 01546 tmp->prefs = prefs; 01547 tmp->pingid = -1; 01548 tmp->lagid = -1; 01549 tmp->autoid = -1; 01550 tmp->authid = -1; 01551 tmp->initid = -1; 01552 tmp->keyrotateid = -1; 01553 01554 ast_string_field_set(tmp,exten, "s"); 01555 ast_string_field_set(tmp,host, host); 01556 01557 tmp->jb = jb_new(); 01558 tmp->jbid = -1; 01559 jbconf.max_jitterbuf = maxjitterbuffer; 01560 jbconf.resync_threshold = resyncthreshold; 01561 jbconf.max_contig_interp = maxjitterinterps; 01562 jbconf.target_extra = jittertargetextra; 01563 jb_setconf(tmp->jb,&jbconf); 01564 01565 AST_LIST_HEAD_INIT_NOLOCK(&tmp->dpentries); 01566 01567 return tmp; 01568 }
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 3650 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().
03651 { 03652 if (ast_strlen_zero(data)) 03653 return; 03654 03655 pds->peer = strsep(&data, "/"); 03656 pds->exten = strsep(&data, "/"); 03657 pds->options = data; 03658 03659 if (pds->exten) { 03660 data = pds->exten; 03661 pds->exten = strsep(&data, "@"); 03662 pds->context = data; 03663 } 03664 03665 if (strchr(pds->peer, '@')) { 03666 data = pds->peer; 03667 pds->username = strsep(&data, "@"); 03668 pds->peer = data; 03669 } 03670 03671 if (pds->username) { 03672 data = pds->username; 03673 pds->username = strsep(&data, ":"); 03674 pds->password = data; 03675 } 03676 03677 data = pds->peer; 03678 pds->peer = strsep(&data, ":"); 03679 pds->port = data; 03680 03681 /* check for a key name wrapped in [] in the secret position, if found, 03682 move it to the key field instead 03683 */ 03684 if (pds->password && (pds->password[0] == '[')) { 03685 pds->key = ast_strip_quoted(pds->password, "[", "]"); 03686 pds->password = NULL; 03687 } 03688 }
static int peer_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1332 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, and iax2_peer::name.
Referenced by load_module().
01333 { 01334 struct iax2_peer *peer = obj, *peer2 = arg; 01335 01336 return !strcmp(peer->name, peer2->name) ? CMP_MATCH | CMP_STOP : 0; 01337 }
static int peer_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11077 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
11078 { 11079 struct iax2_peer *peer = obj; 11080 11081 ast_set_flag(peer, IAX_DELME); 11082 11083 return 0; 11084 }
static void peer_destructor | ( | void * | obj | ) | [static] |
Definition at line 10599 of file chan_iax2.c.
References ast_dnsmgr_release(), ast_event_unsubscribe(), ast_free_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_free_memory, iax2_peer::callno, iax2_peer::dnsmgr, iax2_peer::ha, iax2_destroy(), iax2_peer::mwi_event_sub, and register_peer_exten().
Referenced by build_peer().
10600 { 10601 struct iax2_peer *peer = obj; 10602 int callno = peer->callno; 10603 10604 ast_free_ha(peer->ha); 10605 10606 if (callno > 0) { 10607 ast_mutex_lock(&iaxsl[callno]); 10608 iax2_destroy(callno); 10609 ast_mutex_unlock(&iaxsl[callno]); 10610 } 10611 10612 register_peer_exten(peer, 0); 10613 10614 if (peer->dnsmgr) 10615 ast_dnsmgr_release(peer->dnsmgr); 10616 10617 if (peer->mwi_event_sub) 10618 ast_event_unsubscribe(peer->mwi_event_sub); 10619 10620 ast_string_field_free_memory(peer); 10621 }
static int peer_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1322 of file chan_iax2.c.
References ast_str_hash(), and iax2_peer::name.
Referenced by load_module().
01323 { 01324 const struct iax2_peer *peer = obj; 01325 01326 return ast_str_hash(peer->name); 01327 }
Definition at line 1379 of file chan_iax2.c.
References ao2_ref.
Referenced by __iax2_poke_noanswer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_unregister(), iax2_poke_peer(), reg_source_db(), socket_process(), and update_registry().
01380 { 01381 ao2_ref(peer, +1); 01382 return peer; 01383 }
static int peer_set_sock_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 12370 of file chan_iax2.c.
References iax2_peer::sockfd.
Referenced by load_module().
12371 { 12372 struct iax2_peer *peer = obj; 12373 12374 if (peer->sockfd < 0) 12375 peer->sockfd = defaultsockfd; 12376 12377 return 0; 12378 }
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 10527 of file chan_iax2.c.
References ast_debug, ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, io, LOG_WARNING, iax2_peer::name, netsock, outsock, qos, socket_read(), iax2_peer::sockfd, and strsep().
Referenced by build_peer().
10528 { 10529 struct sockaddr_in sin; 10530 int nonlocal = 1; 10531 int port = IAX_DEFAULT_PORTNO; 10532 int sockfd = defaultsockfd; 10533 char *tmp; 10534 char *addr; 10535 char *portstr; 10536 10537 if (!(tmp = ast_strdupa(srcaddr))) 10538 return -1; 10539 10540 addr = strsep(&tmp, ":"); 10541 portstr = tmp; 10542 10543 if (portstr) { 10544 port = atoi(portstr); 10545 if (port < 1) 10546 port = IAX_DEFAULT_PORTNO; 10547 } 10548 10549 if (!ast_get_ip(&sin, addr)) { 10550 struct ast_netsock *sock; 10551 int res; 10552 10553 sin.sin_port = 0; 10554 sin.sin_family = AF_INET; 10555 res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin)); 10556 if (res == 0) { 10557 /* ip address valid. */ 10558 sin.sin_port = htons(port); 10559 if (!(sock = ast_netsock_find(netsock, &sin))) 10560 sock = ast_netsock_find(outsock, &sin); 10561 if (sock) { 10562 sockfd = ast_netsock_sockfd(sock); 10563 nonlocal = 0; 10564 } else { 10565 unsigned int orig_saddr = sin.sin_addr.s_addr; 10566 /* INADDR_ANY matches anyway! */ 10567 sin.sin_addr.s_addr = INADDR_ANY; 10568 if (ast_netsock_find(netsock, &sin)) { 10569 sin.sin_addr.s_addr = orig_saddr; 10570 sock = ast_netsock_bind(outsock, io, srcaddr, port, qos.tos, qos.cos, socket_read, NULL); 10571 if (sock) { 10572 sockfd = ast_netsock_sockfd(sock); 10573 ast_netsock_unref(sock); 10574 nonlocal = 0; 10575 } else { 10576 nonlocal = 2; 10577 } 10578 } 10579 } 10580 } 10581 } 10582 10583 peer->sockfd = sockfd; 10584 10585 if (nonlocal == 1) { 10586 ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", 10587 srcaddr, peer->name); 10588 return -1; 10589 } else if (nonlocal == 2) { 10590 ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n", 10591 srcaddr, peer->name); 10592 return -1; 10593 } else { 10594 ast_debug(1, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); 10595 return 0; 10596 } 10597 }
static int peer_status | ( | struct iax2_peer * | peer, | |
char * | status, | |||
int | statuslen | |||
) | [static] |
peer_status: Report Peer status in character string
Definition at line 2702 of file chan_iax2.c.
References ast_copy_string(), iax2_peer::lastms, and iax2_peer::maxms.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), function_iaxpeer(), function_sippeer(), handle_cli_iax2_show_peer(), and manager_iax2_show_peer_list().
02703 { 02704 int res = 0; 02705 if (peer->maxms) { 02706 if (peer->lastms < 0) { 02707 ast_copy_string(status, "UNREACHABLE", statuslen); 02708 } else if (peer->lastms > peer->maxms) { 02709 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 02710 res = 1; 02711 } else if (peer->lastms) { 02712 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 02713 res = 1; 02714 } else { 02715 ast_copy_string(status, "UNKNOWN", statuslen); 02716 } 02717 } else { 02718 ast_copy_string(status, "Unmonitored", statuslen); 02719 res = -1; 02720 } 02721 return res; 02722 }
Definition at line 1385 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_peers(), complete_iax2_unregister(), create_addr(), function_iaxpeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), manager_iax2_show_peer_list(), poke_all_peers(), prune_peers(), reg_source_db(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().
01386 { 01387 ao2_ref(peer, -1); 01388 return NULL; 01389 }
static void poke_all_peers | ( | void | ) | [static] |
Definition at line 11564 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, iax2_poke_peer(), and peer_unref().
Referenced by reload_config().
11565 { 11566 struct ao2_iterator i; 11567 struct iax2_peer *peer; 11568 11569 i = ao2_iterator_init(peers, 0); 11570 while ((peer = ao2_iterator_next(&i))) { 11571 iax2_poke_peer(peer, 0); 11572 peer_unref(peer); 11573 } 11574 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 11137 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ast_test_flag, IAX_DELME, IAX_RTCACHEFRIENDS, peer_unref(), and unlink_peer().
11138 { 11139 struct iax2_peer *peer; 11140 struct ao2_iterator i; 11141 11142 i = ao2_iterator_init(peers, 0); 11143 while ((peer = ao2_iterator_next(&i))) { 11144 if (ast_test_flag(peer, IAX_DELME) || ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 11145 unlink_peer(peer); 11146 } 11147 peer_unref(peer); 11148 } 11149 }
static void prune_users | ( | void | ) | [static] |
Definition at line 11122 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next, ao2_unlink, ast_test_flag, IAX_DELME, IAX_RTCACHEFRIENDS, user, and user_unref().
Referenced by handle_cli_iax2_prune_realtime(), and reload_config().
11123 { 11124 struct iax2_user *user; 11125 struct ao2_iterator i; 11126 11127 i = ao2_iterator_init(users, 0); 11128 while ((user = ao2_iterator_next(&i))) { 11129 if (ast_test_flag(user, IAX_DELME) || ast_test_flag(user, IAX_RTCACHEFRIENDS)) { 11130 ao2_unlink(users, user); 11131 } 11132 user_unref(user); 11133 } 11134 }
static int pvt_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 12387 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, chan_iax2_pvt::frames_received, and match().
12388 { 12389 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 12390 12391 /* The frames_received field is used to hold whether we're matching 12392 * against a full frame or not ... */ 12393 12394 return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 12395 pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0; 12396 }
static void pvt_destructor | ( | void * | obj | ) | [static] |
Definition at line 1490 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_string_field_free_memory, ast_variables_destroy(), iax2_registry::callno, iax_frame::callno, chan_iax2_pvt::callno, jb_frame::data, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, iax2_trunk_peer::list, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, and chan_iax2_pvt::vars.
01491 { 01492 struct chan_iax2_pvt *pvt = obj; 01493 struct iax_frame *cur = NULL; 01494 01495 ast_mutex_lock(&iaxsl[pvt->callno]); 01496 iax2_destroy_helper(pvt); 01497 ast_mutex_unlock(&iaxsl[pvt->callno]); 01498 01499 /* Already gone */ 01500 ast_set_flag(pvt, IAX_ALREADYGONE); 01501 01502 AST_LIST_LOCK(&frame_queue); 01503 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 01504 /* Cancel any pending transmissions */ 01505 if (cur->callno == pvt->callno) { 01506 cur->retries = -1; 01507 } 01508 } 01509 AST_LIST_UNLOCK(&frame_queue); 01510 01511 if (pvt->reg) { 01512 pvt->reg->callno = 0; 01513 } 01514 01515 if (!pvt->owner) { 01516 jb_frame frame; 01517 if (pvt->vars) { 01518 ast_variables_destroy(pvt->vars); 01519 pvt->vars = NULL; 01520 } 01521 01522 while (jb_getall(pvt->jb, &frame) == JB_OK) { 01523 iax2_frame_free(frame.data); 01524 } 01525 01526 jb_destroy(pvt->jb); 01527 ast_string_field_free_memory(pvt); 01528 } 01529 }
static int pvt_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 12380 of file chan_iax2.c.
References chan_iax2_pvt::peercallno.
12381 { 12382 const struct chan_iax2_pvt *pvt = obj; 12383 12384 return pvt->peercallno; 12385 }
static int raw_hangup | ( | struct sockaddr_in * | sin, | |
unsigned short | src, | |||
unsigned short | dst, | |||
int | sockfd | |||
) | [static] |
Definition at line 6239 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_inet_ntoa(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_outputframe(), 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().
06240 { 06241 struct ast_iax2_full_hdr fh; 06242 fh.scallno = htons(src | IAX_FLAG_FULL); 06243 fh.dcallno = htons(dst); 06244 fh.ts = 0; 06245 fh.oseqno = 0; 06246 fh.iseqno = 0; 06247 fh.type = AST_FRAME_IAX; 06248 fh.csub = compress_subclass(IAX_COMMAND_INVAL); 06249 iax_outputframe(NULL, &fh, 0, sin, 0); 06250 #if 0 06251 if (option_debug) 06252 #endif 06253 ast_debug(1, "Raw Hangup %s:%d, src=%d, dst=%d\n", 06254 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst); 06255 return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin)); 06256 }
static struct iax2_peer * realtime_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 3264 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, SENTINEL, ast_variable::value, and var.
03265 { 03266 struct ast_variable *var = NULL; 03267 struct ast_variable *tmp; 03268 struct iax2_peer *peer=NULL; 03269 time_t regseconds = 0, nowtime; 03270 int dynamic=0; 03271 03272 if (peername) { 03273 var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", SENTINEL); 03274 if (!var && sin) 03275 var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL); 03276 } else if (sin) { 03277 char porta[25]; 03278 sprintf(porta, "%d", ntohs(sin->sin_port)); 03279 var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, SENTINEL); 03280 if (var) { 03281 /* We'll need the peer name in order to build the structure! */ 03282 for (tmp = var; tmp; tmp = tmp->next) { 03283 if (!strcasecmp(tmp->name, "name")) 03284 peername = tmp->value; 03285 } 03286 } 03287 } 03288 if (!var && peername) { /* Last ditch effort */ 03289 var = ast_load_realtime("iaxpeers", "name", peername, SENTINEL); 03290 /*!\note 03291 * If this one loaded something, then we need to ensure that the host 03292 * field matched. The only reason why we can't have this as a criteria 03293 * is because we only have the IP address and the host field might be 03294 * set as a name (and the reverse PTR might not match). 03295 */ 03296 if (var && sin) { 03297 for (tmp = var; tmp; tmp = tmp->next) { 03298 if (!strcasecmp(tmp->name, "host")) { 03299 struct ast_hostent ahp; 03300 struct hostent *hp; 03301 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 03302 /* No match */ 03303 ast_variables_destroy(var); 03304 var = NULL; 03305 } 03306 break; 03307 } 03308 } 03309 } 03310 } 03311 if (!var) 03312 return NULL; 03313 03314 peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); 03315 03316 if (!peer) { 03317 ast_variables_destroy(var); 03318 return NULL; 03319 } 03320 03321 for (tmp = var; tmp; tmp = tmp->next) { 03322 /* Make sure it's not a user only... */ 03323 if (!strcasecmp(tmp->name, "type")) { 03324 if (strcasecmp(tmp->value, "friend") && 03325 strcasecmp(tmp->value, "peer")) { 03326 /* Whoops, we weren't supposed to exist! */ 03327 peer = peer_unref(peer); 03328 break; 03329 } 03330 } else if (!strcasecmp(tmp->name, "regseconds")) { 03331 ast_get_time_t(tmp->value, ®seconds, 0, NULL); 03332 } else if (!strcasecmp(tmp->name, "ipaddr")) { 03333 inet_aton(tmp->value, &(peer->addr.sin_addr)); 03334 } else if (!strcasecmp(tmp->name, "port")) { 03335 peer->addr.sin_port = htons(atoi(tmp->value)); 03336 } else if (!strcasecmp(tmp->name, "host")) { 03337 if (!strcasecmp(tmp->value, "dynamic")) 03338 dynamic = 1; 03339 } 03340 } 03341 03342 ast_variables_destroy(var); 03343 03344 if (!peer) 03345 return NULL; 03346 03347 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 03348 ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS); 03349 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) { 03350 if (peer->expire > -1) { 03351 if (!ast_sched_del(sched, peer->expire)) { 03352 peer->expire = -1; 03353 peer_unref(peer); 03354 } 03355 } 03356 peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer)); 03357 if (peer->expire == -1) 03358 peer_unref(peer); 03359 } 03360 ao2_link(peers, peer); 03361 if (ast_test_flag(peer, IAX_DYNAMIC)) 03362 reg_source_db(peer); 03363 } else { 03364 ast_set_flag(peer, IAX_TEMPONLY); 03365 } 03366 03367 if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) { 03368 time(&nowtime); 03369 if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) { 03370 memset(&peer->addr, 0, sizeof(peer->addr)); 03371 realtime_update_peer(peer->name, &peer->addr, 0); 03372 ast_debug(1, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n", 03373 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 03374 } 03375 else { 03376 ast_debug(1, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n", 03377 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 03378 } 03379 } 03380 03381 return peer; 03382 }
static void realtime_update_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin, | |||
time_t | regtime | |||
) | [static] |
Definition at line 3455 of file chan_iax2.c.
References ast_inet_ntoa(), ast_update_realtime(), and SENTINEL.
Referenced by __expire_registry(), update_peer(), and update_registry().
03456 { 03457 char port[10]; 03458 char regseconds[20]; 03459 03460 snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); 03461 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 03462 ast_update_realtime("iaxpeers", "name", peername, 03463 "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 03464 "regseconds", regseconds, SENTINEL); 03465 }
static struct iax2_user* realtime_user | ( | const char * | username, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 3384 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, SENTINEL, ast_variable::value, and var.
03385 { 03386 struct ast_variable *var; 03387 struct ast_variable *tmp; 03388 struct iax2_user *user=NULL; 03389 03390 var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", SENTINEL); 03391 if (!var) 03392 var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL); 03393 if (!var && sin) { 03394 char porta[6]; 03395 snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port)); 03396 var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, SENTINEL); 03397 if (!var) 03398 var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, SENTINEL); 03399 } 03400 if (!var) { /* Last ditch effort */ 03401 var = ast_load_realtime("iaxusers", "name", username, SENTINEL); 03402 /*!\note 03403 * If this one loaded something, then we need to ensure that the host 03404 * field matched. The only reason why we can't have this as a criteria 03405 * is because we only have the IP address and the host field might be 03406 * set as a name (and the reverse PTR might not match). 03407 */ 03408 if (var) { 03409 for (tmp = var; tmp; tmp = tmp->next) { 03410 if (!strcasecmp(tmp->name, "host")) { 03411 struct ast_hostent ahp; 03412 struct hostent *hp; 03413 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 03414 /* No match */ 03415 ast_variables_destroy(var); 03416 var = NULL; 03417 } 03418 break; 03419 } 03420 } 03421 } 03422 } 03423 if (!var) 03424 return NULL; 03425 03426 tmp = var; 03427 while(tmp) { 03428 /* Make sure it's not a peer only... */ 03429 if (!strcasecmp(tmp->name, "type")) { 03430 if (strcasecmp(tmp->value, "friend") && 03431 strcasecmp(tmp->value, "user")) { 03432 return NULL; 03433 } 03434 } 03435 tmp = tmp->next; 03436 } 03437 03438 user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); 03439 03440 ast_variables_destroy(var); 03441 03442 if (!user) 03443 return NULL; 03444 03445 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 03446 ast_set_flag(user, IAX_RTCACHEFRIENDS); 03447 ao2_link(users, user); 03448 } else { 03449 ast_set_flag(user, IAX_TEMPONLY); 03450 } 03451 03452 return user; 03453 }
static void reg_source_db | ( | struct iax2_peer * | p | ) | [static] |
Definition at line 7092 of file chan_iax2.c.
References iax2_peer::addr, ast_db_get(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_inet_ntoa(), ast_sched_del(), ast_test_flag, ast_verb, iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), IAX_TEMPONLY, inet_aton(), iax2_peer::name, peer_ref(), peer_unref(), register_peer_exten(), and sched.
Referenced by build_peer(), set_config(), and temp_peer().
07093 { 07094 char data[80]; 07095 struct in_addr in; 07096 char *c, *d; 07097 if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { 07098 c = strchr(data, ':'); 07099 if (c) { 07100 *c = '\0'; 07101 c++; 07102 if (inet_aton(data, &in)) { 07103 d = strchr(c, ':'); 07104 if (d) { 07105 *d = '\0'; 07106 d++; 07107 ast_verb(3, "Seeding '%s' at %s:%d for %d\n", p->name, 07108 ast_inet_ntoa(in), atoi(c), atoi(d)); 07109 iax2_poke_peer(p, 0); 07110 p->expiry = atoi(d); 07111 memset(&p->addr, 0, sizeof(p->addr)); 07112 p->addr.sin_family = AF_INET; 07113 p->addr.sin_addr = in; 07114 p->addr.sin_port = htons(atoi(c)); 07115 if (p->expire > -1) { 07116 if (!ast_sched_del(sched, p->expire)) { 07117 p->expire = -1; 07118 peer_unref(p); 07119 } 07120 } 07121 ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ 07122 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 07123 if (p->expire == -1) 07124 peer_unref(p); 07125 if (iax2_regfunk) 07126 iax2_regfunk(p->name, 1); 07127 register_peer_exten(p, 1); 07128 } 07129 07130 } 07131 } 07132 } 07133 }
static void register_peer_exten | ( | struct iax2_peer * | peer, | |
int | onoff | |||
) | [static] |
Definition at line 7013 of file chan_iax2.c.
References ast_add_extension(), ast_context_remove_extension(), ast_copy_string(), ast_exists_extension(), ast_free_ptr, ast_strdup, ast_strlen_zero(), ext, iax2_peer::name, iax2_peer::regexten, S_OR, and strsep().
Referenced by __expire_registry(), expire_register(), handle_response_peerpoke(), parse_register_contact(), peer_destructor(), reg_source_db(), sip_destroy_peer(), sip_poke_noanswer(), and update_registry().
07014 { 07015 char multi[256]; 07016 char *stringp, *ext; 07017 if (!ast_strlen_zero(regcontext)) { 07018 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 07019 stringp = multi; 07020 while((ext = strsep(&stringp, "&"))) { 07021 if (onoff) { 07022 if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL)) 07023 ast_add_extension(regcontext, 1, ext, 1, NULL, NULL, 07024 "Noop", ast_strdup(peer->name), ast_free_ptr, "IAX2"); 07025 } else 07026 ast_context_remove_extension(regcontext, ext, 1, NULL); 07027 } 07028 } 07029 }
static int register_verify | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Verify inbound registration.
Definition at line 6410 of file chan_iax2.c.
References ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_copy_string(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, iax2_peer::inkeys, LOG_NOTICE, LOG_WARNING, md5(), iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax2_peer::name, iax_ies::password, iax_ies::refresh, iax_ies::rsa_result, iax2_peer::secret, secret, strsep(), and iax_ies::username.
Referenced by handle_request_register(), and socket_process().
06411 { 06412 char requeststr[256] = ""; 06413 char peer[256] = ""; 06414 char md5secret[256] = ""; 06415 char rsasecret[256] = ""; 06416 char secret[256] = ""; 06417 struct iax2_peer *p = NULL; 06418 struct ast_key *key; 06419 char *keyn; 06420 int x; 06421 int expire = 0; 06422 int res = -1; 06423 06424 ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06425 /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */ 06426 if (ies->username) 06427 ast_copy_string(peer, ies->username, sizeof(peer)); 06428 if (ies->password) 06429 ast_copy_string(secret, ies->password, sizeof(secret)); 06430 if (ies->md5_result) 06431 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 06432 if (ies->rsa_result) 06433 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 06434 if (ies->refresh) 06435 expire = ies->refresh; 06436 06437 if (ast_strlen_zero(peer)) { 06438 ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr)); 06439 return -1; 06440 } 06441 06442 /* SLD: first call to lookup peer during registration */ 06443 ast_mutex_unlock(&iaxsl[callno]); 06444 p = find_peer(peer, 1); 06445 ast_mutex_lock(&iaxsl[callno]); 06446 if (!p || !iaxs[callno]) { 06447 if (iaxs[callno]) { 06448 int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT)); 06449 /* Anything, as long as it's non-blank */ 06450 ast_string_field_set(iaxs[callno], secret, "badsecret"); 06451 /* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless 06452 * 1. A challenge already exists indicating a AUTHREQ was already sent out. 06453 * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it. 06454 * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened 06455 * to be plaintext, indicating it is an authmethod used by other peers on the system. 06456 * 06457 * If none of these cases exist, res will be returned as 0 without authentication indicating 06458 * an AUTHREQ needs to be sent out. */ 06459 06460 if (ast_strlen_zero(iaxs[callno]->challenge) && 06461 !(!ast_strlen_zero(secret) && plaintext)) { 06462 /* by setting res to 0, an REGAUTH will be sent */ 06463 res = 0; 06464 } 06465 } 06466 if (authdebug && !p) 06467 ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 06468 goto return_unref; 06469 } 06470 06471 if (!ast_test_flag(p, IAX_DYNAMIC)) { 06472 if (authdebug) 06473 ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 06474 goto return_unref; 06475 } 06476 06477 if (!ast_apply_ha(p->ha, sin)) { 06478 if (authdebug) 06479 ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 06480 goto return_unref; 06481 } 06482 ast_string_field_set(iaxs[callno], secret, p->secret); 06483 ast_string_field_set(iaxs[callno], inkeys, p->inkeys); 06484 /* Check secret against what we have on file */ 06485 if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) { 06486 if (!ast_strlen_zero(p->inkeys)) { 06487 char tmpkeys[256]; 06488 char *stringp=NULL; 06489 ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys)); 06490 stringp=tmpkeys; 06491 keyn = strsep(&stringp, ":"); 06492 while(keyn) { 06493 key = ast_key_get(keyn, AST_KEY_PUBLIC); 06494 if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) { 06495 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06496 break; 06497 } else if (!key) 06498 ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn); 06499 keyn = strsep(&stringp, ":"); 06500 } 06501 if (!keyn) { 06502 if (authdebug) 06503 ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys); 06504 goto return_unref; 06505 } 06506 } else { 06507 if (authdebug) 06508 ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer); 06509 goto return_unref; 06510 } 06511 } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { 06512 struct MD5Context md5; 06513 unsigned char digest[16]; 06514 char *tmppw, *stringp; 06515 06516 tmppw = ast_strdupa(p->secret); 06517 stringp = tmppw; 06518 while((tmppw = strsep(&stringp, ";"))) { 06519 MD5Init(&md5); 06520 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 06521 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 06522 MD5Final(digest, &md5); 06523 for (x=0;x<16;x++) 06524 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 06525 if (!strcasecmp(requeststr, md5secret)) 06526 break; 06527 } 06528 if (tmppw) { 06529 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06530 } else { 06531 if (authdebug) 06532 ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret); 06533 goto return_unref; 06534 } 06535 } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) { 06536 /* They've provided a plain text password and we support that */ 06537 if (strcmp(secret, p->secret)) { 06538 if (authdebug) 06539 ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 06540 goto return_unref; 06541 } else 06542 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06543 } else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) { 06544 /* if challenge has been sent, but no challenge response if given, reject. */ 06545 goto return_unref; 06546 } 06547 ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ 06548 06549 /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */ 06550 res = 0; 06551 06552 return_unref: 06553 if (iaxs[callno]) { 06554 ast_string_field_set(iaxs[callno], peer, peer); 06555 06556 /* Choose lowest expiry number */ 06557 if (expire && (expire < iaxs[callno]->expiry)) { 06558 iaxs[callno]->expiry = expire; 06559 } 06560 } 06561 06562 if (p) { 06563 peer_unref(p); 06564 } 06565 return res; 06566 }
static int registry_authrequest | ( | int | callno | ) | [static] |
Definition at line 7290 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strdupa, ast_string_field_set, iax2_peer::authmethods, find_peer(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_COMMAND_REGAUTH, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CHALLENGE, IAX_IE_USERNAME, peer_unref(), and send_command().
Referenced by socket_process().
07291 { 07292 struct iax_ie_data ied; 07293 struct iax2_peer *p; 07294 char challenge[10]; 07295 const char *peer_name; 07296 int sentauthmethod; 07297 07298 peer_name = ast_strdupa(iaxs[callno]->peer); 07299 07300 /* SLD: third call to find_peer in registration */ 07301 ast_mutex_unlock(&iaxsl[callno]); 07302 if ((p = find_peer(peer_name, 1))) { 07303 last_authmethod = p->authmethods; 07304 } 07305 07306 ast_mutex_lock(&iaxsl[callno]); 07307 if (!iaxs[callno]) 07308 goto return_unref; 07309 07310 memset(&ied, 0, sizeof(ied)); 07311 /* The selection of which delayed reject is sent may leak information, 07312 * if it sets a static response. For example, if a host is known to only 07313 * use MD5 authentication, then an RSA response would indicate that the 07314 * peer does not exist, and vice-versa. 07315 * Therefore, we use whatever the last peer used (which may vary over the 07316 * course of a server, which should leak minimal information). */ 07317 sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT); 07318 if (!p) { 07319 iaxs[callno]->authmethods = sentauthmethod; 07320 } 07321 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod); 07322 if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) { 07323 /* Build the challenge */ 07324 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 07325 ast_string_field_set(iaxs[callno], challenge, challenge); 07326 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge); 07327 } 07328 iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name); 07329 07330 return_unref: 07331 if (p) { 07332 peer_unref(p); 07333 } 07334 07335 return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1; 07336 }
static int registry_rerequest | ( | struct iax_ies * | ies, | |
int | callno, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 7338 of file chan_iax2.c.
References iax2_registry::addr, ast_copy_string(), AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax_ies::challenge, IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax2_registry::refresh, REG_STATE_AUTHSENT, iax2_registry::regstate, iax2_registry::secret, send_command(), iax2_registry::username, and iax_ies::username.
Referenced by socket_process().
07339 { 07340 struct iax2_registry *reg; 07341 /* Start pessimistic */ 07342 struct iax_ie_data ied; 07343 char peer[256] = ""; 07344 char challenge[256] = ""; 07345 int res; 07346 int authmethods = 0; 07347 if (ies->authmethods) 07348 authmethods = ies->authmethods; 07349 if (ies->username) 07350 ast_copy_string(peer, ies->username, sizeof(peer)); 07351 if (ies->challenge) 07352 ast_copy_string(challenge, ies->challenge, sizeof(challenge)); 07353 memset(&ied, 0, sizeof(ied)); 07354 reg = iaxs[callno]->reg; 07355 if (reg) { 07356 if (inaddrcmp(®->addr, sin)) { 07357 ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 07358 return -1; 07359 } 07360 if (ast_strlen_zero(reg->secret)) { 07361 ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); 07362 reg->regstate = REG_STATE_NOAUTH; 07363 return -1; 07364 } 07365 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 07366 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 07367 if (reg->secret[0] == '[') { 07368 char tmpkey[256]; 07369 ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); 07370 tmpkey[strlen(tmpkey) - 1] = '\0'; 07371 res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL); 07372 } else 07373 res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL); 07374 if (!res) { 07375 reg->regstate = REG_STATE_AUTHSENT; 07376 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 07377 } else 07378 return -1; 07379 ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); 07380 } else 07381 ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); 07382 return -1; 07383 }
static char* regstate2str | ( | int | regstate | ) | [static] |
Definition at line 5601 of file chan_iax2.c.
References REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED.
Referenced by handle_cli_iax2_show_registry(), handle_response_register(), manager_show_registry(), sip_reg_timeout(), and sip_show_registry().
05602 { 05603 switch(regstate) { 05604 case REG_STATE_UNREGISTERED: 05605 return "Unregistered"; 05606 case REG_STATE_REGSENT: 05607 return "Request Sent"; 05608 case REG_STATE_AUTHSENT: 05609 return "Auth. Sent"; 05610 case REG_STATE_REGISTERED: 05611 return "Registered"; 05612 case REG_STATE_REJECTED: 05613 return "Rejected"; 05614 case REG_STATE_TIMEOUT: 05615 return "Timeout"; 05616 case REG_STATE_NOAUTH: 05617 return "No Authentication"; 05618 default: 05619 return "Unknown"; 05620 } 05621 }
static int reload | ( | void | ) | [static] |
Definition at line 11621 of file chan_iax2.c.
References reload_config().
11622 { 11623 return reload_config(); 11624 }
static int reload_config | ( | void | ) | [static] |
Definition at line 11575 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_unload_realtime(), config, debugaddr, iax2_registry::entry, iax2_do_register(), iax_provision_reload(), poke_all_peers(), prune_peers(), prune_users(), reload_firmware(), and set_config().
11576 { 11577 char *config = "iax.conf"; 11578 struct iax2_registry *reg; 11579 11580 if (set_config(config, 1) > 0) { 11581 prune_peers(); 11582 prune_users(); 11583 trunk_timed = trunk_untimed = 0; 11584 trunk_nmaxmtu = trunk_maxmtu = 0; 11585 memset(&debugaddr, '\0', sizeof(debugaddr)); 11586 11587 AST_LIST_LOCK(®istrations); 11588 AST_LIST_TRAVERSE(®istrations, reg, entry) 11589 iax2_do_register(reg); 11590 AST_LIST_UNLOCK(®istrations); 11591 11592 /* Qualify hosts, too */ 11593 poke_all_peers(); 11594 } 11595 11596 reload_firmware(0); 11597 iax_provision_reload(1); 11598 ast_unload_realtime("iaxpeers"); 11599 11600 return 0; 11601 }
static void reload_firmware | ( | int | unload | ) | [static] |
Definition at line 2211 of file chan_iax2.c.
References ast_config_AST_DATA_DIR, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verb, iax_firmware::dead, destroy_firmware(), dir, errno, iax2_trunk_peer::list, LOG_WARNING, and try_firmware().
Referenced by __unload_module(), load_module(), and reload_config().
02212 { 02213 struct iax_firmware *cur = NULL; 02214 DIR *fwd; 02215 struct dirent *de; 02216 char dir[256], fn[256]; 02217 02218 AST_LIST_LOCK(&firmwares); 02219 02220 /* Mark all as dead */ 02221 AST_LIST_TRAVERSE(&firmwares, cur, list) 02222 cur->dead = 1; 02223 02224 /* Now that we have marked them dead... load new ones */ 02225 if (!unload) { 02226 snprintf(dir, sizeof(dir), "%s/firmware/iax", ast_config_AST_DATA_DIR); 02227 fwd = opendir(dir); 02228 if (fwd) { 02229 while((de = readdir(fwd))) { 02230 if (de->d_name[0] != '.') { 02231 snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name); 02232 if (!try_firmware(fn)) { 02233 ast_verb(2, "Loaded firmware '%s'\n", de->d_name); 02234 } 02235 } 02236 } 02237 closedir(fwd); 02238 } else 02239 ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno)); 02240 } 02241 02242 /* Clean up leftovers */ 02243 AST_LIST_TRAVERSE_SAFE_BEGIN(&firmwares, cur, list) { 02244 if (!cur->dead) 02245 continue; 02246 AST_LIST_REMOVE_CURRENT(list); 02247 destroy_firmware(cur); 02248 } 02249 AST_LIST_TRAVERSE_SAFE_END; 02250 02251 AST_LIST_UNLOCK(&firmwares); 02252 }
static void remove_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1720 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().
01721 { 01722 if (!pvt->peercallno) { 01723 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01724 return; 01725 } 01726 01727 ao2_unlink(iax_peercallno_pvts, pvt); 01728 }
static void remove_by_transfercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1701 of file chan_iax2.c.
References ao2_unlink, ast_log(), iax_transfercallno_pvts, LOG_ERROR, and chan_iax2_pvt::transfercallno.
Referenced by complete_transfer(), and iax2_destroy().
01702 { 01703 if (!pvt->transfercallno) { 01704 ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n"); 01705 return; 01706 } 01707 01708 ao2_unlink(iax_transfercallno_pvts, pvt); 01709 }
Definition at line 7818 of file chan_iax2.c.
References ast_string_field_set, iax_frame::callno, IAX_MAX_OSPBLOCK_NUM, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPBUFF_SIZE, iax_ies::ospblocklength, and iax_ies::osptokenblock.
Referenced by socket_process().
07819 { 07820 int i; 07821 unsigned int length, offset = 0; 07822 char full_osptoken[IAX_MAX_OSPBUFF_SIZE]; 07823 07824 for (i = 0; i < IAX_MAX_OSPBLOCK_NUM; i++) { 07825 length = ies->ospblocklength[i]; 07826 if (length != 0) { 07827 if (length > IAX_MAX_OSPBLOCK_SIZE) { 07828 /* OSP token block length wrong, clear buffer */ 07829 offset = 0; 07830 break; 07831 } else { 07832 memcpy(full_osptoken + offset, ies->osptokenblock[i], length); 07833 offset += length; 07834 } 07835 } else { 07836 break; 07837 } 07838 } 07839 *(full_osptoken + offset) = '\0'; 07840 if (strlen(full_osptoken) != offset) { 07841 /* OSP token length wrong, clear buffer */ 07842 *full_osptoken = '\0'; 07843 } 07844 07845 ast_string_field_set(iaxs[fr->callno], osptoken, full_osptoken); 07846 }
Definition at line 7807 of file chan_iax2.c.
References iax_frame::callno, iax_ies::rr_delay, iax_ies::rr_dropped, iax_ies::rr_jitter, iax_ies::rr_loss, iax_ies::rr_ooo, and iax_ies::rr_pkts.
Referenced by socket_process().
07808 { 07809 iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter; 07810 iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24; 07811 iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff; 07812 iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts; 07813 iaxs[fr->callno]->remote_rr.delay = ies->rr_delay; 07814 iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped; 07815 iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; 07816 }
static void* sched_thread | ( | void * | ignore | ) | [static] |
Definition at line 10355 of file chan_iax2.c.
References ast_cond_timedwait(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), ast_tvnow(), sched, and sched_lock.
10356 { 10357 int count; 10358 int res; 10359 struct timeval wait; 10360 struct timespec ts; 10361 10362 for (;;) { 10363 pthread_testcancel(); 10364 ast_mutex_lock(&sched_lock); 10365 res = ast_sched_wait(sched); 10366 if ((res > 1000) || (res < 0)) 10367 res = 1000; 10368 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); 10369 ts.tv_sec = wait.tv_sec; 10370 ts.tv_nsec = wait.tv_usec * 1000; 10371 ast_cond_timedwait(&sched_cond, &sched_lock, &ts); 10372 ast_mutex_unlock(&sched_lock); 10373 pthread_testcancel(); 10374 10375 count = ast_sched_runq(sched); 10376 if (count >= 20) 10377 ast_debug(1, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); 10378 } 10379 10380 return NULL; 10381 }
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 3119 of file chan_iax2.c.
References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), ast_debug, AST_FRAME_CNG, AST_FRAME_VOICE, ast_samp2tv(), AST_SCHED_DEL, ast_test_flag, ast_tv(), ast_tvadd(), ast_tvzero(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, ast_channel_tech::properties, sched, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().
Referenced by socket_process(), and socket_process_meta().
03120 { 03121 int type, len; 03122 int ret; 03123 int needfree = 0; 03124 struct ast_channel *owner = NULL; 03125 struct ast_channel *bridge = NULL; 03126 03127 /* Attempt to recover wrapped timestamps */ 03128 unwrap_timestamp(fr); 03129 03130 /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */ 03131 if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) 03132 fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000)); 03133 else { 03134 #if 0 03135 ast_debug(1, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n"); 03136 #endif 03137 fr->af.delivery = ast_tv(0,0); 03138 } 03139 03140 type = JB_TYPE_CONTROL; 03141 len = 0; 03142 03143 if(fr->af.frametype == AST_FRAME_VOICE) { 03144 type = JB_TYPE_VOICE; 03145 len = ast_codec_get_samples(&fr->af) / 8; 03146 } else if(fr->af.frametype == AST_FRAME_CNG) { 03147 type = JB_TYPE_SILENCE; 03148 } 03149 03150 if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) { 03151 if (tsout) 03152 *tsout = fr->ts; 03153 __do_deliver(fr); 03154 return -1; 03155 } 03156 03157 if ((owner = iaxs[fr->callno]->owner)) 03158 bridge = ast_bridged_channel(owner); 03159 03160 /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to 03161 * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */ 03162 if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) { 03163 jb_frame frame; 03164 03165 /* deliver any frames in the jb */ 03166 while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { 03167 __do_deliver(frame.data); 03168 /* __do_deliver() can make the call disappear */ 03169 if (!iaxs[fr->callno]) 03170 return -1; 03171 } 03172 03173 jb_reset(iaxs[fr->callno]->jb); 03174 03175 AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid); 03176 03177 /* deliver this frame now */ 03178 if (tsout) 03179 *tsout = fr->ts; 03180 __do_deliver(fr); 03181 return -1; 03182 } 03183 03184 /* insert into jitterbuffer */ 03185 /* TODO: Perhaps we could act immediately if it's not droppable and late */ 03186 ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts, 03187 calc_rxstamp(iaxs[fr->callno],fr->ts)); 03188 if (ret == JB_DROP) { 03189 needfree++; 03190 } else if (ret == JB_SCHED) { 03191 update_jbsched(iaxs[fr->callno]); 03192 } 03193 if (tsout) 03194 *tsout = fr->ts; 03195 if (needfree) { 03196 /* Free our iax frame */ 03197 iax2_frame_free(fr); 03198 return -1; 03199 } 03200 return 0; 03201 }
static int scheduled_destroy | ( | const void * | vid | ) | [static] |
Definition at line 1476 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_destroy(), LOG_DEBUG, option_debug, and PTR_TO_CALLNO.
Referenced by iax2_hangup().
01477 { 01478 short callno = PTR_TO_CALLNO(vid); 01479 ast_mutex_lock(&iaxsl[callno]); 01480 if (iaxs[callno]) { 01481 if (option_debug) { 01482 ast_log(LOG_DEBUG, "Really destroying %d now...\n", callno); 01483 } 01484 iax2_destroy(callno); 01485 } 01486 ast_mutex_unlock(&iaxsl[callno]); 01487 return 0; 01488 }
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 3623 of file chan_iax2.c.
References AST_FRAME_IAX, compress_subclass(), and f.
Referenced by socket_process().
03624 { 03625 struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno), 03626 .ts = htonl(ts), .iseqno = seqno, .oseqno = 0, .type = AST_FRAME_IAX, 03627 .csub = compress_subclass(command) }; 03628 03629 return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin)); 03630 }
static int send_command | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5965 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_key_rotate(), iax2_poke_peer(), iax2_provision(), iax2_start_transfer(), registry_authrequest(), registry_rerequest(), send_command_locked(), and socket_process().
05966 { 05967 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); 05968 }
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 5984 of file chan_iax2.c.
References __send_command(), chan_iax2_pvt::callno, and iax2_predestroy().
Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_hangup(), socket_process(), and update_registry().
05985 { 05986 int call_num = i->callno; 05987 /* It is assumed that the callno has already been locked */ 05988 iax2_predestroy(i->callno); 05989 if (!iaxs[call_num]) 05990 return -1; 05991 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1); 05992 }
static int send_command_immediate | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5994 of file chan_iax2.c.
References __send_command().
Referenced by iax2_vnak(), and socket_process().
05995 { 05996 return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0); 05997 }
static int send_command_locked | ( | unsigned short | callno, | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5970 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), and send_command().
Referenced by iax2_answer(), iax2_digit_begin(), iax2_digit_end(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), and iax2_transfer().
05971 { 05972 int res; 05973 ast_mutex_lock(&iaxsl[callno]); 05974 res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno); 05975 ast_mutex_unlock(&iaxsl[callno]); 05976 return res; 05977 }
static int send_command_transfer | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | ||||
) | [static] |
Definition at line 5999 of file chan_iax2.c.
References __send_command().
Referenced by socket_process(), and try_transfer().
06000 { 06001 return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0); 06002 }
static int send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1275 of file chan_iax2.c.
References __send_lagrq(), and schedule_action.
Referenced by __find_callno(), __send_lagrq(), and make_trunk().
01276 { 01277 #ifdef SCHED_MULTITHREADED 01278 if (schedule_action(__send_lagrq, data)) 01279 #endif 01280 __send_lagrq(data); 01281 01282 return 0; 01283 }
static int send_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2324 of file chan_iax2.c.
References ast_debug, ast_inet_ntoa(), errno, f, handle_error(), iax_showframe(), and iax2_trunk_peer::sockfd.
Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().
02325 { 02326 int res; 02327 int callno = f->callno; 02328 02329 /* Don't send if there was an error, but return error instead */ 02330 if (!callno || !iaxs[callno] || iaxs[callno]->error) 02331 return -1; 02332 02333 /* Called with iaxsl held */ 02334 if (iaxdebug) 02335 ast_debug(3, "Sending %d on %d/%d to %s:%d\n", f->ts, callno, iaxs[callno]->peercallno, ast_inet_ntoa(iaxs[callno]->addr.sin_addr), ntohs(iaxs[callno]->addr.sin_port)); 02336 02337 if (f->transfer) { 02338 if (iaxdebug) 02339 iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02340 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, sizeof(iaxs[callno]->transfer)); 02341 } else { 02342 if (iaxdebug) 02343 iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02344 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, sizeof(iaxs[callno]->addr)); 02345 } 02346 if (res < 0) { 02347 if (iaxdebug) 02348 ast_debug(1, "Received error: %s\n", strerror(errno)); 02349 handle_error(); 02350 } else 02351 res = 0; 02352 02353 return res; 02354 }
static int send_ping | ( | const void * | data | ) | [static] |
Definition at line 1230 of file chan_iax2.c.
References __send_ping(), and schedule_action.
Referenced by __find_callno(), __send_ping(), do_monitor(), init_phone_step2(), and make_trunk().
01231 { 01232 #ifdef SCHED_MULTITHREADED 01233 if (schedule_action(__send_ping, data)) 01234 #endif 01235 __send_ping(data); 01236 01237 return 0; 01238 }
static int send_trunk | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [static] |
Definition at line 7520 of file chan_iax2.c.
References iax2_trunk_peer::addr, iax_frame::afdata, ast_debug, ast_inet_ntoa(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, globalflags, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_hdr::metacmd, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.
Referenced by iax2_trunk_queue(), and timing_read().
07521 { 07522 int res = 0; 07523 struct iax_frame *fr; 07524 struct ast_iax2_meta_hdr *meta; 07525 struct ast_iax2_meta_trunk_hdr *mth; 07526 int calls = 0; 07527 07528 /* Point to frame */ 07529 fr = (struct iax_frame *)tpeer->trunkdata; 07530 /* Point to meta data */ 07531 meta = (struct ast_iax2_meta_hdr *)fr->afdata; 07532 mth = (struct ast_iax2_meta_trunk_hdr *)meta->data; 07533 if (tpeer->trunkdatalen) { 07534 /* We're actually sending a frame, so fill the meta trunk header and meta header */ 07535 meta->zeros = 0; 07536 meta->metacmd = IAX_META_TRUNK; 07537 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) 07538 meta->cmddata = IAX_META_TRUNK_MINI; 07539 else 07540 meta->cmddata = IAX_META_TRUNK_SUPERMINI; 07541 mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now)); 07542 /* And the rest of the ast_iax2 header */ 07543 fr->direction = DIRECTION_OUTGRESS; 07544 fr->retrans = -1; 07545 fr->transfer = 0; 07546 /* Any appropriate call will do */ 07547 fr->data = fr->afdata; 07548 fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr); 07549 res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd); 07550 calls = tpeer->calls; 07551 #if 0 07552 ast_debug(1, "Trunking %d call chunks in %d bytes to %s:%d, ts=%d\n", calls, fr->datalen, ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), ntohl(mth->ts)); 07553 #endif 07554 /* Reset transmit trunk side data */ 07555 tpeer->trunkdatalen = 0; 07556 tpeer->calls = 0; 07557 } 07558 if (res < 0) 07559 return res; 07560 return calls; 07561 }
static int set_config | ( | char * | config_file, | |
int | reload | |||
) | [static] |
Load configuration.
Definition at line 11169 of file chan_iax2.c.
References ao2_link, ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_context_find_or_create(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_netsock_bind(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_netsock_sockfd(), ast_netsock_unref(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_str2cos(), ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, build_peer(), build_user(), capability, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MAXMS, errno, format, gen, get_encrypt_methods(), globalflags, iax2_register(), IAX_ALLOWFWDOWNLOAD, IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_ENCRYPT_KEYROTATE, 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_TRUNKDATA, ast_variable::name, netsock, ast_variable::next, outsock, peer_unref(), prefs, qos, reg_source_db(), secret, set_config_destroy(), socket_read(), user, user_unref(), and ast_variable::value.
Referenced by load_module(), reload(), and reload_config().
11170 { 11171 struct ast_config *cfg, *ucfg; 11172 int capability=iax2_capability; 11173 struct ast_variable *v; 11174 char *cat; 11175 const char *utype; 11176 const char *tosval; 11177 int format; 11178 int portno = IAX_DEFAULT_PORTNO; 11179 int x; 11180 int mtuv; 11181 struct iax2_user *user; 11182 struct iax2_peer *peer; 11183 struct ast_netsock *ns; 11184 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 11185 #if 0 11186 static unsigned short int last_port=0; 11187 #endif 11188 11189 cfg = ast_config_load(config_file, config_flags); 11190 11191 if (!cfg) { 11192 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 11193 return -1; 11194 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 11195 ucfg = ast_config_load("users.conf", config_flags); 11196 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 11197 return 0; 11198 /* Otherwise we need to reread both files */ 11199 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 11200 cfg = ast_config_load(config_file, config_flags); 11201 } else { /* iax.conf changed, gotta reread users.conf, too */ 11202 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 11203 ucfg = ast_config_load("users.conf", config_flags); 11204 } 11205 11206 if (reload) { 11207 set_config_destroy(); 11208 } 11209 11210 /* Reset global codec prefs */ 11211 memset(&prefs, 0 , sizeof(struct ast_codec_pref)); 11212 11213 /* Reset Global Flags */ 11214 memset(&globalflags, 0, sizeof(globalflags)); 11215 ast_set_flag(&globalflags, IAX_RTUPDATE); 11216 11217 /* Turns on support for key rotation during encryption. */ 11218 iax2_encryption |= IAX_ENCRYPT_KEYROTATE; 11219 #ifdef SO_NO_CHECK 11220 nochecksums = 0; 11221 #endif 11222 /* Reset default parking lot */ 11223 default_parkinglot[0] = '\0'; 11224 11225 min_reg_expire = IAX_DEFAULT_REG_EXPIRE; 11226 max_reg_expire = IAX_DEFAULT_REG_EXPIRE; 11227 11228 maxauthreq = 3; 11229 11230 srvlookup = 0; 11231 11232 v = ast_variable_browse(cfg, "general"); 11233 11234 /* Seed initial tos value */ 11235 tosval = ast_variable_retrieve(cfg, "general", "tos"); 11236 if (tosval) { 11237 if (ast_str2tos(tosval, &qos.tos)) 11238 ast_log(LOG_WARNING, "Invalid tos value, refer to QoS documentation\n"); 11239 } 11240 /* Seed initial cos value */ 11241 tosval = ast_variable_retrieve(cfg, "general", "cos"); 11242 if (tosval) { 11243 if (ast_str2cos(tosval, &qos.cos)) 11244 ast_log(LOG_WARNING, "Invalid cos value, refer to QoS documentation\n"); 11245 } 11246 while(v) { 11247 if (!strcasecmp(v->name, "bindport")){ 11248 if (reload) 11249 ast_log(LOG_NOTICE, "Ignoring bindport on reload\n"); 11250 else 11251 portno = atoi(v->value); 11252 } else if (!strcasecmp(v->name, "pingtime")) 11253 ping_time = atoi(v->value); 11254 else if (!strcasecmp(v->name, "iaxthreadcount")) { 11255 if (reload) { 11256 if (atoi(v->value) != iaxthreadcount) 11257 ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n"); 11258 } else { 11259 iaxthreadcount = atoi(v->value); 11260 if (iaxthreadcount < 1) { 11261 ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n"); 11262 iaxthreadcount = 1; 11263 } else if (iaxthreadcount > 256) { 11264 ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n"); 11265 iaxthreadcount = 256; 11266 } 11267 } 11268 } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) { 11269 if (reload) { 11270 AST_LIST_LOCK(&dynamic_list); 11271 iaxmaxthreadcount = atoi(v->value); 11272 AST_LIST_UNLOCK(&dynamic_list); 11273 } else { 11274 iaxmaxthreadcount = atoi(v->value); 11275 if (iaxmaxthreadcount < 0) { 11276 ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n"); 11277 iaxmaxthreadcount = 0; 11278 } else if (iaxmaxthreadcount > 256) { 11279 ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n"); 11280 iaxmaxthreadcount = 256; 11281 } 11282 } 11283 } else if (!strcasecmp(v->name, "nochecksums")) { 11284 #ifdef SO_NO_CHECK 11285 if (ast_true(v->value)) 11286 nochecksums = 1; 11287 else 11288 nochecksums = 0; 11289 #else 11290 if (ast_true(v->value)) 11291 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 11292 #endif 11293 } 11294 else if (!strcasecmp(v->name, "maxjitterbuffer")) 11295 maxjitterbuffer = atoi(v->value); 11296 else if (!strcasecmp(v->name, "resyncthreshold")) 11297 resyncthreshold = atoi(v->value); 11298 else if (!strcasecmp(v->name, "maxjitterinterps")) 11299 maxjitterinterps = atoi(v->value); 11300 else if (!strcasecmp(v->name, "jittertargetextra")) 11301 jittertargetextra = atoi(v->value); 11302 else if (!strcasecmp(v->name, "lagrqtime")) 11303 lagrq_time = atoi(v->value); 11304 else if (!strcasecmp(v->name, "maxregexpire")) 11305 max_reg_expire = atoi(v->value); 11306 else if (!strcasecmp(v->name, "minregexpire")) 11307 min_reg_expire = atoi(v->value); 11308 else if (!strcasecmp(v->name, "bindaddr")) { 11309 if (reload) { 11310 ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n"); 11311 } else { 11312 if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, qos.tos, qos.cos, socket_read, NULL))) { 11313 ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno); 11314 } else { 11315 if (strchr(v->value, ':')) 11316 ast_verb(2, "Binding IAX2 to '%s'\n", v->value); 11317 else 11318 ast_verb(2, "Binding IAX2 to '%s:%d'\n", v->value, portno); 11319 if (defaultsockfd < 0) 11320 defaultsockfd = ast_netsock_sockfd(ns); 11321 ast_netsock_unref(ns); 11322 } 11323 } 11324 } else if (!strcasecmp(v->name, "authdebug")) 11325 authdebug = ast_true(v->value); 11326 else if (!strcasecmp(v->name, "encryption")) 11327 iax2_encryption |= get_encrypt_methods(v->value); 11328 else if (!strcasecmp(v->name, "transfer")) { 11329 if (!strcasecmp(v->value, "mediaonly")) { 11330 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 11331 } else if (ast_true(v->value)) { 11332 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 11333 } else 11334 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 11335 } else if (!strcasecmp(v->name, "codecpriority")) { 11336 if(!strcasecmp(v->value, "caller")) 11337 ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST); 11338 else if(!strcasecmp(v->value, "disabled")) 11339 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 11340 else if(!strcasecmp(v->value, "reqonly")) { 11341 ast_set_flag((&globalflags), IAX_CODEC_NOCAP); 11342 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 11343 } 11344 } else if (!strcasecmp(v->name, "jitterbuffer")) 11345 ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 11346 else if (!strcasecmp(v->name, "forcejitterbuffer")) 11347 ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF); 11348 else if (!strcasecmp(v->name, "delayreject")) 11349 delayreject = ast_true(v->value); 11350 else if (!strcasecmp(v->name, "allowfwdownload")) 11351 ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD); 11352 else if (!strcasecmp(v->name, "rtcachefriends")) 11353 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS); 11354 else if (!strcasecmp(v->name, "rtignoreregexpire")) 11355 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE); 11356 else if (!strcasecmp(v->name, "rtupdate")) 11357 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE); 11358 else if (!strcasecmp(v->name, "trunktimestamps")) 11359 ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS); 11360 else if (!strcasecmp(v->name, "rtautoclear")) { 11361 int i = atoi(v->value); 11362 if(i > 0) 11363 global_rtautoclear = i; 11364 else 11365 i = 0; 11366 ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR); 11367 } else if (!strcasecmp(v->name, "trunkfreq")) { 11368 trunkfreq = atoi(v->value); 11369 if (trunkfreq < 10) 11370 trunkfreq = 10; 11371 } else if (!strcasecmp(v->name, "trunkmtu")) { 11372 mtuv = atoi(v->value); 11373 if (mtuv == 0 ) 11374 global_max_trunk_mtu = 0; 11375 else if (mtuv >= 172 && mtuv < 4000) 11376 global_max_trunk_mtu = mtuv; 11377 else 11378 ast_log(LOG_NOTICE, "trunkmtu value out of bounds (%d) at line %d\n", 11379 mtuv, v->lineno); 11380 } else if (!strcasecmp(v->name, "trunkmaxsize")) { 11381 trunkmaxsize = atoi(v->value); 11382 if (trunkmaxsize == 0) 11383 trunkmaxsize = MAX_TRUNKDATA; 11384 } else if (!strcasecmp(v->name, "autokill")) { 11385 if (sscanf(v->value, "%d", &x) == 1) { 11386 if (x >= 0) 11387 autokill = x; 11388 else 11389 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 11390 } else if (ast_true(v->value)) { 11391 autokill = DEFAULT_MAXMS; 11392 } else { 11393 autokill = 0; 11394 } 11395 } else if (!strcasecmp(v->name, "bandwidth")) { 11396 if (!strcasecmp(v->value, "low")) { 11397 capability = IAX_CAPABILITY_LOWBANDWIDTH; 11398 } else if (!strcasecmp(v->value, "medium")) { 11399 capability = IAX_CAPABILITY_MEDBANDWIDTH; 11400 } else if (!strcasecmp(v->value, "high")) { 11401 capability = IAX_CAPABILITY_FULLBANDWIDTH; 11402 } else 11403 ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); 11404 } else if (!strcasecmp(v->name, "allow")) { 11405 ast_parse_allow_disallow(&prefs, &capability, v->value, 1); 11406 } else if (!strcasecmp(v->name, "disallow")) { 11407 ast_parse_allow_disallow(&prefs, &capability, v->value, 0); 11408 } else if (!strcasecmp(v->name, "register")) { 11409 iax2_register(v->value, v->lineno); 11410 } else if (!strcasecmp(v->name, "iaxcompat")) { 11411 iaxcompat = ast_true(v->value); 11412 } else if (!strcasecmp(v->name, "regcontext")) { 11413 ast_copy_string(regcontext, v->value, sizeof(regcontext)); 11414 /* Create context if it doesn't exist already */ 11415 ast_context_find_or_create(NULL, NULL, regcontext, "IAX2"); 11416 } else if (!strcasecmp(v->name, "tos")) { 11417 if (ast_str2tos(v->value, &qos.tos)) 11418 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 11419 } else if (!strcasecmp(v->name, "cos")) { 11420 if (ast_str2cos(v->value, &qos.cos)) 11421 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 11422 } else if (!strcasecmp(v->name, "parkinglot")) { 11423 ast_copy_string(default_parkinglot, v->value, sizeof(default_parkinglot)); 11424 } else if (!strcasecmp(v->name, "accountcode")) { 11425 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 11426 } else if (!strcasecmp(v->name, "mohinterpret")) { 11427 ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); 11428 } else if (!strcasecmp(v->name, "mohsuggest")) { 11429 ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest)); 11430 } else if (!strcasecmp(v->name, "amaflags")) { 11431 format = ast_cdr_amaflags2int(v->value); 11432 if (format < 0) { 11433 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 11434 } else { 11435 amaflags = format; 11436 } 11437 } else if (!strcasecmp(v->name, "language")) { 11438 ast_copy_string(language, v->value, sizeof(language)); 11439 } else if (!strcasecmp(v->name, "maxauthreq")) { 11440 maxauthreq = atoi(v->value); 11441 if (maxauthreq < 0) 11442 maxauthreq = 0; 11443 } else if (!strcasecmp(v->name, "adsi")) { 11444 adsi = ast_true(v->value); 11445 } else if (!strcasecmp(v->name, "srvlookup")) { 11446 srvlookup = ast_true(v->value); 11447 } /*else if (strcasecmp(v->name,"type")) */ 11448 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 11449 v = v->next; 11450 } 11451 11452 if (defaultsockfd < 0) { 11453 if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, qos.tos, qos.cos, socket_read, NULL))) { 11454 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 11455 } else { 11456 ast_verb(2, "Binding IAX2 to default address 0.0.0.0:%d\n", portno); 11457 defaultsockfd = ast_netsock_sockfd(ns); 11458 ast_netsock_unref(ns); 11459 } 11460 } 11461 if (reload) { 11462 ast_netsock_release(outsock); 11463 outsock = ast_netsock_list_alloc(); 11464 if (!outsock) { 11465 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 11466 return -1; 11467 } 11468 ast_netsock_init(outsock); 11469 } 11470 11471 if (min_reg_expire > max_reg_expire) { 11472 ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n", 11473 min_reg_expire, max_reg_expire, max_reg_expire); 11474 min_reg_expire = max_reg_expire; 11475 } 11476 iax2_capability = capability; 11477 11478 if (ucfg) { 11479 struct ast_variable *gen; 11480 int genhasiax; 11481 int genregisteriax; 11482 const char *hasiax, *registeriax; 11483 11484 genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); 11485 genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); 11486 gen = ast_variable_browse(ucfg, "general"); 11487 cat = ast_category_browse(ucfg, NULL); 11488 while (cat) { 11489 if (strcasecmp(cat, "general")) { 11490 hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); 11491 registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); 11492 if (ast_true(hasiax) || (!hasiax && genhasiax)) { 11493 /* Start with general parameters, then specific parameters, user and peer */ 11494 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 11495 if (user) { 11496 ao2_link(users, user); 11497 user = user_unref(user); 11498 } 11499 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 11500 if (peer) { 11501 if (ast_test_flag(peer, IAX_DYNAMIC)) 11502 reg_source_db(peer); 11503 ao2_link(peers, peer); 11504 peer = peer_unref(peer); 11505 } 11506 } 11507 if (ast_true(registeriax) || (!registeriax && genregisteriax)) { 11508 char tmp[256]; 11509 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 11510 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 11511 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 11512 if (!host) 11513 host = ast_variable_retrieve(ucfg, "general", "host"); 11514 if (!username) 11515 username = ast_variable_retrieve(ucfg, "general", "username"); 11516 if (!secret) 11517 secret = ast_variable_retrieve(ucfg, "general", "secret"); 11518 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 11519 if (!ast_strlen_zero(secret)) 11520 snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); 11521 else 11522 snprintf(tmp, sizeof(tmp), "%s@%s", username, host); 11523 iax2_register(tmp, 0); 11524 } 11525 } 11526 } 11527 cat = ast_category_browse(ucfg, cat); 11528 } 11529 ast_config_destroy(ucfg); 11530 } 11531 11532 cat = ast_category_browse(cfg, NULL); 11533 while(cat) { 11534 if (strcasecmp(cat, "general")) { 11535 utype = ast_variable_retrieve(cfg, cat, "type"); 11536 if (utype) { 11537 if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { 11538 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 11539 if (user) { 11540 ao2_link(users, user); 11541 user = user_unref(user); 11542 } 11543 } 11544 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { 11545 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 11546 if (peer) { 11547 if (ast_test_flag(peer, IAX_DYNAMIC)) 11548 reg_source_db(peer); 11549 ao2_link(peers, peer); 11550 peer = peer_unref(peer); 11551 } 11552 } else if (strcasecmp(utype, "user")) { 11553 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file); 11554 } 11555 } else 11556 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 11557 } 11558 cat = ast_category_browse(cfg, cat); 11559 } 11560 ast_config_destroy(cfg); 11561 return 1; 11562 }
static void set_config_destroy | ( | void | ) | [static] |
Definition at line 11151 of file chan_iax2.c.
References ast_clear_flag, delete_users(), globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, MAX_TRUNK_MTU, and MAX_TRUNKDATA.
Referenced by set_config().
11152 { 11153 strcpy(accountcode, ""); 11154 strcpy(language, ""); 11155 strcpy(mohinterpret, "default"); 11156 strcpy(mohsuggest, ""); 11157 global_max_trunk_mtu = MAX_TRUNK_MTU; 11158 trunkmaxsize = MAX_TRUNKDATA; 11159 amaflags = 0; 11160 delayreject = 0; 11161 ast_clear_flag((&globalflags), IAX_NOTRANSFER); 11162 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 11163 ast_clear_flag((&globalflags), IAX_USEJITTERBUF); 11164 ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF); 11165 delete_users(); 11166 }
static void signal_condition | ( | ast_mutex_t * | lock, | |
ast_cond_t * | cond | |||
) | [static] |
Definition at line 807 of file chan_iax2.c.
References ast_cond_signal(), ast_mutex_lock(), and ast_mutex_unlock().
Referenced by __schedule_action(), iax2_process_thread(), iax2_sched_add(), iax2_sched_replace(), iax2_transmit(), and socket_read().
00808 { 00809 ast_mutex_lock(lock); 00810 ast_cond_signal(cond); 00811 ast_mutex_unlock(lock); 00812 }
static int socket_process | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 8244 of file chan_iax2.c.
References ast_aes_decrypt_key, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), ast_calloc, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_channel_datastore_add(), ast_channel_trylock, ast_channel_unlock, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_datastore_alloc(), ast_datastore_free(), ast_debug, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNAVAILABLE, ast_devstate_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_free, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_sched_del(), AST_SCHED_DEL, ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_var_assign(), ast_variables_destroy(), ast_verb, auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax_ies::called_number, iax_ies::callno, iax2_peer::callno, iax2_dpcache::callno, iax_frame::callno, iax_ies::cause, iax_ies::causecode, iax_ies::challenge, check_access(), check_provisioning(), cid_num, iax_ies::codec_prefs, complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, DEADLOCK_AVOIDANCE, decrypt_frame(), iax_ies::devicetype, dp_lookup(), iax_ies::encmethods, ast_var_t::entries, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), iax2_dpcache::flags, iax_ies::format, format, ast_frame::frametype, iax_ies::fwdesc, globalflags, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_variable_datastore_info, iax2_vnak(), IAX_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CALLENCRYPTED, 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_RTKEY, 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_DEBUGDIGEST, 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_outputframe(), iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), inaddrcmp(), ast_datastore::inheritance, iax2_peer::lastms, LOG_ERROR, log_jitterstats(), LOG_NOTICE, LOG_WARNING, make_trunk(), manager_event, iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, iax_ies::musiconhold, iax2_peer::name, ast_channel::name, NEW_ALLOW, NEW_PREVENT, iax_frame::oseqno, pbx_builtin_setvar_helper(), peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, iax_ies::provver, iax_ies::provverpres, raw_hangup(), iax_ies::refresh, REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, S_OR, save_osptoken(), save_rr(), sched, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, socket_process_meta(), spawn_dp_lookup(), stop_stuff(), store_by_peercallno(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, try_transfer(), iax_frame::ts, uncompress_subclass(), update_registry(), iax_ies::username, var, iax_ies::vars, VERBOSE_PREFIX_4, vnak_retransmit(), and ast_iax2_meta_hdr::zeros.
Referenced by handle_deferred_full_frames().
08245 { 08246 struct sockaddr_in sin; 08247 int res; 08248 int updatehistory=1; 08249 int new = NEW_PREVENT; 08250 int dcallno = 0; 08251 struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf; 08252 struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf; 08253 struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf; 08254 struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf; 08255 struct iax_frame *fr; 08256 struct iax_frame *cur; 08257 struct ast_frame f = { 0, }; 08258 struct ast_channel *c = NULL; 08259 struct iax2_dpcache *dp; 08260 struct iax2_peer *peer; 08261 struct iax_ies ies; 08262 struct iax_ie_data ied0, ied1; 08263 int format; 08264 int fd; 08265 int exists; 08266 int minivid = 0; 08267 char empty[32]=""; /* Safety measure */ 08268 struct iax_frame *duped_fr; 08269 char host_pref_buf[128]; 08270 char caller_pref_buf[128]; 08271 struct ast_codec_pref pref; 08272 char *using_prefs = "mine"; 08273 08274 /* allocate an iax_frame with 4096 bytes of data buffer */ 08275 fr = alloca(sizeof(*fr) + 4096); 08276 memset(fr, 0, sizeof(*fr)); 08277 fr->afdatalen = 4096; /* From alloca() above */ 08278 08279 /* Copy frequently used parameters to the stack */ 08280 res = thread->buf_len; 08281 fd = thread->iofd; 08282 memcpy(&sin, &thread->iosin, sizeof(sin)); 08283 08284 if (res < sizeof(*mh)) { 08285 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int) sizeof(*mh)); 08286 return 1; 08287 } 08288 if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { 08289 if (res < sizeof(*vh)) { 08290 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)); 08291 return 1; 08292 } 08293 08294 /* This is a video frame, get call number */ 08295 fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0); 08296 minivid = 1; 08297 } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) 08298 return socket_process_meta(res, meta, &sin, fd, fr); 08299 08300 #ifdef DEBUG_SUPPORT 08301 if (res >= sizeof(*fh)) 08302 iax_outputframe(NULL, fh, 1, &sin, res - sizeof(*fh)); 08303 #endif 08304 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08305 if (res < sizeof(*fh)) { 08306 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)); 08307 return 1; 08308 } 08309 08310 /* Get the destination call number */ 08311 dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; 08312 /* Retrieve the type and subclass */ 08313 f.frametype = fh->type; 08314 if (f.frametype == AST_FRAME_VIDEO) { 08315 f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 08316 } else { 08317 f.subclass = uncompress_subclass(fh->csub); 08318 } 08319 08320 /* Deal with POKE/PONG without allocating a callno */ 08321 if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) { 08322 /* Reply back with a PONG, but don't care about the result. */ 08323 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohs(fh->ts), fh->iseqno + 1); 08324 return 1; 08325 } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) { 08326 /* Ignore */ 08327 return 1; 08328 } 08329 08330 if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) || 08331 (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) || 08332 (f.subclass == IAX_COMMAND_REGREL))) 08333 new = NEW_ALLOW; 08334 } else { 08335 /* Don't know anything about it yet */ 08336 f.frametype = AST_FRAME_NULL; 08337 f.subclass = 0; 08338 } 08339 08340 if (!fr->callno) { 08341 int check_dcallno = 0; 08342 08343 /* 08344 * We enforce accurate destination call numbers for all full frames except 08345 * LAGRQ and PING commands. This is because older versions of Asterisk 08346 * schedule these commands to get sent very quickly, and they will sometimes 08347 * be sent before they receive the first frame from the other side. When 08348 * that happens, it doesn't contain the destination call number. However, 08349 * not checking it for these frames is safe. 08350 * 08351 * Discussed in the following thread: 08352 * http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 08353 */ 08354 08355 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08356 check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1; 08357 } 08358 08359 fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno); 08360 } 08361 08362 if (fr->callno > 0) 08363 ast_mutex_lock(&iaxsl[fr->callno]); 08364 08365 if (!fr->callno || !iaxs[fr->callno]) { 08366 /* A call arrived for a nonexistent destination. Unless it's an "inval" 08367 frame, reply with an inval */ 08368 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08369 /* We can only raw hangup control frames */ 08370 if (((f.subclass != IAX_COMMAND_INVAL) && 08371 (f.subclass != IAX_COMMAND_TXCNT) && 08372 (f.subclass != IAX_COMMAND_TXACC) && 08373 (f.subclass != IAX_COMMAND_FWDOWNL))|| 08374 (f.frametype != AST_FRAME_IAX)) 08375 raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL, 08376 fd); 08377 } 08378 if (fr->callno > 0) 08379 ast_mutex_unlock(&iaxsl[fr->callno]); 08380 return 1; 08381 } 08382 if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) { 08383 if (decrypt_frame(fr->callno, fh, &f, &res)) { 08384 ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); 08385 ast_mutex_unlock(&iaxsl[fr->callno]); 08386 return 1; 08387 } 08388 #ifdef DEBUG_SUPPORT 08389 else 08390 iax_outputframe(NULL, fh, 3, &sin, res - sizeof(*fh)); 08391 #endif 08392 } 08393 08394 /* count this frame */ 08395 iaxs[fr->callno]->frames_received++; 08396 08397 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid && 08398 f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */ 08399 f.subclass != IAX_COMMAND_TXACC) { /* for attended transfer */ 08400 unsigned short new_peercallno; 08401 08402 new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL); 08403 if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) { 08404 if (iaxs[fr->callno]->peercallno) { 08405 remove_by_peercallno(iaxs[fr->callno]); 08406 } 08407 iaxs[fr->callno]->peercallno = new_peercallno; 08408 store_by_peercallno(iaxs[fr->callno]); 08409 } 08410 } 08411 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08412 if (iaxdebug) 08413 ast_debug(1, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); 08414 /* Check if it's out of order (and not an ACK or INVAL) */ 08415 fr->oseqno = fh->oseqno; 08416 fr->iseqno = fh->iseqno; 08417 fr->ts = ntohl(fh->ts); 08418 #ifdef IAXTESTS 08419 if (test_resync) { 08420 ast_debug(1, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync); 08421 fr->ts += test_resync; 08422 } 08423 #endif /* IAXTESTS */ 08424 #if 0 08425 if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || 08426 ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX && 08427 (f.subclass == IAX_COMMAND_NEW || 08428 f.subclass == IAX_COMMAND_AUTHREQ || 08429 f.subclass == IAX_COMMAND_ACCEPT || 08430 f.subclass == IAX_COMMAND_REJECT)) ) ) 08431 #endif 08432 if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE)) 08433 updatehistory = 0; 08434 if ((iaxs[fr->callno]->iseqno != fr->oseqno) && 08435 (iaxs[fr->callno]->iseqno || 08436 ((f.subclass != IAX_COMMAND_TXCNT) && 08437 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 08438 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 08439 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 08440 (f.subclass != IAX_COMMAND_TXACC)) || 08441 (f.frametype != AST_FRAME_IAX))) { 08442 if ( 08443 ((f.subclass != IAX_COMMAND_ACK) && 08444 (f.subclass != IAX_COMMAND_INVAL) && 08445 (f.subclass != IAX_COMMAND_TXCNT) && 08446 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 08447 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 08448 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 08449 (f.subclass != IAX_COMMAND_TXACC) && 08450 (f.subclass != IAX_COMMAND_VNAK)) || 08451 (f.frametype != AST_FRAME_IAX)) { 08452 /* If it's not an ACK packet, it's out of order. */ 08453 ast_debug(1, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 08454 iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass); 08455 /* Check to see if we need to request retransmission, 08456 * and take sequence number wraparound into account */ 08457 if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) { 08458 /* If we've already seen it, ack it XXX There's a border condition here XXX */ 08459 if ((f.frametype != AST_FRAME_IAX) || 08460 ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) { 08461 ast_debug(1, "Acking anyway\n"); 08462 /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if 08463 we have anything to send, we'll retransmit and get an ACK back anyway XXX */ 08464 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08465 } 08466 } else { 08467 /* Send a VNAK requesting retransmission */ 08468 iax2_vnak(fr->callno); 08469 } 08470 ast_mutex_unlock(&iaxsl[fr->callno]); 08471 return 1; 08472 } 08473 } else { 08474 /* Increment unless it's an ACK or VNAK */ 08475 if (((f.subclass != IAX_COMMAND_ACK) && 08476 (f.subclass != IAX_COMMAND_INVAL) && 08477 (f.subclass != IAX_COMMAND_TXCNT) && 08478 (f.subclass != IAX_COMMAND_TXACC) && 08479 (f.subclass != IAX_COMMAND_VNAK)) || 08480 (f.frametype != AST_FRAME_IAX)) 08481 iaxs[fr->callno]->iseqno++; 08482 } 08483 /* A full frame */ 08484 if (res < sizeof(*fh)) { 08485 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int) sizeof(*fh)); 08486 ast_mutex_unlock(&iaxsl[fr->callno]); 08487 return 1; 08488 } 08489 /* Ensure text frames are NULL-terminated */ 08490 if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') { 08491 if (res < thread->buf_size) 08492 thread->buf[res++] = '\0'; 08493 else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */ 08494 thread->buf[res - 1] = '\0'; 08495 } 08496 f.datalen = res - sizeof(*fh); 08497 08498 /* Handle implicit ACKing unless this is an INVAL, and only if this is 08499 from the real peer, not the transfer peer */ 08500 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 08501 ((f.subclass != IAX_COMMAND_INVAL) || 08502 (f.frametype != AST_FRAME_IAX))) { 08503 unsigned char x; 08504 int call_to_destroy; 08505 /* First we have to qualify that the ACKed value is within our window */ 08506 if (iaxs[fr->callno]->rseqno >= iaxs[fr->callno]->oseqno || (fr->iseqno >= iaxs[fr->callno]->rseqno && fr->iseqno < iaxs[fr->callno]->oseqno)) 08507 x = fr->iseqno; 08508 else 08509 x = iaxs[fr->callno]->oseqno; 08510 if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) { 08511 /* The acknowledgement is within our window. Time to acknowledge everything 08512 that it says to */ 08513 for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) { 08514 /* Ack the packet with the given timestamp */ 08515 if (iaxdebug) 08516 ast_debug(1, "Cancelling transmission of packet %d\n", x); 08517 call_to_destroy = 0; 08518 AST_LIST_LOCK(&frame_queue); 08519 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 08520 /* If it's our call, and our timestamp, mark -1 retries */ 08521 if ((fr->callno == cur->callno) && (x == cur->oseqno)) { 08522 cur->retries = -1; 08523 /* Destroy call if this is the end */ 08524 if (cur->final) 08525 call_to_destroy = fr->callno; 08526 } 08527 } 08528 AST_LIST_UNLOCK(&frame_queue); 08529 if (call_to_destroy) { 08530 if (iaxdebug) 08531 ast_debug(1, "Really destroying %d, having been acked on final message\n", call_to_destroy); 08532 ast_mutex_lock(&iaxsl[call_to_destroy]); 08533 iax2_destroy(call_to_destroy); 08534 ast_mutex_unlock(&iaxsl[call_to_destroy]); 08535 } 08536 } 08537 /* Note how much we've received acknowledgement for */ 08538 if (iaxs[fr->callno]) 08539 iaxs[fr->callno]->rseqno = fr->iseqno; 08540 else { 08541 /* Stop processing now */ 08542 ast_mutex_unlock(&iaxsl[fr->callno]); 08543 return 1; 08544 } 08545 } else { 08546 ast_debug(1, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno); 08547 } 08548 } 08549 if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 08550 ((f.frametype != AST_FRAME_IAX) || 08551 ((f.subclass != IAX_COMMAND_TXACC) && 08552 (f.subclass != IAX_COMMAND_TXCNT)))) { 08553 /* Only messages we accept from a transfer host are TXACC and TXCNT */ 08554 ast_mutex_unlock(&iaxsl[fr->callno]); 08555 return 1; 08556 } 08557 08558 if (f.datalen) { 08559 if (f.frametype == AST_FRAME_IAX) { 08560 if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) { 08561 ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); 08562 ast_mutex_unlock(&iaxsl[fr->callno]); 08563 return 1; 08564 } 08565 f.data.ptr = NULL; 08566 f.datalen = 0; 08567 } else { 08568 f.data.ptr = thread->buf + sizeof(*fh); 08569 memset(&ies, 0, sizeof(ies)); 08570 } 08571 } else { 08572 if (f.frametype == AST_FRAME_IAX) 08573 f.data.ptr = NULL; 08574 else 08575 f.data.ptr = empty; 08576 memset(&ies, 0, sizeof(ies)); 08577 } 08578 08579 /* when we receive the first full frame for a new incoming channel, 08580 it is safe to start the PBX on the channel because we have now 08581 completed a 3-way handshake with the peer */ 08582 if ((f.frametype == AST_FRAME_VOICE) || 08583 (f.frametype == AST_FRAME_VIDEO) || 08584 (f.frametype == AST_FRAME_IAX)) { 08585 if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) { 08586 ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 08587 if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) { 08588 ast_mutex_unlock(&iaxsl[fr->callno]); 08589 return 1; 08590 } 08591 } 08592 08593 if (ies.vars) { 08594 struct ast_datastore *variablestore = NULL; 08595 struct ast_variable *var, *prev = NULL; 08596 AST_LIST_HEAD(, ast_var_t) *varlist; 08597 if ((c = iaxs[fr->callno]->owner)) { 08598 varlist = ast_calloc(1, sizeof(*varlist)); 08599 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 08600 08601 if (variablestore && varlist) { 08602 variablestore->data = varlist; 08603 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 08604 AST_LIST_HEAD_INIT(varlist); 08605 ast_debug(1, "I can haz IAX vars?\n"); 08606 for (var = ies.vars; var; var = var->next) { 08607 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 08608 if (prev) { 08609 ast_free(prev); 08610 } 08611 prev = var; 08612 if (!newvar) { 08613 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 08614 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 08615 } else { 08616 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 08617 } 08618 } 08619 if (prev) { 08620 ast_free(prev); 08621 } 08622 ies.vars = NULL; 08623 ast_channel_datastore_add(c, variablestore); 08624 } else { 08625 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 08626 if (variablestore) { 08627 ast_datastore_free(variablestore); 08628 } 08629 if (varlist) { 08630 ast_free(varlist); 08631 } 08632 } 08633 } else { 08634 /* No channel yet, so transfer the variables directly over to the pvt, 08635 * for later inheritance. */ 08636 ast_debug(1, "No channel, so populating IAXVARs to the pvt, as an intermediate step.\n"); 08637 for (var = ies.vars; var && var->next; var = var->next); 08638 if (var) { 08639 var->next = iaxs[fr->callno]->iaxvars; 08640 iaxs[fr->callno]->iaxvars = ies.vars; 08641 ies.vars = NULL; 08642 } 08643 } 08644 } 08645 08646 if (ies.vars) { 08647 ast_debug(1, "I have IAX variables, but they were not processed\n"); 08648 } 08649 } 08650 08651 if (f.frametype == AST_FRAME_VOICE) { 08652 if (f.subclass != iaxs[fr->callno]->voiceformat) { 08653 iaxs[fr->callno]->voiceformat = f.subclass; 08654 ast_debug(1, "Ooh, voice format changed to %d\n", f.subclass); 08655 if (iaxs[fr->callno]->owner) { 08656 int orignative; 08657 retryowner: 08658 if (ast_channel_trylock(iaxs[fr->callno]->owner)) { 08659 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 08660 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; 08661 } 08662 if (iaxs[fr->callno]) { 08663 if (iaxs[fr->callno]->owner) { 08664 orignative = iaxs[fr->callno]->owner->nativeformats; 08665 iaxs[fr->callno]->owner->nativeformats = f.subclass; 08666 if (iaxs[fr->callno]->owner->readformat) 08667 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 08668 iaxs[fr->callno]->owner->nativeformats = orignative; 08669 ast_channel_unlock(iaxs[fr->callno]->owner); 08670 } 08671 } else { 08672 ast_debug(1, "Neat, somebody took away the channel at a magical time but i found it!\n"); 08673 /* Free remote variables (if any) */ 08674 if (ies.vars) { 08675 ast_variables_destroy(ies.vars); 08676 ast_debug(1, "I can haz iaxvars, but they is no good. :-(\n"); 08677 ies.vars = NULL; 08678 } 08679 ast_mutex_unlock(&iaxsl[fr->callno]); 08680 return 1; 08681 } 08682 } 08683 } 08684 } 08685 if (f.frametype == AST_FRAME_VIDEO) { 08686 if (f.subclass != iaxs[fr->callno]->videoformat) { 08687 ast_debug(1, "Ooh, video format changed to %d\n", f.subclass & ~0x1); 08688 iaxs[fr->callno]->videoformat = f.subclass & ~0x1; 08689 } 08690 } 08691 if (f.frametype == AST_FRAME_CONTROL && iaxs[fr->callno]->owner) { 08692 if (f.subclass == AST_CONTROL_BUSY) { 08693 iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_BUSY; 08694 } else if (f.subclass == AST_CONTROL_CONGESTION) { 08695 iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_CONGESTION; 08696 } 08697 } 08698 if (f.frametype == AST_FRAME_IAX) { 08699 AST_SCHED_DEL(sched, iaxs[fr->callno]->initid); 08700 /* Handle the IAX pseudo frame itself */ 08701 if (iaxdebug) 08702 ast_debug(1, "IAX subclass %d received\n", f.subclass); 08703 08704 /* Update last ts unless the frame's timestamp originated with us. */ 08705 if (iaxs[fr->callno]->last < fr->ts && 08706 f.subclass != IAX_COMMAND_ACK && 08707 f.subclass != IAX_COMMAND_PONG && 08708 f.subclass != IAX_COMMAND_LAGRP) { 08709 iaxs[fr->callno]->last = fr->ts; 08710 if (iaxdebug) 08711 ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts); 08712 } 08713 08714 switch(f.subclass) { 08715 case IAX_COMMAND_ACK: 08716 /* Do nothing */ 08717 break; 08718 case IAX_COMMAND_QUELCH: 08719 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08720 /* Generate Manager Hold event, if necessary*/ 08721 if (iaxs[fr->callno]->owner) { 08722 manager_event(EVENT_FLAG_CALL, "Hold", 08723 "Status: On\r\n" 08724 "Channel: %s\r\n" 08725 "Uniqueid: %s\r\n", 08726 iaxs[fr->callno]->owner->name, 08727 iaxs[fr->callno]->owner->uniqueid); 08728 } 08729 08730 ast_set_flag(iaxs[fr->callno], IAX_QUELCH); 08731 if (ies.musiconhold) { 08732 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 08733 const char *moh_suggest = iaxs[fr->callno]->mohsuggest; 08734 iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 08735 S_OR(moh_suggest, NULL), 08736 !ast_strlen_zero(moh_suggest) ? strlen(moh_suggest) + 1 : 0); 08737 if (!iaxs[fr->callno]) { 08738 ast_mutex_unlock(&iaxsl[fr->callno]); 08739 return 1; 08740 } 08741 } 08742 } 08743 } 08744 break; 08745 case IAX_COMMAND_UNQUELCH: 08746 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08747 /* Generate Manager Unhold event, if necessary*/ 08748 if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) { 08749 manager_event(EVENT_FLAG_CALL, "Hold", 08750 "Status: Off\r\n" 08751 "Channel: %s\r\n" 08752 "Uniqueid: %s\r\n", 08753 iaxs[fr->callno]->owner->name, 08754 iaxs[fr->callno]->owner->uniqueid); 08755 } 08756 08757 ast_clear_flag(iaxs[fr->callno], IAX_QUELCH); 08758 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 08759 iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); 08760 if (!iaxs[fr->callno]) { 08761 ast_mutex_unlock(&iaxsl[fr->callno]); 08762 return 1; 08763 } 08764 } 08765 } 08766 break; 08767 case IAX_COMMAND_TXACC: 08768 if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { 08769 /* Ack the packet with the given timestamp */ 08770 AST_LIST_LOCK(&frame_queue); 08771 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 08772 /* Cancel any outstanding txcnt's */ 08773 if ((fr->callno == cur->callno) && (cur->transfer)) 08774 cur->retries = -1; 08775 } 08776 AST_LIST_UNLOCK(&frame_queue); 08777 memset(&ied1, 0, sizeof(ied1)); 08778 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno); 08779 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1); 08780 iaxs[fr->callno]->transferring = TRANSFER_READY; 08781 } 08782 break; 08783 case IAX_COMMAND_NEW: 08784 /* Ignore if it's already up */ 08785 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) 08786 break; 08787 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 08788 ast_mutex_unlock(&iaxsl[fr->callno]); 08789 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 08790 ast_mutex_lock(&iaxsl[fr->callno]); 08791 if (!iaxs[fr->callno]) { 08792 ast_mutex_unlock(&iaxsl[fr->callno]); 08793 return 1; 08794 } 08795 } 08796 /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ 08797 if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) { 08798 int new_callno; 08799 if ((new_callno = make_trunk(fr->callno, 1)) != -1) 08800 fr->callno = new_callno; 08801 } 08802 /* For security, always ack immediately */ 08803 if (delayreject) 08804 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08805 if (check_access(fr->callno, &sin, &ies)) { 08806 /* They're not allowed on */ 08807 auth_fail(fr->callno, IAX_COMMAND_REJECT); 08808 if (authdebug) 08809 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); 08810 break; 08811 } 08812 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 08813 const char *context, *exten, *cid_num; 08814 08815 context = ast_strdupa(iaxs[fr->callno]->context); 08816 exten = ast_strdupa(iaxs[fr->callno]->exten); 08817 cid_num = ast_strdupa(iaxs[fr->callno]->cid_num); 08818 08819 /* This might re-enter the IAX code and need the lock */ 08820 ast_mutex_unlock(&iaxsl[fr->callno]); 08821 exists = ast_exists_extension(NULL, context, exten, 1, cid_num); 08822 ast_mutex_lock(&iaxsl[fr->callno]); 08823 08824 if (!iaxs[fr->callno]) { 08825 ast_mutex_unlock(&iaxsl[fr->callno]); 08826 return 1; 08827 } 08828 } else 08829 exists = 0; 08830 /* Get OSP token if it does exist */ 08831 save_osptoken(fr, &ies); 08832 if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { 08833 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 08834 memset(&ied0, 0, sizeof(ied0)); 08835 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08836 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 08837 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08838 if (!iaxs[fr->callno]) { 08839 ast_mutex_unlock(&iaxsl[fr->callno]); 08840 return 1; 08841 } 08842 if (authdebug) 08843 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); 08844 } else { 08845 /* Select an appropriate format */ 08846 08847 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08848 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08849 using_prefs = "reqonly"; 08850 } else { 08851 using_prefs = "disabled"; 08852 } 08853 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 08854 memset(&pref, 0, sizeof(pref)); 08855 strcpy(caller_pref_buf, "disabled"); 08856 strcpy(host_pref_buf, "disabled"); 08857 } else { 08858 using_prefs = "mine"; 08859 /* If the information elements are in here... use them */ 08860 if (ies.codec_prefs) 08861 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 08862 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08863 /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ 08864 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08865 pref = iaxs[fr->callno]->rprefs; 08866 using_prefs = "caller"; 08867 } else { 08868 pref = iaxs[fr->callno]->prefs; 08869 } 08870 } else 08871 pref = iaxs[fr->callno]->prefs; 08872 08873 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 08874 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 08875 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 08876 } 08877 if (!format) { 08878 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08879 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 08880 if (!format) { 08881 memset(&ied0, 0, sizeof(ied0)); 08882 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08883 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08884 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08885 if (!iaxs[fr->callno]) { 08886 ast_mutex_unlock(&iaxsl[fr->callno]); 08887 return 1; 08888 } 08889 if (authdebug) { 08890 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08891 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); 08892 else 08893 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); 08894 } 08895 } else { 08896 /* Pick one... */ 08897 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08898 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 08899 format = 0; 08900 } else { 08901 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08902 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 08903 memset(&pref, 0, sizeof(pref)); 08904 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08905 strcpy(caller_pref_buf,"disabled"); 08906 strcpy(host_pref_buf,"disabled"); 08907 } else { 08908 using_prefs = "mine"; 08909 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08910 /* Do the opposite of what we tried above. */ 08911 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08912 pref = iaxs[fr->callno]->prefs; 08913 } else { 08914 pref = iaxs[fr->callno]->rprefs; 08915 using_prefs = "caller"; 08916 } 08917 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 08918 08919 } else /* if no codec_prefs IE do it the old way */ 08920 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08921 } 08922 } 08923 08924 if (!format) { 08925 memset(&ied0, 0, sizeof(ied0)); 08926 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08927 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08928 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08929 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08930 if (!iaxs[fr->callno]) { 08931 ast_mutex_unlock(&iaxsl[fr->callno]); 08932 return 1; 08933 } 08934 if (authdebug) 08935 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); 08936 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 08937 break; 08938 } 08939 } 08940 } 08941 if (format) { 08942 /* No authentication required, let them in */ 08943 memset(&ied1, 0, sizeof(ied1)); 08944 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 08945 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 08946 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 08947 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08948 ast_verb(3, "Accepting UNAUTHENTICATED call from %s:\n" 08949 "%srequested format = %s,\n" 08950 "%srequested prefs = %s,\n" 08951 "%sactual format = %s,\n" 08952 "%shost prefs = %s,\n" 08953 "%spriority = %s\n", 08954 ast_inet_ntoa(sin.sin_addr), 08955 VERBOSE_PREFIX_4, 08956 ast_getformatname(iaxs[fr->callno]->peerformat), 08957 VERBOSE_PREFIX_4, 08958 caller_pref_buf, 08959 VERBOSE_PREFIX_4, 08960 ast_getformatname(format), 08961 VERBOSE_PREFIX_4, 08962 host_pref_buf, 08963 VERBOSE_PREFIX_4, 08964 using_prefs); 08965 08966 iaxs[fr->callno]->chosenformat = format; 08967 ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 08968 } else { 08969 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08970 /* If this is a TBD call, we're ready but now what... */ 08971 ast_verb(3, "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 08972 } 08973 } 08974 } 08975 break; 08976 } 08977 if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5) 08978 merge_encryption(iaxs[fr->callno],ies.encmethods); 08979 else 08980 iaxs[fr->callno]->encmethods = 0; 08981 if (!authenticate_request(fr->callno) && iaxs[fr->callno]) 08982 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); 08983 if (!iaxs[fr->callno]) { 08984 ast_mutex_unlock(&iaxsl[fr->callno]); 08985 return 1; 08986 } 08987 break; 08988 case IAX_COMMAND_DPREQ: 08989 /* Request status in the dialplan */ 08990 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) && 08991 !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) { 08992 if (iaxcompat) { 08993 /* Spawn a thread for the lookup */ 08994 spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num); 08995 } else { 08996 /* Just look it up */ 08997 dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1); 08998 } 08999 } 09000 break; 09001 case IAX_COMMAND_HANGUP: 09002 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 09003 ast_debug(1, "Immediately destroying %d, having received hangup\n", fr->callno); 09004 /* Set hangup cause according to remote */ 09005 if (ies.causecode && iaxs[fr->callno]->owner) 09006 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 09007 /* Send ack immediately, before we destroy */ 09008 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09009 iax2_destroy(fr->callno); 09010 break; 09011 case IAX_COMMAND_REJECT: 09012 /* Set hangup cause according to remote */ 09013 if (ies.causecode && iaxs[fr->callno]->owner) 09014 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 09015 09016 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 09017 if (iaxs[fr->callno]->owner && authdebug) 09018 ast_log(LOG_WARNING, "Call rejected by %s: %s\n", 09019 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), 09020 ies.cause ? ies.cause : "<Unknown>"); 09021 ast_debug(1, "Immediately destroying %d, having received reject\n", 09022 fr->callno); 09023 } 09024 /* Send ack immediately, before we destroy */ 09025 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, 09026 fr->ts, NULL, 0, fr->iseqno); 09027 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) 09028 iaxs[fr->callno]->error = EPERM; 09029 iax2_destroy(fr->callno); 09030 break; 09031 case IAX_COMMAND_TRANSFER: 09032 { 09033 struct ast_channel *bridged_chan; 09034 09035 if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) { 09036 /* Set BLINDTRANSFER channel variables */ 09037 09038 ast_mutex_unlock(&iaxsl[fr->callno]); 09039 pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name); 09040 ast_mutex_lock(&iaxsl[fr->callno]); 09041 if (!iaxs[fr->callno]) { 09042 ast_mutex_unlock(&iaxsl[fr->callno]); 09043 return 1; 09044 } 09045 09046 pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name); 09047 if (!strcmp(ies.called_number, ast_parking_ext())) { 09048 struct ast_channel *saved_channel = iaxs[fr->callno]->owner; 09049 ast_mutex_unlock(&iaxsl[fr->callno]); 09050 if (iax_park(bridged_chan, saved_channel)) { 09051 ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name); 09052 } else { 09053 ast_debug(1, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name); 09054 } 09055 ast_mutex_lock(&iaxsl[fr->callno]); 09056 } else { 09057 if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1)) 09058 ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 09059 ies.called_number, iaxs[fr->callno]->context); 09060 else { 09061 ast_debug(1, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 09062 ies.called_number, iaxs[fr->callno]->context); 09063 } 09064 } 09065 } else { 09066 ast_debug(1, "Async goto not applicable on call %d\n", fr->callno); 09067 } 09068 09069 break; 09070 } 09071 case IAX_COMMAND_ACCEPT: 09072 /* Ignore if call is already up or needs authentication or is a TBD */ 09073 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED)) 09074 break; 09075 if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 09076 /* Send ack immediately, before we destroy */ 09077 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09078 iax2_destroy(fr->callno); 09079 break; 09080 } 09081 if (ies.format) { 09082 iaxs[fr->callno]->peerformat = ies.format; 09083 } else { 09084 if (iaxs[fr->callno]->owner) 09085 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; 09086 else 09087 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; 09088 } 09089 ast_verb(3, "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat)); 09090 if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { 09091 memset(&ied0, 0, sizeof(ied0)); 09092 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09093 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09094 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09095 if (!iaxs[fr->callno]) { 09096 ast_mutex_unlock(&iaxsl[fr->callno]); 09097 return 1; 09098 } 09099 if (authdebug) 09100 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); 09101 } else { 09102 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09103 if (iaxs[fr->callno]->owner) { 09104 /* Switch us to use a compatible format */ 09105 iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; 09106 ast_verb(3, "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); 09107 retryowner2: 09108 if (ast_channel_trylock(iaxs[fr->callno]->owner)) { 09109 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 09110 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; 09111 } 09112 09113 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { 09114 /* Setup read/write formats properly. */ 09115 if (iaxs[fr->callno]->owner->writeformat) 09116 ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); 09117 if (iaxs[fr->callno]->owner->readformat) 09118 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 09119 ast_channel_unlock(iaxs[fr->callno]->owner); 09120 } 09121 } 09122 } 09123 if (iaxs[fr->callno]) { 09124 AST_LIST_LOCK(&dpcache); 09125 AST_LIST_TRAVERSE(&iaxs[fr->callno]->dpentries, dp, peer_list) 09126 if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) 09127 iax2_dprequest(dp, fr->callno); 09128 AST_LIST_UNLOCK(&dpcache); 09129 } 09130 break; 09131 case IAX_COMMAND_POKE: 09132 /* Send back a pong packet with the original timestamp */ 09133 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); 09134 if (!iaxs[fr->callno]) { 09135 ast_mutex_unlock(&iaxsl[fr->callno]); 09136 return 1; 09137 } 09138 break; 09139 case IAX_COMMAND_PING: 09140 { 09141 struct iax_ie_data pingied; 09142 construct_rr(iaxs[fr->callno], &pingied); 09143 /* Send back a pong packet with the original timestamp */ 09144 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1); 09145 } 09146 break; 09147 case IAX_COMMAND_PONG: 09148 /* Calculate ping time */ 09149 iaxs[fr->callno]->pingtime = calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts; 09150 /* save RR info */ 09151 save_rr(fr, &ies); 09152 09153 /* Good time to write jb stats for this call */ 09154 log_jitterstats(fr->callno); 09155 09156 if (iaxs[fr->callno]->peerpoke) { 09157 peer = iaxs[fr->callno]->peerpoke; 09158 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) { 09159 if (iaxs[fr->callno]->pingtime <= peer->maxms) { 09160 ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime); 09161 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 09162 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "IAX2/%s", peer->name); /* Activate notification */ 09163 } 09164 } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) { 09165 if (iaxs[fr->callno]->pingtime > peer->maxms) { 09166 ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime); 09167 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 09168 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ 09169 } 09170 } 09171 peer->lastms = iaxs[fr->callno]->pingtime; 09172 if (peer->smoothing && (peer->lastms > -1)) 09173 peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2; 09174 else if (peer->smoothing && peer->lastms < 0) 09175 peer->historicms = (0 + peer->historicms) / 2; 09176 else 09177 peer->historicms = iaxs[fr->callno]->pingtime; 09178 09179 /* Remove scheduled iax2_poke_noanswer */ 09180 if (peer->pokeexpire > -1) { 09181 if (!ast_sched_del(sched, peer->pokeexpire)) { 09182 peer_unref(peer); 09183 peer->pokeexpire = -1; 09184 } 09185 } 09186 /* Schedule the next cycle */ 09187 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) 09188 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 09189 else 09190 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer)); 09191 if (peer->pokeexpire == -1) 09192 peer_unref(peer); 09193 /* and finally send the ack */ 09194 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09195 /* And wrap up the qualify call */ 09196 iax2_destroy(fr->callno); 09197 peer->callno = 0; 09198 ast_debug(1, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms); 09199 } 09200 break; 09201 case IAX_COMMAND_LAGRQ: 09202 case IAX_COMMAND_LAGRP: 09203 f.src = "LAGRQ"; 09204 f.mallocd = 0; 09205 f.offset = 0; 09206 f.samples = 0; 09207 iax_frame_wrap(fr, &f); 09208 if(f.subclass == IAX_COMMAND_LAGRQ) { 09209 /* Received a LAGRQ - echo back a LAGRP */ 09210 fr->af.subclass = IAX_COMMAND_LAGRP; 09211 iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0); 09212 } else { 09213 /* Received LAGRP in response to our LAGRQ */ 09214 unsigned int ts; 09215 /* This is a reply we've been given, actually measure the difference */ 09216 ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af); 09217 iaxs[fr->callno]->lag = ts - fr->ts; 09218 if (iaxdebug) 09219 ast_debug(1, "Peer %s lag measured as %dms\n", 09220 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag); 09221 } 09222 break; 09223 case IAX_COMMAND_AUTHREQ: 09224 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 09225 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>"); 09226 break; 09227 } 09228 if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) { 09229 struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL, 09230 .subclass = AST_CONTROL_HANGUP, 09231 }; 09232 ast_log(LOG_WARNING, 09233 "I don't know how to authenticate %s to %s\n", 09234 ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); 09235 iax2_queue_frame(fr->callno, &hangup_fr); 09236 } 09237 if (!iaxs[fr->callno]) { 09238 ast_mutex_unlock(&iaxsl[fr->callno]); 09239 return 1; 09240 } 09241 break; 09242 case IAX_COMMAND_AUTHREP: 09243 /* For security, always ack immediately */ 09244 if (delayreject) 09245 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09246 /* Ignore once we've started */ 09247 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 09248 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>"); 09249 break; 09250 } 09251 if (authenticate_verify(iaxs[fr->callno], &ies)) { 09252 if (authdebug) 09253 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); 09254 memset(&ied0, 0, sizeof(ied0)); 09255 auth_fail(fr->callno, IAX_COMMAND_REJECT); 09256 break; 09257 } 09258 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 09259 /* This might re-enter the IAX code and need the lock */ 09260 exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num); 09261 } else 09262 exists = 0; 09263 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 09264 if (authdebug) 09265 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); 09266 memset(&ied0, 0, sizeof(ied0)); 09267 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 09268 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 09269 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09270 if (!iaxs[fr->callno]) { 09271 ast_mutex_unlock(&iaxsl[fr->callno]); 09272 return 1; 09273 } 09274 } else { 09275 /* Select an appropriate format */ 09276 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 09277 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09278 using_prefs = "reqonly"; 09279 } else { 09280 using_prefs = "disabled"; 09281 } 09282 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 09283 memset(&pref, 0, sizeof(pref)); 09284 strcpy(caller_pref_buf, "disabled"); 09285 strcpy(host_pref_buf, "disabled"); 09286 } else { 09287 using_prefs = "mine"; 09288 if (ies.codec_prefs) 09289 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 09290 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 09291 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 09292 pref = iaxs[fr->callno]->rprefs; 09293 using_prefs = "caller"; 09294 } else { 09295 pref = iaxs[fr->callno]->prefs; 09296 } 09297 } else /* if no codec_prefs IE do it the old way */ 09298 pref = iaxs[fr->callno]->prefs; 09299 09300 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 09301 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 09302 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 09303 } 09304 if (!format) { 09305 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09306 ast_debug(1, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability); 09307 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 09308 } 09309 if (!format) { 09310 if (authdebug) { 09311 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 09312 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); 09313 else 09314 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); 09315 } 09316 memset(&ied0, 0, sizeof(ied0)); 09317 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09318 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09319 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09320 if (!iaxs[fr->callno]) { 09321 ast_mutex_unlock(&iaxsl[fr->callno]); 09322 return 1; 09323 } 09324 } else { 09325 /* Pick one... */ 09326 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09327 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 09328 format = 0; 09329 } else { 09330 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 09331 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 09332 memset(&pref, 0, sizeof(pref)); 09333 format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? 09334 iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09335 strcpy(caller_pref_buf,"disabled"); 09336 strcpy(host_pref_buf,"disabled"); 09337 } else { 09338 using_prefs = "mine"; 09339 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 09340 /* Do the opposite of what we tried above. */ 09341 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 09342 pref = iaxs[fr->callno]->prefs; 09343 } else { 09344 pref = iaxs[fr->callno]->rprefs; 09345 using_prefs = "caller"; 09346 } 09347 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 09348 } else /* if no codec_prefs IE do it the old way */ 09349 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09350 } 09351 } 09352 if (!format) { 09353 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09354 if (authdebug) { 09355 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 09356 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); 09357 else 09358 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); 09359 } 09360 memset(&ied0, 0, sizeof(ied0)); 09361 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09362 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09363 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09364 if (!iaxs[fr->callno]) { 09365 ast_mutex_unlock(&iaxsl[fr->callno]); 09366 return 1; 09367 } 09368 } 09369 } 09370 } 09371 if (format) { 09372 /* Authentication received */ 09373 memset(&ied1, 0, sizeof(ied1)); 09374 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 09375 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 09376 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 09377 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09378 ast_verb(3, "Accepting AUTHENTICATED call from %s:\n" 09379 "%srequested format = %s,\n" 09380 "%srequested prefs = %s,\n" 09381 "%sactual format = %s,\n" 09382 "%shost prefs = %s,\n" 09383 "%spriority = %s\n", 09384 ast_inet_ntoa(sin.sin_addr), 09385 VERBOSE_PREFIX_4, 09386 ast_getformatname(iaxs[fr->callno]->peerformat), 09387 VERBOSE_PREFIX_4, 09388 caller_pref_buf, 09389 VERBOSE_PREFIX_4, 09390 ast_getformatname(format), 09391 VERBOSE_PREFIX_4, 09392 host_pref_buf, 09393 VERBOSE_PREFIX_4, 09394 using_prefs); 09395 09396 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09397 if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format))) 09398 iax2_destroy(fr->callno); 09399 else if (ies.vars) { 09400 struct ast_datastore *variablestore; 09401 struct ast_variable *var, *prev = NULL; 09402 AST_LIST_HEAD(, ast_var_t) *varlist; 09403 varlist = ast_calloc(1, sizeof(*varlist)); 09404 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 09405 if (variablestore && varlist) { 09406 variablestore->data = varlist; 09407 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 09408 AST_LIST_HEAD_INIT(varlist); 09409 ast_debug(1, "I can haz IAX vars? w00t\n"); 09410 for (var = ies.vars; var; var = var->next) { 09411 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 09412 if (prev) 09413 ast_free(prev); 09414 prev = var; 09415 if (!newvar) { 09416 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 09417 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09418 } else { 09419 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 09420 } 09421 } 09422 if (prev) 09423 ast_free(prev); 09424 ies.vars = NULL; 09425 ast_channel_datastore_add(c, variablestore); 09426 } else { 09427 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09428 if (variablestore) 09429 ast_datastore_free(variablestore); 09430 if (varlist) 09431 ast_free(varlist); 09432 } 09433 } 09434 } else { 09435 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 09436 /* If this is a TBD call, we're ready but now what... */ 09437 ast_verb(3, "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 09438 } 09439 } 09440 } 09441 break; 09442 case IAX_COMMAND_DIAL: 09443 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) { 09444 ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 09445 ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); 09446 if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { 09447 if (authdebug) 09448 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); 09449 memset(&ied0, 0, sizeof(ied0)); 09450 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 09451 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 09452 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09453 if (!iaxs[fr->callno]) { 09454 ast_mutex_unlock(&iaxsl[fr->callno]); 09455 return 1; 09456 } 09457 } else { 09458 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09459 ast_verb(3, "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat); 09460 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09461 send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); 09462 if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat))) 09463 iax2_destroy(fr->callno); 09464 else if (ies.vars) { 09465 struct ast_datastore *variablestore; 09466 struct ast_variable *var, *prev = NULL; 09467 AST_LIST_HEAD(, ast_var_t) *varlist; 09468 varlist = ast_calloc(1, sizeof(*varlist)); 09469 variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); 09470 ast_debug(1, "I can haz IAX vars? w00t\n"); 09471 if (variablestore && varlist) { 09472 variablestore->data = varlist; 09473 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 09474 AST_LIST_HEAD_INIT(varlist); 09475 for (var = ies.vars; var; var = var->next) { 09476 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 09477 if (prev) 09478 ast_free(prev); 09479 prev = var; 09480 if (!newvar) { 09481 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 09482 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09483 } else { 09484 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 09485 } 09486 } 09487 if (prev) 09488 ast_free(prev); 09489 ies.vars = NULL; 09490 ast_channel_datastore_add(c, variablestore); 09491 } else { 09492 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09493 if (variablestore) 09494 ast_datastore_free(variablestore); 09495 if (varlist) 09496 ast_free(varlist); 09497 } 09498 } 09499 } 09500 } 09501 break; 09502 case IAX_COMMAND_INVAL: 09503 iaxs[fr->callno]->error = ENOTCONN; 09504 ast_debug(1, "Immediately destroying %d, having received INVAL\n", fr->callno); 09505 iax2_destroy(fr->callno); 09506 ast_debug(1, "Destroying call %d\n", fr->callno); 09507 break; 09508 case IAX_COMMAND_VNAK: 09509 ast_debug(1, "Received VNAK: resending outstanding frames\n"); 09510 /* Force retransmission */ 09511 vnak_retransmit(fr->callno, fr->iseqno); 09512 break; 09513 case IAX_COMMAND_REGREQ: 09514 case IAX_COMMAND_REGREL: 09515 /* For security, always ack immediately */ 09516 if (delayreject) 09517 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09518 if (register_verify(fr->callno, &sin, &ies)) { 09519 if (!iaxs[fr->callno]) { 09520 ast_mutex_unlock(&iaxsl[fr->callno]); 09521 return 1; 09522 } 09523 /* Send delayed failure */ 09524 auth_fail(fr->callno, IAX_COMMAND_REGREJ); 09525 break; 09526 } 09527 if (!iaxs[fr->callno]) { 09528 ast_mutex_unlock(&iaxsl[fr->callno]); 09529 return 1; 09530 } 09531 if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 09532 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED)) { 09533 09534 if (f.subclass == IAX_COMMAND_REGREL) 09535 memset(&sin, 0, sizeof(sin)); 09536 if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) 09537 ast_log(LOG_WARNING, "Registry error\n"); 09538 if (!iaxs[fr->callno]) { 09539 ast_mutex_unlock(&iaxsl[fr->callno]); 09540 return 1; 09541 } 09542 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 09543 ast_mutex_unlock(&iaxsl[fr->callno]); 09544 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 09545 ast_mutex_lock(&iaxsl[fr->callno]); 09546 if (!iaxs[fr->callno]) { 09547 ast_mutex_unlock(&iaxsl[fr->callno]); 09548 return 1; 09549 } 09550 } 09551 break; 09552 } 09553 registry_authrequest(fr->callno); 09554 if (!iaxs[fr->callno]) { 09555 ast_mutex_unlock(&iaxsl[fr->callno]); 09556 return 1; 09557 } 09558 break; 09559 case IAX_COMMAND_REGACK: 09560 if (iax2_ack_registry(&ies, &sin, fr->callno)) 09561 ast_log(LOG_WARNING, "Registration failure\n"); 09562 /* Send ack immediately, before we destroy */ 09563 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09564 iax2_destroy(fr->callno); 09565 break; 09566 case IAX_COMMAND_REGREJ: 09567 if (iaxs[fr->callno]->reg) { 09568 if (authdebug) { 09569 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)); 09570 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>"); 09571 } 09572 iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; 09573 } 09574 /* Send ack immediately, before we destroy */ 09575 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09576 iax2_destroy(fr->callno); 09577 break; 09578 case IAX_COMMAND_REGAUTH: 09579 /* Authentication request */ 09580 if (registry_rerequest(&ies, fr->callno, &sin)) { 09581 memset(&ied0, 0, sizeof(ied0)); 09582 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); 09583 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 09584 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09585 if (!iaxs[fr->callno]) { 09586 ast_mutex_unlock(&iaxsl[fr->callno]); 09587 return 1; 09588 } 09589 } 09590 break; 09591 case IAX_COMMAND_TXREJ: 09592 iaxs[fr->callno]->transferring = 0; 09593 ast_verb(3, "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 09594 memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer)); 09595 if (iaxs[fr->callno]->bridgecallno) { 09596 if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { 09597 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0; 09598 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 09599 } 09600 } 09601 break; 09602 case IAX_COMMAND_TXREADY: 09603 if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || 09604 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) { 09605 if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) 09606 iaxs[fr->callno]->transferring = TRANSFER_MREADY; 09607 else 09608 iaxs[fr->callno]->transferring = TRANSFER_READY; 09609 ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 09610 if (iaxs[fr->callno]->bridgecallno) { 09611 if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || 09612 (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { 09613 /* They're both ready, now release them. */ 09614 if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) { 09615 ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 09616 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 09617 09618 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; 09619 iaxs[fr->callno]->transferring = TRANSFER_MEDIA; 09620 09621 memset(&ied0, 0, sizeof(ied0)); 09622 memset(&ied1, 0, sizeof(ied1)); 09623 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 09624 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 09625 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1); 09626 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1); 09627 } else { 09628 ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 09629 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 09630 09631 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED; 09632 iaxs[fr->callno]->transferring = TRANSFER_RELEASED; 09633 ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE); 09634 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 09635 09636 /* Stop doing lag & ping requests */ 09637 stop_stuff(fr->callno); 09638 stop_stuff(iaxs[fr->callno]->bridgecallno); 09639 09640 memset(&ied0, 0, sizeof(ied0)); 09641 memset(&ied1, 0, sizeof(ied1)); 09642 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 09643 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 09644 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1); 09645 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1); 09646 } 09647 09648 } 09649 } 09650 } 09651 break; 09652 case IAX_COMMAND_TXREQ: 09653 try_transfer(iaxs[fr->callno], &ies); 09654 break; 09655 case IAX_COMMAND_TXCNT: 09656 if (iaxs[fr->callno]->transferring) 09657 send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); 09658 break; 09659 case IAX_COMMAND_TXREL: 09660 /* Send ack immediately, rather than waiting until we've changed addresses */ 09661 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09662 complete_transfer(fr->callno, &ies); 09663 stop_stuff(fr->callno); /* for attended transfer to work with libiax */ 09664 break; 09665 case IAX_COMMAND_TXMEDIA: 09666 if (iaxs[fr->callno]->transferring == TRANSFER_READY) { 09667 AST_LIST_LOCK(&frame_queue); 09668 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 09669 /* Cancel any outstanding frames and start anew */ 09670 if ((fr->callno == cur->callno) && (cur->transfer)) 09671 cur->retries = -1; 09672 } 09673 AST_LIST_UNLOCK(&frame_queue); 09674 /* Start sending our media to the transfer address, but otherwise leave the call as-is */ 09675 iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS; 09676 } 09677 break; 09678 case IAX_COMMAND_RTKEY: 09679 if (!IAX_CALLENCRYPTED(iaxs[fr->callno])) { 09680 ast_log(LOG_WARNING, 09681 "we've been told to rotate our encryption key, " 09682 "but this isn't an encrypted call. bad things will happen.\n" 09683 ); 09684 break; 09685 } 09686 09687 IAX_DEBUGDIGEST("Receiving", ies.challenge); 09688 09689 ast_aes_decrypt_key((unsigned char *) ies.challenge, &iaxs[fr->callno]->dcx); 09690 break; 09691 case IAX_COMMAND_DPREP: 09692 complete_dpreply(iaxs[fr->callno], &ies); 09693 break; 09694 case IAX_COMMAND_UNSUPPORT: 09695 ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown); 09696 break; 09697 case IAX_COMMAND_FWDOWNL: 09698 /* Firmware download */ 09699 if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) { 09700 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1); 09701 break; 09702 } 09703 memset(&ied0, 0, sizeof(ied0)); 09704 res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc); 09705 if (res < 0) 09706 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09707 else if (res > 0) 09708 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 09709 else 09710 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 09711 if (!iaxs[fr->callno]) { 09712 ast_mutex_unlock(&iaxsl[fr->callno]); 09713 return 1; 09714 } 09715 break; 09716 default: 09717 ast_debug(1, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno); 09718 memset(&ied0, 0, sizeof(ied0)); 09719 iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass); 09720 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1); 09721 } 09722 /* Free remote variables (if any) */ 09723 if (ies.vars) { 09724 ast_variables_destroy(ies.vars); 09725 ast_debug(1, "I can haz IAX vars, but they is no good :-(\n"); 09726 ies.vars = NULL; 09727 } 09728 09729 /* Don't actually pass these frames along */ 09730 if ((f.subclass != IAX_COMMAND_ACK) && 09731 (f.subclass != IAX_COMMAND_TXCNT) && 09732 (f.subclass != IAX_COMMAND_TXACC) && 09733 (f.subclass != IAX_COMMAND_INVAL) && 09734 (f.subclass != IAX_COMMAND_VNAK)) { 09735 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 09736 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09737 } 09738 ast_mutex_unlock(&iaxsl[fr->callno]); 09739 return 1; 09740 } 09741 /* Unless this is an ACK or INVAL frame, ack it */ 09742 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 09743 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09744 } else if (minivid) { 09745 f.frametype = AST_FRAME_VIDEO; 09746 if (iaxs[fr->callno]->videoformat > 0) 09747 f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); 09748 else { 09749 ast_log(LOG_WARNING, "Received mini frame before first full video frame\n"); 09750 iax2_vnak(fr->callno); 09751 ast_mutex_unlock(&iaxsl[fr->callno]); 09752 return 1; 09753 } 09754 f.datalen = res - sizeof(*vh); 09755 if (f.datalen) 09756 f.data.ptr = thread->buf + sizeof(*vh); 09757 else 09758 f.data.ptr = NULL; 09759 #ifdef IAXTESTS 09760 if (test_resync) { 09761 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff); 09762 } else 09763 #endif /* IAXTESTS */ 09764 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff); 09765 } else { 09766 /* A mini frame */ 09767 f.frametype = AST_FRAME_VOICE; 09768 if (iaxs[fr->callno]->voiceformat > 0) 09769 f.subclass = iaxs[fr->callno]->voiceformat; 09770 else { 09771 ast_debug(1, "Received mini frame before first full voice frame\n"); 09772 iax2_vnak(fr->callno); 09773 ast_mutex_unlock(&iaxsl[fr->callno]); 09774 return 1; 09775 } 09776 f.datalen = res - sizeof(struct ast_iax2_mini_hdr); 09777 if (f.datalen < 0) { 09778 ast_log(LOG_WARNING, "Datalen < 0?\n"); 09779 ast_mutex_unlock(&iaxsl[fr->callno]); 09780 return 1; 09781 } 09782 if (f.datalen) 09783 f.data.ptr = thread->buf + sizeof(*mh); 09784 else 09785 f.data.ptr = NULL; 09786 #ifdef IAXTESTS 09787 if (test_resync) { 09788 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff); 09789 } else 09790 #endif /* IAXTESTS */ 09791 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts); 09792 /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */ 09793 } 09794 /* Don't pass any packets until we're started */ 09795 if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 09796 ast_mutex_unlock(&iaxsl[fr->callno]); 09797 return 1; 09798 } 09799 /* Common things */ 09800 f.src = "IAX2"; 09801 f.mallocd = 0; 09802 f.offset = 0; 09803 f.len = 0; 09804 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { 09805 f.samples = ast_codec_get_samples(&f); 09806 /* We need to byteswap incoming slinear samples from network byte order */ 09807 if (f.subclass == AST_FORMAT_SLINEAR) 09808 ast_frame_byteswap_be(&f); 09809 } else 09810 f.samples = 0; 09811 iax_frame_wrap(fr, &f); 09812 09813 /* If this is our most recent packet, use it as our basis for timestamping */ 09814 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 09815 /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/ 09816 fr->outoforder = 0; 09817 } else { 09818 if (iaxdebug && iaxs[fr->callno]) 09819 ast_debug(1, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr->ts, iaxs[fr->callno]->last); 09820 fr->outoforder = -1; 09821 } 09822 fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO)); 09823 duped_fr = iaxfrdup2(fr); 09824 if (duped_fr) { 09825 schedule_delivery(duped_fr, updatehistory, 0, &fr->ts); 09826 } 09827 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 09828 iaxs[fr->callno]->last = fr->ts; 09829 #if 1 09830 if (iaxdebug) 09831 ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts); 09832 #endif 09833 } 09834 09835 /* Always run again */ 09836 ast_mutex_unlock(&iaxsl[fr->callno]); 09837 return 1; 09838 }
static int socket_process_meta | ( | int | packet_len, | |
struct ast_iax2_meta_hdr * | meta, | |||
struct sockaddr_in * | sin, | |||
int | sockfd, | |||
struct iax_frame * | fr | |||
) | [static] |
Definition at line 8044 of file chan_iax2.c.
References ast_codec_get_samples(), AST_FRAME_VOICE, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_test_flag, ast_tvnow(), ast_tvzero(), iax_frame::callno, ast_iax2_mini_hdr::callno, f, find_callno_locked(), find_tpeer(), fix_peerts(), iax2_vnak(), IAX_FLAG_FULL, iax_frame_wrap(), IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_STATE_STARTED, iaxfrdup2(), ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, ast_iax2_meta_trunk_mini::mini, NEW_PREVENT, iax_frame::outoforder, iax2_trunk_peer::rxtrunktime, schedule_delivery(), iax2_trunk_peer::trunkact, iax_frame::ts, and ast_iax2_mini_hdr::ts.
Referenced by socket_process().
08046 { 08047 unsigned char metatype; 08048 struct ast_iax2_meta_trunk_mini *mtm; 08049 struct ast_iax2_meta_trunk_hdr *mth; 08050 struct ast_iax2_meta_trunk_entry *mte; 08051 struct iax2_trunk_peer *tpeer; 08052 unsigned int ts; 08053 void *ptr; 08054 struct timeval rxtrunktime; 08055 struct ast_frame f = { 0, }; 08056 08057 if (packet_len < sizeof(*meta)) { 08058 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", 08059 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 08060 return 1; 08061 } 08062 08063 if (meta->metacmd != IAX_META_TRUNK) 08064 return 1; 08065 08066 if (packet_len < (sizeof(*meta) + sizeof(*mth))) { 08067 ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %d min)\n", packet_len, 08068 (int) (sizeof(*meta) + sizeof(*mth))); 08069 return 1; 08070 } 08071 mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data); 08072 ts = ntohl(mth->ts); 08073 metatype = meta->cmddata; 08074 packet_len -= (sizeof(*meta) + sizeof(*mth)); 08075 ptr = mth->data; 08076 tpeer = find_tpeer(sin, sockfd); 08077 if (!tpeer) { 08078 ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", 08079 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 08080 return 1; 08081 } 08082 tpeer->trunkact = ast_tvnow(); 08083 if (!ts || ast_tvzero(tpeer->rxtrunktime)) 08084 tpeer->rxtrunktime = tpeer->trunkact; 08085 rxtrunktime = tpeer->rxtrunktime; 08086 ast_mutex_unlock(&tpeer->lock); 08087 while (packet_len >= sizeof(*mte)) { 08088 /* Process channels */ 08089 unsigned short callno, trunked_ts, len; 08090 08091 if (metatype == IAX_META_TRUNK_MINI) { 08092 mtm = (struct ast_iax2_meta_trunk_mini *) ptr; 08093 ptr += sizeof(*mtm); 08094 packet_len -= sizeof(*mtm); 08095 len = ntohs(mtm->len); 08096 callno = ntohs(mtm->mini.callno); 08097 trunked_ts = ntohs(mtm->mini.ts); 08098 } else if (metatype == IAX_META_TRUNK_SUPERMINI) { 08099 mte = (struct ast_iax2_meta_trunk_entry *)ptr; 08100 ptr += sizeof(*mte); 08101 packet_len -= sizeof(*mte); 08102 len = ntohs(mte->len); 08103 callno = ntohs(mte->callno); 08104 trunked_ts = 0; 08105 } else { 08106 ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 08107 break; 08108 } 08109 /* Stop if we don't have enough data */ 08110 if (len > packet_len) 08111 break; 08112 fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, sin, NEW_PREVENT, sockfd, 0); 08113 if (!fr->callno) 08114 continue; 08115 08116 /* If it's a valid call, deliver the contents. If not, we 08117 drop it, since we don't have a scallno to use for an INVAL */ 08118 /* Process as a mini frame */ 08119 memset(&f, 0, sizeof(f)); 08120 f.frametype = AST_FRAME_VOICE; 08121 if (!iaxs[fr->callno]) { 08122 /* drop it */ 08123 } else if (iaxs[fr->callno]->voiceformat == 0) { 08124 ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n"); 08125 iax2_vnak(fr->callno); 08126 } else { 08127 f.subclass = iaxs[fr->callno]->voiceformat; 08128 f.datalen = len; 08129 if (f.datalen >= 0) { 08130 if (f.datalen) 08131 f.data.ptr = ptr; 08132 else 08133 f.data.ptr = NULL; 08134 if (trunked_ts) 08135 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff); 08136 else 08137 fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts); 08138 /* Don't pass any packets until we're started */ 08139 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08140 struct iax_frame *duped_fr; 08141 08142 /* Common things */ 08143 f.src = "IAX2"; 08144 f.mallocd = 0; 08145 f.offset = 0; 08146 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 08147 f.samples = ast_codec_get_samples(&f); 08148 else 08149 f.samples = 0; 08150 fr->outoforder = 0; 08151 iax_frame_wrap(fr, &f); 08152 duped_fr = iaxfrdup2(fr); 08153 if (duped_fr) 08154 schedule_delivery(duped_fr, 1, 1, &fr->ts); 08155 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) 08156 iaxs[fr->callno]->last = fr->ts; 08157 } 08158 } else { 08159 ast_log(LOG_WARNING, "Datalen < 0?\n"); 08160 } 08161 } 08162 ast_mutex_unlock(&iaxsl[fr->callno]); 08163 ptr += len; 08164 packet_len -= len; 08165 } 08166 08167 return 1; 08168 }
static int socket_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 7966 of file chan_iax2.c.
References ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_thread::callno, ast_iax2_full_hdr::csub, defer_full_frame(), errno, iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), iax2_thread::list, LOG_WARNING, ast_iax2_full_hdr::scallno, signal_condition(), iax2_thread::sin, thread, and ast_iax2_full_hdr::type.
Referenced by network_thread(), peer_set_srcaddr(), and set_config().
07967 { 07968 struct iax2_thread *thread; 07969 socklen_t len; 07970 time_t t; 07971 static time_t last_errtime = 0; 07972 struct ast_iax2_full_hdr *fh; 07973 07974 if (!(thread = find_idle_thread())) { 07975 time(&t); 07976 if (t != last_errtime) 07977 ast_debug(1, "Out of idle IAX2 threads for I/O, pausing!\n"); 07978 last_errtime = t; 07979 usleep(1); 07980 return 1; 07981 } 07982 07983 len = sizeof(thread->iosin); 07984 thread->iofd = fd; 07985 thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len); 07986 thread->buf_size = sizeof(thread->readbuf); 07987 thread->buf = thread->readbuf; 07988 if (thread->buf_len < 0) { 07989 if (errno != ECONNREFUSED && errno != EAGAIN) 07990 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 07991 handle_error(); 07992 thread->iostate = IAX_IOSTATE_IDLE; 07993 signal_condition(&thread->lock, &thread->cond); 07994 return 1; 07995 } 07996 if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */ 07997 thread->iostate = IAX_IOSTATE_IDLE; 07998 signal_condition(&thread->lock, &thread->cond); 07999 return 1; 08000 } 08001 08002 /* Determine if this frame is a full frame; if so, and any thread is currently 08003 processing a full frame for the same callno from this peer, then drop this 08004 frame (and the peer will retransmit it) */ 08005 fh = (struct ast_iax2_full_hdr *) thread->buf; 08006 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 08007 struct iax2_thread *cur = NULL; 08008 uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL; 08009 08010 AST_LIST_LOCK(&active_list); 08011 AST_LIST_TRAVERSE(&active_list, cur, list) { 08012 if ((cur->ffinfo.callno == callno) && 08013 !inaddrcmp(&cur->ffinfo.sin, &thread->iosin)) 08014 break; 08015 } 08016 if (cur) { 08017 /* we found another thread processing a full frame for this call, 08018 so queue it up for processing later. */ 08019 defer_full_frame(thread, cur); 08020 AST_LIST_UNLOCK(&active_list); 08021 thread->iostate = IAX_IOSTATE_IDLE; 08022 signal_condition(&thread->lock, &thread->cond); 08023 return 1; 08024 } else { 08025 /* this thread is going to process this frame, so mark it */ 08026 thread->ffinfo.callno = callno; 08027 memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin)); 08028 thread->ffinfo.type = fh->type; 08029 thread->ffinfo.csub = fh->csub; 08030 } 08031 AST_LIST_UNLOCK(&active_list); 08032 } 08033 08034 /* Mark as ready and send on its way */ 08035 thread->iostate = IAX_IOSTATE_READY; 08036 #ifdef DEBUG_SCHED_MULTITHREAD 08037 ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc)); 08038 #endif 08039 signal_condition(&thread->lock, &thread->cond); 08040 08041 return 1; 08042 }
static void spawn_dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid | |||
) | [static] |
Definition at line 7682 of file chan_iax2.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_pthread_create_detached, ast_strdup, dp_lookup_thread(), and LOG_WARNING.
Referenced by socket_process().
07683 { 07684 pthread_t newthread; 07685 struct dpreq_data *dpr; 07686 07687 if (!(dpr = ast_calloc(1, sizeof(*dpr)))) 07688 return; 07689 07690 dpr->callno = callno; 07691 ast_copy_string(dpr->context, context, sizeof(dpr->context)); 07692 ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum)); 07693 if (callerid) 07694 dpr->callerid = ast_strdup(callerid); 07695 if (ast_pthread_create_detached(&newthread, NULL, dp_lookup_thread, dpr)) { 07696 ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); 07697 } 07698 }
static int start_network_thread | ( | void | ) | [static] |
Definition at line 10448 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create_detached, iax2_process_thread(), IAX_THREAD_TYPE_POOL, iaxthreadcount, iax2_thread::list, LOG_WARNING, and thread.
Referenced by load_module().
10449 { 10450 struct iax2_thread *thread; 10451 int threadcount = 0; 10452 int x; 10453 for (x = 0; x < iaxthreadcount; x++) { 10454 thread = ast_calloc(1, sizeof(*thread)); 10455 if (thread) { 10456 thread->type = IAX_THREAD_TYPE_POOL; 10457 thread->threadnum = ++threadcount; 10458 ast_mutex_init(&thread->lock); 10459 ast_cond_init(&thread->cond, NULL); 10460 if (ast_pthread_create_detached(&thread->threadid, NULL, iax2_process_thread, thread)) { 10461 ast_log(LOG_WARNING, "Failed to create new thread!\n"); 10462 ast_free(thread); 10463 thread = NULL; 10464 } 10465 AST_LIST_LOCK(&idle_list); 10466 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 10467 AST_LIST_UNLOCK(&idle_list); 10468 } 10469 } 10470 ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL); 10471 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 10472 ast_verb(2, "%d helper threads started\n", threadcount); 10473 return 0; 10474 }
static void stop_stuff | ( | int | callno | ) | [static] |
Definition at line 7385 of file chan_iax2.c.
References iax2_destroy_helper().
Referenced by socket_process().
07386 { 07387 iax2_destroy_helper(iaxs[callno]); 07388 }
static void store_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1710 of file chan_iax2.c.
References ao2_link, ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by __find_callno(), complete_transfer(), and socket_process().
01711 { 01712 if (!pvt->peercallno) { 01713 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01714 return; 01715 } 01716 01717 ao2_link(iax_peercallno_pvts, pvt); 01718 }
static void store_by_transfercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1691 of file chan_iax2.c.
References ao2_link, ast_log(), iax_transfercallno_pvts, LOG_ERROR, and chan_iax2_pvt::transfercallno.
Referenced by try_transfer().
01692 { 01693 if (!pvt->transfercallno) { 01694 ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n"); 01695 return; 01696 } 01697 01698 ao2_link(iax_transfercallno_pvts, pvt); 01699 }
static int timing_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 7571 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_debug, ast_free, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_timer_ack(), ast_tvnow(), ast_verbose, iax2_trunk_expired(), iax2_trunk_peer::lock, send_trunk(), timer, totalcalls, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.
Referenced by network_thread().
07572 { 07573 int res, processed = 0, totalcalls = 0; 07574 struct iax2_trunk_peer *tpeer = NULL, *drop = NULL; 07575 struct timeval now = ast_tvnow(); 07576 07577 if (iaxtrunkdebug) 07578 ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", trunkmaxsize); 07579 07580 if (timer) { 07581 ast_timer_ack(timer, 1); 07582 } 07583 07584 /* For each peer that supports trunking... */ 07585 AST_LIST_LOCK(&tpeers); 07586 AST_LIST_TRAVERSE_SAFE_BEGIN(&tpeers, tpeer, list) { 07587 processed++; 07588 res = 0; 07589 ast_mutex_lock(&tpeer->lock); 07590 /* We can drop a single tpeer per pass. That makes all this logic 07591 substantially easier */ 07592 if (!drop && iax2_trunk_expired(tpeer, &now)) { 07593 /* Take it out of the list, but don't free it yet, because it 07594 could be in use */ 07595 AST_LIST_REMOVE_CURRENT(list); 07596 drop = tpeer; 07597 } else { 07598 res = send_trunk(tpeer, &now); 07599 trunk_timed++; 07600 if (iaxtrunkdebug) 07601 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); 07602 } 07603 totalcalls += res; 07604 res = 0; 07605 ast_mutex_unlock(&tpeer->lock); 07606 } 07607 AST_LIST_TRAVERSE_SAFE_END; 07608 AST_LIST_UNLOCK(&tpeers); 07609 07610 if (drop) { 07611 ast_mutex_lock(&drop->lock); 07612 /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 07613 because by the time they could get tpeerlock, we've already grabbed it */ 07614 ast_debug(1, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); 07615 if (drop->trunkdata) { 07616 ast_free(drop->trunkdata); 07617 drop->trunkdata = NULL; 07618 } 07619 ast_mutex_unlock(&drop->lock); 07620 ast_mutex_destroy(&drop->lock); 07621 ast_free(drop); 07622 07623 } 07624 07625 if (iaxtrunkdebug) 07626 ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls); 07627 iaxtrunkdebug = 0; 07628 07629 return 1; 07630 }
static int transfercallno_pvt_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 12405 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, chan_iax2_pvt::frames_received, and match().
Referenced by load_module().
12406 { 12407 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 12408 12409 /* The frames_received field is used to hold whether we're matching 12410 * against a full frame or not ... */ 12411 12412 return match(&pvt2->transfer, pvt2->transfercallno, pvt2->callno, pvt, 12413 pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0; 12414 }
static int transfercallno_pvt_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 12398 of file chan_iax2.c.
References chan_iax2_pvt::transfercallno.
Referenced by load_module().
12399 { 12400 const struct chan_iax2_pvt *pvt = obj; 12401 12402 return pvt->transfercallno; 12403 }
static int transmit_trunk | ( | struct iax_frame * | f, | |
struct sockaddr_in * | sin, | |||
int | sockfd | |||
) | [static] |
Definition at line 2311 of file chan_iax2.c.
References ast_debug, errno, f, and handle_error().
Referenced by send_trunk().
02312 { 02313 int res; 02314 res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin, 02315 sizeof(*sin)); 02316 if (res < 0) { 02317 ast_debug(1, "Received error: %s\n", strerror(errno)); 02318 handle_error(); 02319 } else 02320 res = 0; 02321 return res; 02322 }
static int try_firmware | ( | char * | s | ) | [static] |
Definition at line 2013 of file chan_iax2.c.
References ast_calloc, AST_FILE_MODE, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_random(), ast_strlen_zero(), ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, errno, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, iax2_trunk_peer::list, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), and ast_iax2_firmware_header::version.
Referenced by reload_firmware().
02014 { 02015 struct stat stbuf; 02016 struct iax_firmware *cur = NULL; 02017 int ifd, fd, res, len, chunk; 02018 struct ast_iax2_firmware_header *fwh, fwh2; 02019 struct MD5Context md5; 02020 unsigned char sum[16], buf[1024]; 02021 char *s2, *last; 02022 02023 if (!(s2 = alloca(strlen(s) + 100))) { 02024 ast_log(LOG_WARNING, "Alloca failed!\n"); 02025 return -1; 02026 } 02027 02028 last = strrchr(s, '/'); 02029 if (last) 02030 last++; 02031 else 02032 last = s; 02033 02034 snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random()); 02035 02036 if ((res = stat(s, &stbuf) < 0)) { 02037 ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno)); 02038 return -1; 02039 } 02040 02041 /* Make sure it's not a directory */ 02042 if (S_ISDIR(stbuf.st_mode)) 02043 return -1; 02044 ifd = open(s, O_RDONLY); 02045 if (ifd < 0) { 02046 ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); 02047 return -1; 02048 } 02049 fd = open(s2, O_RDWR | O_CREAT | O_EXCL, AST_FILE_MODE); 02050 if (fd < 0) { 02051 ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); 02052 close(ifd); 02053 return -1; 02054 } 02055 /* Unlink our newly created file */ 02056 unlink(s2); 02057 02058 /* Now copy the firmware into it */ 02059 len = stbuf.st_size; 02060 while(len) { 02061 chunk = len; 02062 if (chunk > sizeof(buf)) 02063 chunk = sizeof(buf); 02064 res = read(ifd, buf, chunk); 02065 if (res != chunk) { 02066 ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 02067 close(ifd); 02068 close(fd); 02069 return -1; 02070 } 02071 res = write(fd, buf, chunk); 02072 if (res != chunk) { 02073 ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 02074 close(ifd); 02075 close(fd); 02076 return -1; 02077 } 02078 len -= chunk; 02079 } 02080 close(ifd); 02081 /* Return to the beginning */ 02082 lseek(fd, 0, SEEK_SET); 02083 if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) { 02084 ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s); 02085 close(fd); 02086 return -1; 02087 } 02088 if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) { 02089 ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s); 02090 close(fd); 02091 return -1; 02092 } 02093 if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) { 02094 ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s); 02095 close(fd); 02096 return -1; 02097 } 02098 if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) { 02099 ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s); 02100 close(fd); 02101 return -1; 02102 } 02103 fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 02104 if (fwh == (void *) -1) { 02105 ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno)); 02106 close(fd); 02107 return -1; 02108 } 02109 MD5Init(&md5); 02110 MD5Update(&md5, fwh->data, ntohl(fwh->datalen)); 02111 MD5Final(sum, &md5); 02112 if (memcmp(sum, fwh->chksum, sizeof(sum))) { 02113 ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s); 02114 munmap((void*)fwh, stbuf.st_size); 02115 close(fd); 02116 return -1; 02117 } 02118 02119 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02120 if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) { 02121 /* Found a candidate */ 02122 if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version))) 02123 /* The version we have on loaded is older, load this one instead */ 02124 break; 02125 /* This version is no newer than what we have. Don't worry about it. 02126 We'll consider it a proper load anyhow though */ 02127 munmap((void*)fwh, stbuf.st_size); 02128 close(fd); 02129 return 0; 02130 } 02131 } 02132 02133 if (!cur && ((cur = ast_calloc(1, sizeof(*cur))))) { 02134 cur->fd = -1; 02135 AST_LIST_INSERT_TAIL(&firmwares, cur, list); 02136 } 02137 02138 if (cur) { 02139 if (cur->fwh) 02140 munmap((void*)cur->fwh, cur->mmaplen); 02141 if (cur->fd > -1) 02142 close(cur->fd); 02143 cur->fwh = fwh; 02144 cur->fd = fd; 02145 cur->mmaplen = stbuf.st_size; 02146 cur->dead = 0; 02147 } 02148 02149 return 0; 02150 }
static int try_transfer | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6752 of file chan_iax2.c.
References iax_ies::apparent_addr, AST_FRAME_IAX, ast_log(), iax_ies::callno, IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, inet_aton(), LOG_WARNING, send_command_transfer(), store_by_transfercallno(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, iax_ies::transferid, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.
Referenced by socket_process().
06753 { 06754 int newcall = 0; 06755 char newip[256]; 06756 struct iax_ie_data ied; 06757 struct sockaddr_in new; 06758 06759 06760 memset(&ied, 0, sizeof(ied)); 06761 if (ies->apparent_addr) 06762 memmove(&new, ies->apparent_addr, sizeof(new)); 06763 if (ies->callno) 06764 newcall = ies->callno; 06765 if (!newcall || !new.sin_addr.s_addr || !new.sin_port) { 06766 ast_log(LOG_WARNING, "Invalid transfer request\n"); 06767 return -1; 06768 } 06769 pvt->transfercallno = newcall; 06770 memcpy(&pvt->transfer, &new, sizeof(pvt->transfer)); 06771 inet_aton(newip, &pvt->transfer.sin_addr); 06772 pvt->transfer.sin_family = AF_INET; 06773 pvt->transferring = TRANSFER_BEGIN; 06774 pvt->transferid = ies->transferid; 06775 store_by_transfercallno(pvt); 06776 if (ies->transferid) 06777 iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid); 06778 send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); 06779 return 0; 06780 }
static int uncompress_subclass | ( | unsigned char | csub | ) | [static] |
Definition at line 1305 of file chan_iax2.c.
References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.
Referenced by decode_frame(), and socket_process().
01306 { 01307 /* If the SC_LOG flag is set, return 2^csub otherwise csub */ 01308 if (csub & IAX_FLAG_SC_LOG) { 01309 /* special case for 'compressed' -1 */ 01310 if (csub == 0xff) 01311 return -1; 01312 else 01313 return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); 01314 } 01315 else 01316 return csub; 01317 }
static void unlink_peer | ( | struct iax2_peer * | peer | ) | [static] |
Definition at line 7032 of file chan_iax2.c.
References ao2_unlink, ast_sched_del(), iax2_peer::expire, peer_unref(), iax2_peer::pokeexpire, and sched.
Referenced by __expire_registry(), build_peer(), and prune_peers().
07033 { 07034 if (peer->expire > -1) { 07035 if (!ast_sched_del(sched, peer->expire)) { 07036 peer->expire = -1; 07037 peer_unref(peer); 07038 } 07039 } 07040 07041 if (peer->pokeexpire > -1) { 07042 if (!ast_sched_del(sched, peer->pokeexpire)) { 07043 peer->pokeexpire = -1; 07044 peer_unref(peer); 07045 } 07046 } 07047 07048 ao2_unlink(peers, peer); 07049 }
static int unload_module | ( | void | ) | [static] |
Definition at line 12363 of file chan_iax2.c.
References __unload_module(), ast_custom_function_unregister(), iaxpeer_function, and iaxvar_function.
12364 { 12365 ast_custom_function_unregister(&iaxpeer_function); 12366 ast_custom_function_unregister(&iaxvar_function); 12367 return __unload_module(); 12368 }
static void unlock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 4072 of file chan_iax2.c.
References ast_mutex_unlock().
Referenced by iax2_bridge().
04073 { 04074 ast_mutex_unlock(&iaxsl[callno1]); 04075 ast_mutex_unlock(&iaxsl[callno0]); 04076 }
static void unwrap_timestamp | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2976 of file chan_iax2.c.
References iax_frame::af, ast_debug, AST_FRAME_VIDEO, iax_frame::callno, ast_frame::frametype, and iax_frame::ts.
Referenced by schedule_delivery().
02977 { 02978 /* Video mini frames only encode the lower 15 bits of the session 02979 * timestamp, but other frame types (e.g. audio) encode 16 bits. */ 02980 const int ts_shift = (fr->af.frametype == AST_FRAME_VIDEO) ? 15 : 16; 02981 const int lower_mask = (1 << ts_shift) - 1; 02982 const int upper_mask = ~lower_mask; 02983 const int last_upper = iaxs[fr->callno]->last & upper_mask; 02984 02985 if ( (fr->ts & upper_mask) == last_upper ) { 02986 const int x = fr->ts - iaxs[fr->callno]->last; 02987 const int threshold = (ts_shift == 15) ? 25000 : 50000; 02988 02989 if (x < -threshold) { 02990 /* Sudden big jump backwards in timestamp: 02991 What likely happened here is that miniframe timestamp has circled but we haven't 02992 gotten the update from the main packet. We'll just pretend that we did, and 02993 update the timestamp appropriately. */ 02994 fr->ts = (last_upper + (1 << ts_shift)) | (fr->ts & lower_mask); 02995 if (iaxdebug) 02996 ast_debug(1, "schedule_delivery: pushed forward timestamp\n"); 02997 } else if (x > threshold) { 02998 /* Sudden apparent big jump forwards in timestamp: 02999 What's likely happened is this is an old miniframe belonging to the previous 03000 top 15 or 16-bit timestamp that has turned up out of order. 03001 Adjust the timestamp appropriately. */ 03002 fr->ts = (last_upper - (1 << ts_shift)) | (fr->ts & lower_mask); 03003 if (iaxdebug) 03004 ast_debug(1, "schedule_delivery: pushed back timestamp\n"); 03005 } 03006 } 03007 }
static void update_jbsched | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 3011 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvnow(), chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), iax2_sched_replace(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, chan_iax2_pvt::rxcore, and sched.
Referenced by __get_from_jb(), and schedule_delivery().
03012 { 03013 int when; 03014 03015 when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore); 03016 03017 when = jb_next(pvt->jb) - when; 03018 03019 if (when <= 0) { 03020 /* XXX should really just empty until when > 0.. */ 03021 when = 1; 03022 } 03023 03024 pvt->jbid = iax2_sched_replace(pvt->jbid, sched, when, get_from_jb, 03025 CALLNO_TO_PTR(pvt->callno)); 03026 }
static void update_max_nontrunk | ( | void | ) | [static] |
Definition at line 1627 of file chan_iax2.c.
References ast_debug, and TRUNK_CALL_START.
Referenced by __find_callno(), and make_trunk().
01628 { 01629 int max = 1; 01630 int x; 01631 /* XXX Prolly don't need locks here XXX */ 01632 for (x=1;x<TRUNK_CALL_START - 1; x++) { 01633 if (iaxs[x]) 01634 max = x + 1; 01635 } 01636 maxnontrunkcall = max; 01637 if (iaxdebug) 01638 ast_debug(1, "New max nontrunk callno is %d\n", max); 01639 }
static void update_max_trunk | ( | void | ) | [static] |
Definition at line 1610 of file chan_iax2.c.
References ARRAY_LEN, ast_debug, and TRUNK_CALL_START.
Referenced by iax2_destroy(), and make_trunk().
01611 { 01612 int max = TRUNK_CALL_START; 01613 int x; 01614 01615 /* XXX Prolly don't need locks here XXX */ 01616 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01617 if (iaxs[x]) { 01618 max = x + 1; 01619 } 01620 } 01621 01622 maxtrunkcall = max; 01623 if (iaxdebug) 01624 ast_debug(1, "New max trunk callno is %d\n", max); 01625 }
static int update_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2442 of file chan_iax2.c.
References build_rand_pad(), ast_iax2_full_hdr::dcallno, decode_frame(), encrypt_frame(), f, IAX_FLAG_RETRANS, and ast_iax2_full_hdr::iseqno.
Referenced by __attempt_transmit().
02443 { 02444 /* Called with iaxsl lock held, and iaxs[callno] non-NULL */ 02445 struct ast_iax2_full_hdr *fh = f->data; 02446 struct ast_frame af; 02447 02448 /* if frame is encrypted. decrypt before updating it. */ 02449 if (f->encmethods) { 02450 decode_frame(&f->mydcx, fh, &af, &f->datalen); 02451 } 02452 /* Mark this as a retransmission */ 02453 fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno); 02454 /* Update iseqno */ 02455 f->iseqno = iaxs[f->callno]->iseqno; 02456 fh->iseqno = f->iseqno; 02457 02458 /* Now re-encrypt the frame */ 02459 if (f->encmethods) { 02460 /* since this is a retransmit frame, create a new random padding 02461 * before re-encrypting. */ 02462 build_rand_pad(f->semirand, sizeof(f->semirand)); 02463 encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen); 02464 } 02465 return 0; 02466 }
static int update_registry | ( | struct sockaddr_in * | sin, | |
int | callno, | |||
char * | devtype, | |||
int | fd, | |||
unsigned short | refresh | |||
) | [static] |
Definition at line 7141 of file chan_iax2.c.
References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verb, iax2_peer::cid_name, iax2_peer::cid_num, context, EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), globalflags, iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, inaddrcmp(), LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mailbox, manager_event, iax2_peer::name, peer_ref(), peer_unref(), realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, strsep(), version, and iax2_peer::zonetag.
Referenced by socket_process().
07142 { 07143 /* Called from IAX thread only, with proper iaxsl lock */ 07144 struct iax_ie_data ied; 07145 struct iax2_peer *p; 07146 int msgcount; 07147 char data[80]; 07148 int version; 07149 const char *peer_name; 07150 int res = -1; 07151 07152 memset(&ied, 0, sizeof(ied)); 07153 07154 peer_name = ast_strdupa(iaxs[callno]->peer); 07155 07156 /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ 07157 ast_mutex_unlock(&iaxsl[callno]); 07158 if (!(p = find_peer(peer_name, 1))) { 07159 ast_mutex_lock(&iaxsl[callno]); 07160 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 07161 return -1; 07162 } 07163 ast_mutex_lock(&iaxsl[callno]); 07164 if (!iaxs[callno]) 07165 goto return_unref; 07166 07167 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { 07168 if (sin->sin_addr.s_addr) { 07169 time_t nowtime; 07170 time(&nowtime); 07171 realtime_update_peer(peer_name, sin, nowtime); 07172 } else { 07173 realtime_update_peer(peer_name, sin, 0); 07174 } 07175 } 07176 if (inaddrcmp(&p->addr, sin)) { 07177 if (iax2_regfunk) 07178 iax2_regfunk(p->name, 1); 07179 /* Stash the IP address from which they registered */ 07180 memcpy(&p->addr, sin, sizeof(p->addr)); 07181 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry); 07182 if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) { 07183 ast_db_put("IAX/Registry", p->name, data); 07184 ast_verb(3, "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 07185 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 07186 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name); 07187 register_peer_exten(p, 1); 07188 ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ 07189 } else if (!ast_test_flag(p, IAX_TEMPONLY)) { 07190 ast_verb(3, "Unregistered IAX2 '%s' (%s)\n", p->name, 07191 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED"); 07192 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name); 07193 register_peer_exten(p, 0); 07194 ast_db_del("IAX/Registry", p->name); 07195 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", p->name); /* Activate notification */ 07196 } 07197 /* Update the host */ 07198 /* Verify that the host is really there */ 07199 iax2_poke_peer(p, callno); 07200 } 07201 07202 /* Make sure our call still exists, an INVAL at the right point may make it go away */ 07203 if (!iaxs[callno]) { 07204 res = -1; 07205 goto return_unref; 07206 } 07207 07208 /* Store socket fd */ 07209 p->sockfd = fd; 07210 /* Setup the expiry */ 07211 if (p->expire > -1) { 07212 if (!ast_sched_del(sched, p->expire)) { 07213 p->expire = -1; 07214 peer_unref(p); 07215 } 07216 } 07217 /* treat an unspecified refresh interval as the minimum */ 07218 if (!refresh) 07219 refresh = min_reg_expire; 07220 if (refresh > max_reg_expire) { 07221 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 07222 p->name, max_reg_expire, refresh); 07223 p->expiry = max_reg_expire; 07224 } else if (refresh < min_reg_expire) { 07225 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 07226 p->name, min_reg_expire, refresh); 07227 p->expiry = min_reg_expire; 07228 } else { 07229 p->expiry = refresh; 07230 } 07231 if (p->expiry && sin->sin_addr.s_addr) { 07232 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 07233 if (p->expire == -1) 07234 peer_unref(p); 07235 } 07236 iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); 07237 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); 07238 if (sin->sin_addr.s_addr) { 07239 iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); 07240 iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); 07241 if (!ast_strlen_zero(p->mailbox)) { 07242 struct ast_event *event; 07243 int new, old; 07244 char *mailbox, *context; 07245 07246 context = mailbox = ast_strdupa(p->mailbox); 07247 strsep(&context, "@"); 07248 if (ast_strlen_zero(context)) 07249 context = "default"; 07250 07251 event = ast_event_get_cached(AST_EVENT_MWI, 07252 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 07253 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 07254 AST_EVENT_IE_END); 07255 if (event) { 07256 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 07257 old = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 07258 ast_event_destroy(event); 07259 } else { /* Fall back on checking the mailbox directly */ 07260 ast_app_inboxcount(p->mailbox, &new, &old); 07261 } 07262 07263 if (new > 255) { 07264 new = 255; 07265 } 07266 if (old > 255) { 07267 old = 255; 07268 } 07269 msgcount = (old << 8) | new; 07270 07271 iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount); 07272 } 07273 if (ast_test_flag(p, IAX_HASCALLERID)) { 07274 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num); 07275 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name); 07276 } 07277 } 07278 version = iax_check_version(devtype); 07279 if (version) 07280 iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version); 07281 07282 res = 0; 07283 07284 return_unref: 07285 peer_unref(p); 07286 07287 return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1); 07288 }
static int user_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1352 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, and user.
Referenced by load_module().
01353 { 01354 struct iax2_user *user = obj, *user2 = arg; 01355 01356 return !strcmp(user->name, user2->name) ? CMP_MATCH | CMP_STOP : 0; 01357 }
static int user_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11086 of file chan_iax2.c.
References ast_set_flag, IAX_DELME, and user.
Referenced by delete_users().
11087 { 11088 struct iax2_user *user = obj; 11089 11090 ast_set_flag(user, IAX_DELME); 11091 11092 return 0; 11093 }
static void user_destructor | ( | void * | obj | ) | [static] |
Definition at line 10852 of file chan_iax2.c.
References ast_free_ha(), ast_string_field_free_memory, ast_variables_destroy(), free_context(), and user.
Referenced by build_user().
10853 { 10854 struct iax2_user *user = obj; 10855 10856 ast_free_ha(user->ha); 10857 free_context(user->contexts); 10858 if(user->vars) { 10859 ast_variables_destroy(user->vars); 10860 user->vars = NULL; 10861 } 10862 ast_string_field_free_memory(user); 10863 }
static int user_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1342 of file chan_iax2.c.
References ast_str_hash(), and user.
Referenced by load_module().
01343 { 01344 const struct iax2_user *user = obj; 01345 01346 return ast_str_hash(user->name); 01347 }
Definition at line 1405 of file chan_iax2.c.
Referenced by authenticate_request(), authenticate_verify(), build_user(), check_access(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_users(), iax2_destroy_helper(), prune_users(), and set_config().
static void vnak_retransmit | ( | int | callno, | |
int | last | |||
) | [static] |
Definition at line 7486 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, f, iax_frame::list, and send_packet().
Referenced by socket_process().
07487 { 07488 struct iax_frame *f; 07489 07490 AST_LIST_LOCK(&frame_queue); 07491 AST_LIST_TRAVERSE(&frame_queue, f, list) { 07492 /* Send a copy immediately */ 07493 if ((f->callno == callno) && iaxs[f->callno] && 07494 ((unsigned char ) (f->oseqno - last) < 128) && 07495 (f->retries >= 0)) { 07496 send_packet(f); 07497 } 07498 } 07499 AST_LIST_UNLOCK(&frame_queue); 07500 }
static int wait_for_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 3929 of file chan_iax2.c.
References chan_iax2_pvt::callno, DEADLOCK_AVOIDANCE, and chan_iax2_pvt::peercallno.
Referenced by iax2_indicate(), and iax2_setoption().
03930 { 03931 unsigned short callno = pvt->callno; 03932 03933 if (!pvt->peercallno) { 03934 /* We don't know the remote side's call number, yet. :( */ 03935 int count = 10; 03936 while (count-- && pvt && !pvt->peercallno) { 03937 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 03938 pvt = iaxs[callno]; 03939 } 03940 if (!pvt->peercallno) { 03941 return -1; 03942 } 03943 } 03944 03945 return 0; 03946 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Inter Asterisk eXchange (Ver 2)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 12539 of file chan_iax2.c.
char accountcode[AST_MAX_ACCOUNT_CODE] [static] |
Definition at line 243 of file chan_iax2.c.
Referenced by __oh323_new(), ast_cdr_setaccount(), ast_channel_alloc(), begin_dial_channel(), build_gateway(), check_peer_ok(), dahdi_new(), dial_exec_full(), do_forward(), gtalk_new(), jingle_new(), local_call(), mgcp_new(), sip_new(), and tds_log().
int adsi = 0 [static] |
int amaflags = 0 [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 12539 of file chan_iax2.c.
int authdebug = 1 [static] |
Definition at line 159 of file chan_iax2.c.
int autokill = 0 [static] |
Definition at line 160 of file chan_iax2.c.
struct ast_cli_entry cli_iax2[] [static] |
unsigned int cos |
Definition at line 170 of file chan_iax2.c.
struct sockaddr_in debugaddr [static] |
Definition at line 877 of file chan_iax2.c.
Referenced by handle_cli_iax2_set_debug(), iax_outputframe(), and reload_config().
char default_parkinglot[AST_MAX_CONTEXT] [static] |
Definition at line 140 of file chan_iax2.c.
int defaultsockfd = -1 [static] |
Definition at line 182 of file chan_iax2.c.
int delayreject = 0 [static] |
Definition at line 248 of file chan_iax2.c.
int global_max_trunk_mtu [static] |
Maximum MTU, 0 if not used
Definition at line 135 of file chan_iax2.c.
int global_rtautoclear = 120 [static] |
Definition at line 301 of file chan_iax2.c.
struct ast_flags globalflags = { 0 } [static] |
Definition at line 251 of file chan_iax2.c.
Referenced by __expire_registry(), __find_callno(), aji_create_client(), aji_load_config(), apply_general_options(), build_peer(), build_user(), find_or_create(), find_user(), find_user_realtime(), forward_message(), handle_minivm_show_settings(), iax2_request(), iax2_trunk_queue(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), send_trunk(), sendmail(), set_config(), set_config_destroy(), socket_process(), update_registry(), and vm_execmain().
int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static] |
Definition at line 229 of file chan_iax2.c.
int iax2_encryption = 0 [static] |
Definition at line 249 of file chan_iax2.c.
int(*) iax2_regfunk(const char *username, int onoff) = NULL |
Definition at line 184 of file chan_iax2.c.
Referenced by __expire_registry(), reg_source_db(), and update_registry().
struct ast_switch iax2_switch [static] |
struct ast_channel_tech iax2_tech [static] |
Definition at line 989 of file chan_iax2.c.
Referenced by __unload_module(), acf_channel_read(), acf_channel_write(), ast_iax2_new(), function_iaxpeer(), iax2_bridge(), iax2_prov_app(), and load_module().
struct ast_datastore_info iax2_variable_datastore_info [static] |
Initial value:
{ .type = "IAX2_VARIABLE", .duplicate = iax2_dup_variable_datastore, .destroy = iax2_free_variable_datastore, }
Definition at line 1034 of file chan_iax2.c.
Referenced by acf_iaxvar_read(), acf_iaxvar_write(), ast_iax2_new(), authenticate_reply(), iax2_call(), and socket_process().
struct ao2_container* iax_peercallno_pvts [static] |
Another container of iax2_pvt structures.
Active IAX2 pvt structs are also stored in this container, if they are a part of an active call where we know the remote side's call number. The reason for this is that incoming media frames do not contain our call number. So, instead of having to iterate the entire iaxs array, we use this container to look up calls where the remote side is using a given call number.
Definition at line 833 of file chan_iax2.c.
Referenced by __find_callno(), __unload_module(), load_module(), remove_by_peercallno(), and store_by_peercallno().
struct ao2_container* iax_transfercallno_pvts [static] |
Another container of iax2_pvt structures.
*
Active IAX2 pvt stucts used during transfering a call are stored here.
Definition at line 870 of file chan_iax2.c.
Referenced by __find_callno(), __unload_module(), load_module(), remove_by_transfercallno(), and store_by_transfercallno().
int iaxactivethreadcount = 0 [static] |
Definition at line 479 of file chan_iax2.c.
Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().
int iaxcompat = 0 [static] |
Definition at line 161 of file chan_iax2.c.
int iaxdebug = 0 [static] |
Definition at line 231 of file chan_iax2.c.
int iaxdefaultdpcache = 10 * 60 [static] |
Definition at line 164 of file chan_iax2.c.
int iaxdefaulttimeout = 5 [static] |
Definition at line 166 of file chan_iax2.c.
int iaxdynamicthreadcount = 0 [static] |
Definition at line 477 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 chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static] |
an array of iax2 pvt structures
The container for active chan_iax2_pvt structures is implemented as an array for extremely quick direct access to the correct pvt structure based on the local call number. The local call number is used as the index into the array where the associated pvt structure is stored.
Definition at line 822 of file chan_iax2.c.
Referenced by iax_showframe().
ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static] |
chan_iax2_pvt structure locks
These locks are used when accessing a pvt structure in the iaxs array. The index used here is the same as used in the iaxs array. It is the local call number for the associated pvt struct.
Definition at line 842 of file chan_iax2.c.
int iaxthreadcount = DEFAULT_THREAD_COUNT [static] |
Definition at line 475 of file chan_iax2.c.
Referenced by handle_cli_iax2_show_threads(), set_config(), and start_network_thread().
int iaxtrunkdebug = 0 [static] |
Definition at line 233 of file chan_iax2.c.
struct ast_custom_function iaxvar_function [static] |
struct io_context* io [static] |
Definition at line 226 of file chan_iax2.c.
int jittertargetextra = 40 [static] |
Definition at line 152 of file chan_iax2.c.
int lagrq_time = 10 [static] |
Definition at line 148 of file chan_iax2.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 142 of file chan_iax2.c.
int last_authmethod = 0 [static] |
Definition at line 162 of file chan_iax2.c.
The last time a call number was used.
It is important to know the last time that a call number was used locally so that it is not used again too soon. The reason for this is the same as the reason that the TCP protocol state machine requires a "TIME WAIT" state.
For example, say that a call is up. Then, the remote side sends a HANGUP, which we respond to with an ACK. However, there is no way to know whether the ACK made it there successfully. If it were to get lost, the remote side may retransmit the HANGUP. If in the meantime, this call number has been reused locally, given the right set of circumstances, this retransmitted HANGUP could potentially improperly hang up the new session. So, to avoid this potential issue, we must wait a specified timeout period before reusing a local call number.
The specified time that we must wait before reusing a local call number is defined as MIN_REUSE_TIME, with a default of 60 seconds.
Definition at line 863 of file chan_iax2.c.
int max_reg_expire [static] |
Definition at line 174 of file chan_iax2.c.
int max_retries = 4 [static] |
Definition at line 146 of file chan_iax2.c.
int maxauthreq = 3 [static] |
Definition at line 145 of file chan_iax2.c.
int maxjitterbuffer = 1000 [static] |
Definition at line 149 of file chan_iax2.c.
int maxjitterinterps = 10 [static] |
Definition at line 151 of file chan_iax2.c.
int maxnontrunkcall = 1 [static] |
Definition at line 944 of file chan_iax2.c.
int maxtrunkcall = TRUNK_CALL_START [static] |
Definition at line 943 of file chan_iax2.c.
int min_reg_expire [static] |
Definition at line 173 of file chan_iax2.c.
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 244 of file chan_iax2.c.
char mohsuggest[MAX_MUSICCLASS] [static] |
Definition at line 245 of file chan_iax2.c.
Referenced by check_peer_ok(), create_addr_from_peer(), and sip_alloc().
struct ast_netsock_list* netsock [static] |
Definition at line 180 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 253 of file chan_iax2.c.
struct ast_netsock_list* outsock [static] |
used if sourceaddress specified and bindaddr == INADDR_ANY
Definition at line 181 of file chan_iax2.c.
Referenced by __unload_module(), load_module(), peer_set_srcaddr(), and set_config().
char* papp = "IAX2Provision" [static] |
char* pdescrip [static] |
Initial value:
" IAX2Provision([template]): Provisions the calling IAXy (assuming\n" "the calling entity is in fact an IAXy) with the given template or\n" "default if one is not specified. Returns -1 on error or 0 on success.\n"
Definition at line 10085 of file chan_iax2.c.
Referenced by load_module().
struct ao2_container* peers [static] |
Definition at line 693 of file chan_iax2.c.
int ping_time = 21 [static] |
Definition at line 147 of file chan_iax2.c.
struct ast_codec_pref prefs [static] |
Definition at line 126 of file chan_iax2.c.
Referenced by ast_best_codec(), ast_rtp_codec_setpref(), build_peer(), build_user(), check_access(), create_addr(), gtalk_create_member(), gtalk_load_config(), jingle_create_member(), jingle_load_config(), new_iax(), set_config(), set_local_capabilities(), and set_peer_capabilities().
char* psyn = "Provision a calling IAXy with a given template" [static] |
struct { ... } qos [static] |
Referenced by acf_channel_read(), peer_set_srcaddr(), reload_config(), set_config(), and start_rtp().
char regcontext[AST_MAX_CONTEXT] = "" [static] |
Definition at line 143 of file chan_iax2.c.
int resyncthreshold = 1000 [static] |
Definition at line 150 of file chan_iax2.c.
struct sched_context* sched [static] |
Definition at line 227 of file chan_iax2.c.
ast_cond_t sched_cond [static] |
Definition at line 256 of file chan_iax2.c.
ast_mutex_t sched_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 255 of file chan_iax2.c.
Referenced by __unload_module(), iax2_sched_add(), iax2_sched_replace(), iax2_transmit(), and sched_thread().
pthread_t schedthreadid = AST_PTHREADT_NULL [static] |
Definition at line 254 of file chan_iax2.c.
int srvlookup = 0 [static] |
const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static] |
Definition at line 128 of file chan_iax2.c.
int test_losspct = 0 [static] |
Definition at line 235 of file chan_iax2.c.
Definition at line 178 of file chan_iax2.c.
Referenced by __unload_module(), build_peer(), build_user(), check_timer(), find_timer(), load_module(), network_thread(), pthread_timer_ack(), pthread_timer_close(), pthread_timer_destructor(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), pthread_timer_hash(), pthread_timer_open(), pthread_timer_set_rate(), run_timer(), set_state(), timing_read(), and timing_test().
unsigned int tos |
Definition at line 169 of file chan_iax2.c.
int trunk_maxmtu [static] |
Definition at line 136 of file chan_iax2.c.
int trunk_nmaxmtu [static] |
Trunk MTU statistics
Definition at line 136 of file chan_iax2.c.
int trunk_timed [static] |
Definition at line 136 of file chan_iax2.c.
int trunk_untimed [static] |
Definition at line 136 of file chan_iax2.c.
int trunkfreq = 20 [static] |
Definition at line 156 of file chan_iax2.c.
int trunkmaxsize = MAX_TRUNKDATA [static] |
Definition at line 157 of file chan_iax2.c.
struct ao2_container* users [static] |
Definition at line 696 of file chan_iax2.c.
Referenced by delete_users(), find_user(), load_module(), pp_each_user_exec(), and unload_module().