#include "asterisk.h"
#include <sys/mman.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <signal.h>
#include <strings.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <regex.h>
#include <sys/ioctl.h>
#include <dahdi/user.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/md5.h"
#include "asterisk/cdr.h"
#include "asterisk/crypto.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/app.h"
#include "asterisk/astdb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/localtime.h"
#include "asterisk/aes.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/netsock.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "asterisk/event.h"
#include "asterisk/astobj2.h"
#include "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
#include "jitterbuf.h"
Go to the source code of this file.
Data Structures | |
struct | active_list |
struct | chan_iax2_pvt |
struct | create_addr_info |
struct | dpcache |
struct | dpreq_data |
struct | dynamic_list |
struct | firmwares |
struct | frame_queue |
a list of frames that may need to be retransmitted More... | |
struct | iax2_context |
struct | iax2_dpcache |
struct | iax2_peer |
struct | iax2_pkt_buf |
struct | iax2_registry |
struct | iax2_thread |
struct | iax2_trunk_peer |
struct | iax2_user |
struct | iax_dual |
struct | iax_firmware |
struct | iax_rr |
struct | idle_list |
struct | parsed_dial_string |
struct | registrations |
struct | tpeers |
Defines | |
#define | ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n" |
#define | ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n" |
#define | CALLNO_TO_PTR(a) ((void *)(unsigned long)(a)) |
#define | DEBUG_SCHED_MULTITHREAD |
#define | DEBUG_SUPPORT |
#define | DEFAULT_DROP 3 |
#define | DEFAULT_FREQ_NOTOK 10 * 1000 |
#define | DEFAULT_FREQ_OK 60 * 1000 |
#define | DEFAULT_MAX_THREAD_COUNT 100 |
#define | DEFAULT_MAXMS 2000 |
#define | DEFAULT_RETRY_TIME 1000 |
#define | DEFAULT_THREAD_COUNT 10 |
#define | DEFAULT_TRUNKDATA 640 * 10 |
#define | FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s %s%s %3s%s\n" |
#define | FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
#define | FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
#define | FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
#define | FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s %s %9s\n" |
#define | FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
#define | FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
#define | FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
#define | FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
#define | GAMMA (0.01) |
#define | IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
#define | IAX_CAPABILITY_FULLBANDWIDTH (0xFFFF & ~AST_FORMAT_AUDIO_UNDEFINED) |
#define | IAX_CAPABILITY_LOWBANDWIDTH |
#define | IAX_CAPABILITY_LOWFREE |
#define | IAX_CAPABILITY_MEDBANDWIDTH |
#define | MARK_IAX_SUBCLASS_TX 0x8000 |
#define | MAX_JITTER_BUFFER 50 |
#define | MAX_PEER_BUCKETS 563 |
#define | MAX_RETRY_TIME 10000 |
#define | MAX_TIMESTAMP_SKEW 160 |
#define | MAX_TRUNK_MTU 1240 |
Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240. | |
#define | MAX_TRUNKDATA 640 * 200 |
#define | MAX_USER_BUCKETS MAX_PEER_BUCKETS |
#define | MEMORY_SIZE 100 |
#define | MIN_JITTER_BUFFER 10 |
#define | MIN_RETRY_TIME 100 |
#define | MIN_REUSE_TIME 60 |
#define | NEW_ALLOW 1 |
#define | NEW_FORCE 2 |
#define | NEW_PREVENT 0 |
#define | PTR_TO_CALLNO(a) ((unsigned short)(unsigned long)(a)) |
#define | SCHED_MULTITHREADED |
#define | schedule_action(func, data) __schedule_action(func, data, __PRETTY_FUNCTION__) |
#define | TRUNK_CALL_START ARRAY_LEN(iaxs) / 2 |
#define | TS_GAP_FOR_JB_RESYNC 5000 |
Enumerations | |
enum | { CACHE_FLAG_EXISTS = (1 << 0), CACHE_FLAG_NONEXISTENT = (1 << 1), CACHE_FLAG_CANEXIST = (1 << 2), CACHE_FLAG_PENDING = (1 << 3), CACHE_FLAG_TIMEOUT = (1 << 4), CACHE_FLAG_TRANSMITTED = (1 << 5), CACHE_FLAG_UNKNOWN = (1 << 6), CACHE_FLAG_MATCHMORE = (1 << 7) } |
enum | iax2_flags { IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3), IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7), IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12), IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16), IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20), IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24), IAX_DELAYPBXSTART = (1 << 25), IAX_ALLOWFWDOWNLOAD = (1 << 26) } |
enum | iax2_state { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2) } |
enum | iax2_thread_iostate { IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_SCHEDREADY } |
enum | iax2_thread_type { IAX_THREAD_TYPE_POOL, IAX_THREAD_TYPE_DYNAMIC } |
enum | iax_reg_state { REG_STATE_UNREGISTERED = 0, REG_STATE_REGSENT, REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_TIMEOUT, REG_STATE_NOAUTH } |
enum | iax_transfer_state { TRANSFER_NONE = 0, TRANSFER_BEGIN, TRANSFER_READY, TRANSFER_RELEASED, TRANSFER_PASSTHROUGH, TRANSFER_MBEGIN, TRANSFER_MREADY, TRANSFER_MRELEASED, TRANSFER_MPASSTHROUGH, TRANSFER_MEDIA, TRANSFER_MEDIAPASS } |
Functions | |
static void | __attempt_transmit (const void *data) |
static void | __auth_reject (const void *nothing) |
static void | __auto_congest (const void *nothing) |
static void | __auto_hangup (const void *nothing) |
static int | __do_deliver (void *data) |
static void | __expire_registry (const void *data) |
static int | __find_callno (unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int return_locked, int check_dcallno) |
static void | __get_from_jb (const void *p) |
static void | __iax2_do_register_s (const void *data) |
static void | __iax2_poke_noanswer (const void *data) |
static void | __iax2_poke_peer_s (const void *data) |
static int | __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[]) |
static void | __reg_module (void) |
static int | __schedule_action (void(*func)(const void *data), const void *data, const char *funcname) |
static int | __send_command (struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const unsigned char *data, int datalen, int seqno, int now, int transfer, int final) |
static void | __send_lagrq (const void *data) |
static void | __send_ping (const void *data) |
static int | __unload_module (void) |
static void | __unreg_module (void) |
static int | acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen) |
static int | acf_channel_write (struct ast_channel *chan, const char *function, char *data, const char *value) |
static int | acf_iaxvar_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | acf_iaxvar_write (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
static int | apply_context (struct iax2_context *con, const char *context) |
static int | ast_cli_netstats (struct mansession *s, int fd, int limit_fmt) |
static struct ast_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 *tv) |
static int | check_access (int callno, struct sockaddr_in *sin, struct iax_ies *ies) |
static int | check_provisioning (struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver) |
static int | check_srcaddr (struct sockaddr *sa, socklen_t salen) |
Check if address can be used as packet source. | |
static int | complete_dpreply (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
static char * | complete_iax2_show_peer (const char *line, const char *word, int pos, int state) |
static char * | complete_iax2_unregister (const char *line, const char *word, int pos, int state) |
static int | complete_transfer (int callno, struct iax_ies *ies) |
static unsigned char | compress_subclass (int subclass) |
static void | construct_rr (struct chan_iax2_pvt *pvt, struct iax_ie_data *iep) |
static int | create_addr (const char *peername, struct ast_channel *c, struct sockaddr_in *sin, struct create_addr_info *cai) |
static int | decode_frame (ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static int | decrypt_frame (int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static void | defer_full_frame (struct iax2_thread *from_here, struct iax2_thread *to_here) |
Queue the last read full frame for processing by a certain thread. | |
static void | delete_users (void) |
static void | destroy_firmware (struct iax_firmware *cur) |
static void | dp_lookup (int callno, const char *context, const char *callednum, const char *callerid, int skiplock) |
static void * | dp_lookup_thread (void *data) |
static int | encrypt_frame (ast_aes_encrypt_key *ecx, struct ast_iax2_full_hdr *fh, unsigned char *poo, int *datalen) |
static int | expire_registry (const void *data) |
static struct iax2_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 *tv, int callno, unsigned int ts) |
static void | free_context (struct iax2_context *con) |
static int | function_iaxpeer (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
static int | get_auth_methods (const char *value) |
static int | get_encrypt_methods (const char *s) |
static int | get_from_jb (const void *p) |
static char * | handle_cli_iax2_provision (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_prune_realtime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug_jb (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug_jb_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug_trunk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_debug_trunk_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_set_mtu (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Set trunk MTU from CLI. | |
static char * | handle_cli_iax2_show_cache (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_firmware (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_netstats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Show one peer in detail. | |
static char * | handle_cli_iax2_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_registry (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_threads (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_test_losspct (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_iax2_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static void | handle_deferred_full_frames (struct iax2_thread *thread) |
Handle any deferred full frames for this thread. | |
static int | handle_error (void) |
static int | iax2_ack_registry (struct iax_ies *ies, struct sockaddr_in *sin, int callno) |
Acknowledgment received for OUR registration. | |
static void | iax2_ami_channelupdate (struct chan_iax2_pvt *pvt) |
Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers. | |
static int | iax2_answer (struct ast_channel *c) |
static int | iax2_append_register (const char *hostname, const char *username, const char *secret, const char *porta) |
static enum ast_bridge_result | iax2_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
static int | iax2_call (struct ast_channel *c, char *dest, int timeout) |
static int | iax2_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
part of the IAX2 dial plan switch interface | |
static unsigned int | iax2_datetime (const char *tz) |
static void | iax2_destroy (int callno) |
static void | iax2_destroy_helper (struct chan_iax2_pvt *pvt) |
static int | iax2_devicestate (void *data) |
Part of the device state notification system ---. | |
static int | iax2_digit_begin (struct ast_channel *c, char digit) |
static int | iax2_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
static int | iax2_do_register (struct iax2_registry *reg) |
static int | iax2_do_register_s (const void *data) |
static void | iax2_dprequest (struct iax2_dpcache *dp, int callno) |
static void * | iax2_dup_variable_datastore (void *) |
static int | iax2_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Execute IAX2 dialplan switch. | |
static int | iax2_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 switch interface. | |
static int | iax2_fixup (struct ast_channel *oldchannel, struct ast_channel *newchan) |
static void | iax2_frame_free (struct iax_frame *fr) |
static void | iax2_free_variable_datastore (void *) |
static int | iax2_getpeername (struct sockaddr_in sin, char *host, int len) |
static int | iax2_getpeertrunk (struct sockaddr_in sin) |
static int | iax2_hangup (struct ast_channel *c) |
static int | iax2_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen) |
static int | iax2_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 Switch interface. | |
static int | iax2_poke_noanswer (const void *data) |
static int | iax2_poke_peer (struct iax2_peer *peer, int heldcall) |
static int | iax2_poke_peer_cb (void *obj, void *arg, int flags) |
static int | iax2_poke_peer_s (const void *data) |
static int | iax2_predestroy (int callno) |
static void * | iax2_process_thread (void *data) |
static void | iax2_process_thread_cleanup (void *data) |
static int | iax2_prov_app (struct ast_channel *chan, void *data) |
static int | iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force) |
static int | iax2_queue_control_data (int callno, enum ast_control_frame_type control, const void *data, size_t datalen) |
Queue a control frame on the ast_channel owner. | |
static int | iax2_queue_frame (int callno, struct ast_frame *f) |
Queue a frame to a call's owning asterisk channel. | |
static int | iax2_queue_hangup (int callno) |
Queue a hangup frame on the ast_channel owner. | |
static struct ast_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 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 | set_timing (void) |
static void | signal_condition (ast_mutex_t *lock, ast_cond_t *cond) |
static int | socket_process (struct iax2_thread *thread) |
static int | socket_process_meta (int packet_len, struct ast_iax2_meta_hdr *meta, struct sockaddr_in *sin, int sockfd, struct iax_frame *fr) |
static int | socket_read (int *id, int fd, short events, void *cbdata) |
static void | spawn_dp_lookup (int callno, const char *context, const char *callednum, const char *callerid) |
static int | start_network_thread (void) |
static void | stop_stuff (int callno) |
static void | store_by_peercallno (struct chan_iax2_pvt *pvt) |
static void | store_by_transfercallno (struct chan_iax2_pvt *pvt) |
static int | timing_read (int *id, int fd, short events, void *cbdata) |
static int | transfercallno_pvt_cmp_cb (void *obj, void *arg, int flags) |
static int | transfercallno_pvt_hash_cb (const void *obj, const int flags) |
static int | transmit_trunk (struct iax_frame *f, struct sockaddr_in *sin, int sockfd) |
static int | try_firmware (char *s) |
static int | try_transfer (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
static int | uncompress_subclass (unsigned char csub) |
static void | unlink_peer (struct iax2_peer *peer) |
static int | unload_module (void) |
static void | unlock_both (unsigned short callno0, unsigned short callno1) |
static void | unwrap_timestamp (struct iax_frame *fr) |
static void | update_jbsched (struct chan_iax2_pvt *pvt) |
static void | update_max_nontrunk (void) |
static void | update_max_trunk (void) |
static int | update_packet (struct iax_frame *f) |
static int | update_registry (struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) |
static int | user_cmp_cb (void *obj, void *arg, int flags) |
static int | user_delme_cb (void *obj, void *arg, int flags) |
static void | user_destructor (void *obj) |
static int | user_hash_cb (const void *obj, const int flags) |
static struct iax2_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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } |
static char | accountcode [AST_MAX_ACCOUNT_CODE] |
static int | adsi = 0 |
static int | amaflags = 0 |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static int | authdebug = 1 |
static int | autokill = 0 |
static struct ast_cli_entry | cli_iax2 [] |
static struct ast_cli_entry | cli_iax2_set_debug_deprecated = { .handler = handle_cli_iax2_set_debug_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_iax2_set_debug_jb_deprecated = { .handler = handle_cli_iax2_set_debug_jb_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } |
static struct ast_cli_entry | cli_iax2_set_debug_trunk_deprecated = { .handler = handle_cli_iax2_set_debug_trunk_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } |
static char | context [80] = "default" |
static unsigned int | cos = 0 |
static int | defaultsockfd = -1 |
static int | delayreject = 0 |
static int | global_max_trunk_mtu |
static int | global_rtautoclear = 120 |
static struct ast_flags | globalflags = { 0 } |
static int | iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH |
static int | iax2_encryption = 0 |
int(*) | iax2_regfunk (const char *username, int onoff) = NULL |
static struct ast_switch | iax2_switch |
static struct ast_channel_tech | iax2_tech |
static struct ast_datastore_info | iax2_variable_datastore_info |
static struct ao2_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" |
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 int | timingfd = -1 |
static unsigned int | tos = 0 |
static int | trunk_maxmtu |
static int | trunk_nmaxmtu |
static int | trunk_timed |
static int | trunk_untimed |
static int | trunkfreq = 20 |
static int | trunkmaxsize = MAX_TRUNKDATA |
static struct ao2_container * | users |
Definition in file chan_iax2.c.
#define ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n" |
Referenced by ast_cli_netstats().
#define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n" |
Referenced by ast_cli_netstats().
#define CALLNO_TO_PTR | ( | a | ) | ((void *)(unsigned long)(a)) |
Definition at line 114 of file chan_iax2.c.
Referenced by ast_iax2_new(), iax2_call(), iax2_hangup(), and update_jbsched().
#define DEBUG_SCHED_MULTITHREAD |
Definition at line 105 of file chan_iax2.c.
#define DEBUG_SUPPORT |
Definition at line 122 of file chan_iax2.c.
#define DEFAULT_DROP 3 |
Definition at line 120 of file chan_iax2.c.
#define DEFAULT_FREQ_NOTOK 10 * 1000 |
Definition at line 208 of file chan_iax2.c.
Referenced by build_peer(), handle_response_peerpoke(), and sip_poke_noanswer().
#define DEFAULT_FREQ_OK 60 * 1000 |
#define DEFAULT_MAX_THREAD_COUNT 100 |
Definition at line 117 of file chan_iax2.c.
#define DEFAULT_MAXMS 2000 |
Definition at line 206 of file chan_iax2.c.
#define DEFAULT_RETRY_TIME 1000 |
#define DEFAULT_THREAD_COUNT 10 |
Definition at line 116 of file chan_iax2.c.
#define DEFAULT_TRUNKDATA 640 * 10 |
40ms, uncompressed linear * 10 channels
Definition at line 450 of file chan_iax2.c.
Referenced by iax2_trunk_queue().
#define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s %s%s %3s%s\n" |
#define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
#define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
#define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
#define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s %s %9s\n" |
#define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
#define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
#define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
#define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
#define GAMMA (0.01) |
Definition at line 127 of file chan_iax2.c.
#define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
#define IAX_CAPABILITY_FULLBANDWIDTH (0xFFFF & ~AST_FORMAT_AUDIO_UNDEFINED) |
Definition at line 188 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), and set_config().
#define IAX_CAPABILITY_LOWBANDWIDTH |
Value:
(IAX_CAPABILITY_MEDBANDWIDTH & \ ~AST_FORMAT_G726 & \ ~AST_FORMAT_G726_AAL2 & \ ~AST_FORMAT_ADPCM)
Definition at line 197 of file chan_iax2.c.
Referenced by set_config().
#define IAX_CAPABILITY_LOWFREE |
Value:
Definition at line 202 of file chan_iax2.c.
#define IAX_CAPABILITY_MEDBANDWIDTH |
#define MARK_IAX_SUBCLASS_TX 0x8000 |
Definition at line 458 of file chan_iax2.c.
Referenced by ast_cli_netstats(), handle_cli_iax2_show_channels(), and iax2_send().
#define MAX_JITTER_BUFFER 50 |
Definition at line 447 of file chan_iax2.c.
#define MAX_PEER_BUCKETS 563 |
This module will get much higher performance when doing a lot of user and peer lookups if the number of buckets is increased from 1. However, to maintain old behavior for Asterisk 1.4, these are set to 1 by default. When using multiple buckets, search order through these containers is considered random, so you will not be able to depend on the order the entires are specified in iax.conf for matching order.
Definition at line 675 of file chan_iax2.c.
Referenced by load_module().
#define MAX_RETRY_TIME 10000 |
#define MAX_TIMESTAMP_SKEW 160 |
maximum difference between actual and predicted ts for sending
Definition at line 452 of file chan_iax2.c.
#define MAX_TRUNK_MTU 1240 |
Maximum transmission unit for the UDP packet in the trunk not to be fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240.
Definition at line 136 of file chan_iax2.c.
Referenced by handle_cli_iax2_set_mtu(), and set_config().
#define MAX_TRUNKDATA 640 * 200 |
40ms, uncompressed linear * 200 channels
Definition at line 156 of file chan_iax2.c.
Referenced by set_config(), and set_config_destroy().
#define MAX_USER_BUCKETS MAX_PEER_BUCKETS |
#define MEMORY_SIZE 100 |
Definition at line 119 of file chan_iax2.c.
#define MIN_JITTER_BUFFER 10 |
Definition at line 448 of file chan_iax2.c.
#define MIN_RETRY_TIME 100 |
#define MIN_REUSE_TIME 60 |
#define NEW_ALLOW 1 |
#define NEW_FORCE 2 |
Definition at line 1540 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_poke_peer(), iax2_provision(), and iax2_request().
#define NEW_PREVENT 0 |
Definition at line 1538 of file chan_iax2.c.
Referenced by socket_process(), and socket_process_meta().
#define PTR_TO_CALLNO | ( | a | ) | ((unsigned short)(unsigned long)(a)) |
Definition at line 113 of file chan_iax2.c.
Referenced by __auto_congest(), __get_from_jb(), acf_channel_read(), acf_channel_write(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), iax2_write(), and scheduled_destroy().
#define SCHED_MULTITHREADED |
Definition at line 101 of file chan_iax2.c.
#define schedule_action | ( | func, | |||
data | ) | __schedule_action(func, data, __PRETTY_FUNCTION__) |
Definition at line 1144 of file chan_iax2.c.
Referenced by attempt_transmit(), auth_reject(), auto_congest(), auto_hangup(), expire_registry(), get_from_jb(), iax2_do_register_s(), iax2_poke_noanswer(), iax2_poke_peer_s(), send_lagrq(), and send_ping().
#define TRUNK_CALL_START ARRAY_LEN(iaxs) / 2 |
Definition at line 904 of file chan_iax2.c.
Referenced by __find_callno(), make_trunk(), update_max_nontrunk(), and update_max_trunk().
#define TS_GAP_FOR_JB_RESYNC 5000 |
Definition at line 455 of file chan_iax2.c.
anonymous enum |
Definition at line 684 of file chan_iax2.c.
00684 { 00685 /*! Extension exists */ 00686 CACHE_FLAG_EXISTS = (1 << 0), 00687 /*! Extension is nonexistent */ 00688 CACHE_FLAG_NONEXISTENT = (1 << 1), 00689 /*! Extension can exist */ 00690 CACHE_FLAG_CANEXIST = (1 << 2), 00691 /*! Waiting to hear back response */ 00692 CACHE_FLAG_PENDING = (1 << 3), 00693 /*! Timed out */ 00694 CACHE_FLAG_TIMEOUT = (1 << 4), 00695 /*! Request transmitted */ 00696 CACHE_FLAG_TRANSMITTED = (1 << 5), 00697 /*! Timeout */ 00698 CACHE_FLAG_UNKNOWN = (1 << 6), 00699 /*! Matchmore */ 00700 CACHE_FLAG_MATCHMORE = (1 << 7), 00701 };
enum iax2_flags |
Definition at line 253 of file chan_iax2.c.
00253 { 00254 IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ 00255 IAX_DELME = (1 << 1), /*!< Needs to be deleted */ 00256 IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ 00257 IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ 00258 IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ 00259 IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ 00260 IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ 00261 IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ 00262 /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ 00263 IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ 00264 IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ 00265 IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ 00266 IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ 00267 IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ 00268 IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ 00269 IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ 00270 IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ 00271 IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ 00272 IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ 00273 IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ 00274 IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 00275 IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ 00276 IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ 00277 IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ 00278 IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ 00279 IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a 00280 response, so that we've achieved a three-way handshake with 00281 them before sending voice or anything else*/ 00282 IAX_ALLOWFWDOWNLOAD = (1 << 26), /*!< Allow the FWDOWNL command? */ 00283 };
enum iax2_state |
Definition at line 242 of file chan_iax2.c.
00242 { 00243 IAX_STATE_STARTED = (1 << 0), 00244 IAX_STATE_AUTHENTICATED = (1 << 1), 00245 IAX_STATE_TBD = (1 << 2), 00246 };
enum iax2_thread_iostate |
Definition at line 724 of file chan_iax2.c.
00724 { 00725 IAX_IOSTATE_IDLE, 00726 IAX_IOSTATE_READY, 00727 IAX_IOSTATE_PROCESSING, 00728 IAX_IOSTATE_SCHEDREADY, 00729 };
enum iax2_thread_type |
Definition at line 731 of file chan_iax2.c.
00731 { 00732 IAX_THREAD_TYPE_POOL, 00733 IAX_THREAD_TYPE_DYNAMIC, 00734 };
enum iax_reg_state |
REG_STATE_UNREGISTERED | |
REG_STATE_REGSENT | |
REG_STATE_AUTHSENT | |
REG_STATE_REGISTERED | |
REG_STATE_REJECTED | |
REG_STATE_TIMEOUT | |
REG_STATE_NOAUTH |
Definition at line 403 of file chan_iax2.c.
00403 { 00404 REG_STATE_UNREGISTERED = 0, 00405 REG_STATE_REGSENT, 00406 REG_STATE_AUTHSENT, 00407 REG_STATE_REGISTERED, 00408 REG_STATE_REJECTED, 00409 REG_STATE_TIMEOUT, 00410 REG_STATE_NOAUTH 00411 };
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 413 of file chan_iax2.c.
00413 { 00414 TRANSFER_NONE = 0, 00415 TRANSFER_BEGIN, 00416 TRANSFER_READY, 00417 TRANSFER_RELEASED, 00418 TRANSFER_PASSTHROUGH, 00419 TRANSFER_MBEGIN, 00420 TRANSFER_MREADY, 00421 TRANSFER_MRELEASED, 00422 TRANSFER_MPASSTHROUGH, 00423 TRANSFER_MEDIA, 00424 TRANSFER_MEDIAPASS 00425 };
static void __attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2419 of file chan_iax2.c.
References AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), attempt_transmit(), iax_frame::callno, f, ast_frame::frametype, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), iax2_sched_add(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iax2_trunk_peer::list, LOG_WARNING, MAX_RETRY_TIME, ast_format::name, REG_STATE_TIMEOUT, sched, send_command(), send_packet(), ast_frame::subclass, and update_packet().
Referenced by attempt_transmit().
02420 { 02421 /* Attempt to transmit the frame to the remote peer... 02422 Called without iaxsl held. */ 02423 struct iax_frame *f = (struct iax_frame *)data; 02424 int freeme = 0; 02425 int callno = f->callno; 02426 /* Make sure this call is still active */ 02427 if (callno) 02428 ast_mutex_lock(&iaxsl[callno]); 02429 if (callno && iaxs[callno]) { 02430 if ((f->retries < 0) /* Already ACK'd */ || 02431 (f->retries >= max_retries) /* Too many attempts */) { 02432 /* Record an error if we've transmitted too many times */ 02433 if (f->retries >= max_retries) { 02434 if (f->transfer) { 02435 /* Transfer timeout */ 02436 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 02437 } else if (f->final) { 02438 if (f->final) 02439 iax2_destroy(callno); 02440 } else { 02441 if (iaxs[callno]->owner) 02442 ast_log(LOG_WARNING, "Max retries exceeded to host %s on %s (type = %d, subclass = %d, ts=%d, seqno=%d)\n", ast_inet_ntoa(iaxs[f->callno]->addr.sin_addr),iaxs[f->callno]->owner->name , f->af.frametype, f->af.subclass, f->ts, f->oseqno); 02443 iaxs[callno]->error = ETIMEDOUT; 02444 if (iaxs[callno]->owner) { 02445 struct ast_frame fr = { 0, }; 02446 /* Hangup the fd */ 02447 fr.frametype = AST_FRAME_CONTROL; 02448 fr.subclass = AST_CONTROL_HANGUP; 02449 iax2_queue_frame(callno, &fr); /* XXX */ 02450 /* Remember, owner could disappear */ 02451 if (iaxs[callno] && iaxs[callno]->owner) 02452 iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 02453 } else { 02454 if (iaxs[callno]->reg) { 02455 memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us)); 02456 iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT; 02457 iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; 02458 } 02459 iax2_destroy(callno); 02460 } 02461 } 02462 02463 } 02464 freeme = 1; 02465 } else { 02466 /* Update it if it needs it */ 02467 update_packet(f); 02468 /* Attempt transmission */ 02469 send_packet(f); 02470 f->retries++; 02471 /* Try again later after 10 times as long */ 02472 f->retrytime *= 10; 02473 if (f->retrytime > MAX_RETRY_TIME) 02474 f->retrytime = MAX_RETRY_TIME; 02475 /* Transfer messages max out at one second */ 02476 if (f->transfer && (f->retrytime > 1000)) 02477 f->retrytime = 1000; 02478 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 02479 } 02480 } else { 02481 /* Make sure it gets freed */ 02482 f->retries = -1; 02483 freeme = 1; 02484 } 02485 if (callno) 02486 ast_mutex_unlock(&iaxsl[callno]); 02487 /* Do not try again */ 02488 if (freeme) { 02489 /* Don't attempt delivery, just remove it from the queue */ 02490 AST_LIST_LOCK(&frame_queue); 02491 AST_LIST_REMOVE(&frame_queue, f, list); 02492 AST_LIST_UNLOCK(&frame_queue); 02493 f->retrans = -1; 02494 /* Free the IAX frame */ 02495 iax2_frame_free(f); 02496 } 02497 }
static void __auth_reject | ( | const void * | nothing | ) | [static] |
Definition at line 7370 of file chan_iax2.c.
References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, and send_command_final().
Referenced by auth_reject().
07371 { 07372 /* Called from IAX thread only, without iaxs lock */ 07373 int callno = (int)(long)(nothing); 07374 struct iax_ie_data ied; 07375 ast_mutex_lock(&iaxsl[callno]); 07376 if (iaxs[callno]) { 07377 memset(&ied, 0, sizeof(ied)); 07378 if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { 07379 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); 07380 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); 07381 } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { 07382 iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); 07383 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 07384 } 07385 send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); 07386 } 07387 ast_mutex_unlock(&iaxsl[callno]); 07388 }
static void __auto_congest | ( | const void * | nothing | ) | [static] |
Definition at line 3527 of file chan_iax2.c.
References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, iax2_queue_frame(), LOG_NOTICE, and PTR_TO_CALLNO.
Referenced by auto_congest().
03528 { 03529 int callno = PTR_TO_CALLNO(nothing); 03530 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; 03531 ast_mutex_lock(&iaxsl[callno]); 03532 if (iaxs[callno]) { 03533 iaxs[callno]->initid = -1; 03534 iax2_queue_frame(callno, &f); 03535 ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n"); 03536 } 03537 ast_mutex_unlock(&iaxsl[callno]); 03538 }
static void __auto_hangup | ( | const void * | nothing | ) | [static] |
Definition at line 7419 of file chan_iax2.c.
References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, and send_command_final().
Referenced by auto_hangup().
07420 { 07421 /* Called from IAX thread only, without iaxs lock */ 07422 int callno = (int)(long)(nothing); 07423 struct iax_ie_data ied; 07424 ast_mutex_lock(&iaxsl[callno]); 07425 if (iaxs[callno]) { 07426 memset(&ied, 0, sizeof(ied)); 07427 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); 07428 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); 07429 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 07430 } 07431 ast_mutex_unlock(&iaxsl[callno]); 07432 }
static int __do_deliver | ( | void * | data | ) | [static] |
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it. This function calls iax2_queue_frame(), which may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.
Definition at line 2213 of file chan_iax2.c.
References iax_frame::af, ast_clear_flag, AST_FRFLAG_HAS_TIMING_INFO, ast_test_flag, iax_frame::callno, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, and iax_frame::retrans.
Referenced by __get_from_jb(), and schedule_delivery().
02214 { 02215 /* Just deliver the packet by using queueing. This is called by 02216 the IAX thread with the iaxsl lock held. */ 02217 struct iax_frame *fr = data; 02218 fr->retrans = -1; 02219 ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO); 02220 if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) 02221 iax2_queue_frame(fr->callno, &fr->af); 02222 /* Free our iax frame */ 02223 iax2_frame_free(fr); 02224 /* And don't run again */ 02225 return 0; 02226 }
static void __expire_registry | ( | const void * | data | ) | [static] |
Definition at line 7032 of file chan_iax2.c.
References iax2_peer::addr, ast_db_del(), ast_debug, ast_device_state_changed(), ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, globalflags, iax2_regfunk, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, manager_event, iax2_peer::name, peer_unref(), realtime_update_peer(), register_peer_exten(), and unlink_peer().
Referenced by expire_registry().
07033 { 07034 struct iax2_peer *peer = (struct iax2_peer *) data; 07035 07036 if (!peer) 07037 return; 07038 07039 peer->expire = -1; 07040 07041 ast_debug(1, "Expiring registration for peer '%s'\n", peer->name); 07042 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) 07043 realtime_update_peer(peer->name, &peer->addr, 0); 07044 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 07045 /* Reset the address */ 07046 memset(&peer->addr, 0, sizeof(peer->addr)); 07047 /* Reset expiry value */ 07048 peer->expiry = min_reg_expire; 07049 if (!ast_test_flag(peer, IAX_TEMPONLY)) 07050 ast_db_del("IAX/Registry", peer->name); 07051 register_peer_exten(peer, 0); 07052 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07053 if (iax2_regfunk) 07054 iax2_regfunk(peer->name, 0); 07055 07056 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) 07057 unlink_peer(peer); 07058 07059 peer_unref(peer); 07060 }
static int __find_callno | ( | unsigned short | callno, | |
unsigned short | dcallno, | |||
struct sockaddr_in * | sin, | |||
int | new, | |||
int | sockfd, | |||
int | return_locked, | |||
int | check_dcallno | |||
) | [static] |
Definition at line 1685 of file chan_iax2.c.
References chan_iax2_pvt::addr, ao2_find(), ao2_ref(), ast_copy_flags, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_string_field_set, ast_tvnow(), chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, globalflags, iax2_getpeername(), iax2_sched_add(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_peercallno_pvts, iax_transfercallno_pvts, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, LOG_WARNING, match(), MIN_REUSE_TIME, NEW_ALLOW, new_iax(), OBJ_POINTER, chan_iax2_pvt::peercallno, sched, send_lagrq(), send_ping(), store_by_peercallno(), chan_iax2_pvt::transfer, TRUNK_CALL_START, and update_max_nontrunk().
Referenced by find_callno(), and find_callno_locked().
01686 { 01687 int res = 0; 01688 int x; 01689 struct timeval now; 01690 char host[80]; 01691 01692 if (new <= NEW_ALLOW) { 01693 if (callno) { 01694 struct chan_iax2_pvt *pvt; 01695 struct chan_iax2_pvt tmp_pvt = { 01696 .callno = dcallno, 01697 .peercallno = callno, 01698 .transfercallno = callno, 01699 /* hack!! */ 01700 .frames_received = check_dcallno, 01701 }; 01702 01703 memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr)); 01704 /* this works for finding normal call numbers not involving transfering */ 01705 if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 01706 if (return_locked) { 01707 ast_mutex_lock(&iaxsl[pvt->callno]); 01708 } 01709 res = pvt->callno; 01710 ao2_ref(pvt, -1); 01711 pvt = NULL; 01712 return res; 01713 } 01714 /* this searches for transfer call numbers that might not get caught otherwise */ 01715 memset(&tmp_pvt.addr, 0, sizeof(tmp_pvt.addr)); 01716 memcpy(&tmp_pvt.transfer, sin, sizeof(tmp_pvt.addr)); 01717 if ((pvt = ao2_find(iax_transfercallno_pvts, &tmp_pvt, OBJ_POINTER))) { 01718 if (return_locked) { 01719 ast_mutex_lock(&iaxsl[pvt->callno]); 01720 } 01721 res = pvt->callno; 01722 ao2_ref(pvt, -1); 01723 pvt = NULL; 01724 return res; 01725 } 01726 } 01727 /* This will occur on the first response to a message that we initiated, 01728 * such as a PING. */ 01729 if (dcallno) { 01730 ast_mutex_lock(&iaxsl[dcallno]); 01731 } 01732 if (callno && dcallno && iaxs[dcallno] && !iaxs[dcallno]->peercallno && match(sin, callno, dcallno, iaxs[dcallno], check_dcallno)) { 01733 iaxs[dcallno]->peercallno = callno; 01734 res = dcallno; 01735 store_by_peercallno(iaxs[dcallno]); 01736 if (!res || !return_locked) { 01737 ast_mutex_unlock(&iaxsl[dcallno]); 01738 } 01739 return res; 01740 } 01741 if (dcallno) { 01742 ast_mutex_unlock(&iaxsl[dcallno]); 01743 } 01744 #ifdef IAX_OLD_FIND 01745 /* If we get here, we SHOULD NOT find a call structure for this 01746 callno; if we do, it means that there is a call structure that 01747 has a peer callno but did NOT get entered into the hash table, 01748 which is bad. 01749 01750 If we find a call structure using this old, slow method, output a log 01751 message so we'll know about it. After a few months of leaving this in 01752 place, if we don't hear about people seeing these messages, we can 01753 remove this code for good. 01754 */ 01755 01756 for (x = 1; !res && x < maxnontrunkcall; x++) { 01757 ast_mutex_lock(&iaxsl[x]); 01758 if (iaxs[x]) { 01759 /* Look for an exact match */ 01760 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01761 res = x; 01762 } 01763 } 01764 if (!res || !return_locked) 01765 ast_mutex_unlock(&iaxsl[x]); 01766 } 01767 for (x = TRUNK_CALL_START; !res && x < maxtrunkcall; x++) { 01768 ast_mutex_lock(&iaxsl[x]); 01769 if (iaxs[x]) { 01770 /* Look for an exact match */ 01771 if (match(sin, callno, dcallno, iaxs[x], check_dcallno)) { 01772 res = x; 01773 } 01774 } 01775 if (!res || !return_locked) 01776 ast_mutex_unlock(&iaxsl[x]); 01777 } 01778 #endif 01779 } 01780 if (!res && (new >= NEW_ALLOW)) { 01781 int start, found = 0; 01782 01783 /* It may seem odd that we look through the peer list for a name for 01784 * this *incoming* call. Well, it is weird. However, users don't 01785 * have an IP address/port number that we can match against. So, 01786 * this is just checking for a peer that has that IP/port and 01787 * assuming that we have a user of the same name. This isn't always 01788 * correct, but it will be changed if needed after authentication. */ 01789 if (!iax2_getpeername(*sin, host, sizeof(host))) 01790 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 01791 01792 now = ast_tvnow(); 01793 start = 2 + (ast_random() % (TRUNK_CALL_START - 1)); 01794 for (x = start; 1; x++) { 01795 if (x == TRUNK_CALL_START) { 01796 x = 1; 01797 continue; 01798 } 01799 01800 /* Find first unused call number that hasn't been used in a while */ 01801 ast_mutex_lock(&iaxsl[x]); 01802 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01803 found = 1; 01804 break; 01805 } 01806 ast_mutex_unlock(&iaxsl[x]); 01807 01808 if (x == start - 1) { 01809 break; 01810 } 01811 } 01812 /* We've still got lock held if we found a spot */ 01813 if (x == start - 1 && !found) { 01814 ast_log(LOG_WARNING, "No more space\n"); 01815 return 0; 01816 } 01817 iaxs[x] = new_iax(sin, host); 01818 update_max_nontrunk(); 01819 if (iaxs[x]) { 01820 if (iaxdebug) 01821 ast_debug(1, "Creating new call structure %d\n", x); 01822 iaxs[x]->sockfd = sockfd; 01823 iaxs[x]->addr.sin_port = sin->sin_port; 01824 iaxs[x]->addr.sin_family = sin->sin_family; 01825 iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr; 01826 iaxs[x]->peercallno = callno; 01827 iaxs[x]->callno = x; 01828 iaxs[x]->pingtime = DEFAULT_RETRY_TIME; 01829 iaxs[x]->expiry = min_reg_expire; 01830 iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01831 iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01832 iaxs[x]->amaflags = amaflags; 01833 ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 01834 01835 ast_string_field_set(iaxs[x], accountcode, accountcode); 01836 ast_string_field_set(iaxs[x], mohinterpret, mohinterpret); 01837 ast_string_field_set(iaxs[x], mohsuggest, mohsuggest); 01838 01839 if (iaxs[x]->peercallno) { 01840 store_by_peercallno(iaxs[x]); 01841 } 01842 } else { 01843 ast_log(LOG_WARNING, "Out of resources\n"); 01844 ast_mutex_unlock(&iaxsl[x]); 01845 return 0; 01846 } 01847 if (!return_locked) 01848 ast_mutex_unlock(&iaxsl[x]); 01849 res = x; 01850 } 01851 return res; 01852 }
static void __get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 2980 of file chan_iax2.c.
References __do_deliver(), ast_codec_interp_len(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_test_flag, ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, chan_iax2_pvt::jb, JB_DROP, JB_EMPTY, jb_get(), JB_INTERP, jb_next(), JB_NOFRAME, JB_OK, chan_iax2_pvt::jbid, jb_frame::ms, iax2_trunk_peer::next, ast_frame::offset, PTR_TO_CALLNO, chan_iax2_pvt::rxcore, ast_frame::samples, ast_frame::src, ast_frame::subclass, update_jbsched(), and chan_iax2_pvt::voiceformat.
Referenced by get_from_jb().
02981 { 02982 int callno = PTR_TO_CALLNO(p); 02983 struct chan_iax2_pvt *pvt = NULL; 02984 struct iax_frame *fr; 02985 jb_frame frame; 02986 int ret; 02987 long now; 02988 long next; 02989 struct timeval tv = ast_tvnow(); 02990 02991 /* Make sure we have a valid private structure before going on */ 02992 ast_mutex_lock(&iaxsl[callno]); 02993 pvt = iaxs[callno]; 02994 if (!pvt) { 02995 /* No go! */ 02996 ast_mutex_unlock(&iaxsl[callno]); 02997 return; 02998 } 02999 03000 pvt->jbid = -1; 03001 03002 /* round up a millisecond since ast_sched_runq does; */ 03003 /* prevents us from spinning while waiting for our now */ 03004 /* to catch up with runq's now */ 03005 tv.tv_usec += 1000; 03006 03007 now = ast_tvdiff_ms(tv, pvt->rxcore); 03008 03009 if(now >= (next = jb_next(pvt->jb))) { 03010 ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat)); 03011 switch(ret) { 03012 case JB_OK: 03013 fr = frame.data; 03014 __do_deliver(fr); 03015 /* __do_deliver() can cause the call to disappear */ 03016 pvt = iaxs[callno]; 03017 break; 03018 case JB_INTERP: 03019 { 03020 struct ast_frame af = { 0, }; 03021 03022 /* create an interpolation frame */ 03023 af.frametype = AST_FRAME_VOICE; 03024 af.subclass = pvt->voiceformat; 03025 af.samples = frame.ms * 8; 03026 af.src = "IAX2 JB interpolation"; 03027 af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); 03028 af.offset = AST_FRIENDLY_OFFSET; 03029 03030 /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame, 03031 * which we'd need to malloc, and then it would free it. That seems like a drag */ 03032 if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 03033 iax2_queue_frame(callno, &af); 03034 /* iax2_queue_frame() could cause the call to disappear */ 03035 pvt = iaxs[callno]; 03036 } 03037 } 03038 break; 03039 case JB_DROP: 03040 iax2_frame_free(frame.data); 03041 break; 03042 case JB_NOFRAME: 03043 case JB_EMPTY: 03044 /* do nothing */ 03045 break; 03046 default: 03047 /* shouldn't happen */ 03048 break; 03049 } 03050 } 03051 if (pvt) 03052 update_jbsched(pvt); 03053 ast_mutex_unlock(&iaxsl[callno]); 03054 }
static void __iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 6717 of file chan_iax2.c.
References iax2_registry::expire, and iax2_do_register().
Referenced by iax2_do_register_s().
06718 { 06719 struct iax2_registry *reg = (struct iax2_registry *)data; 06720 reg->expire = -1; 06721 iax2_do_register(reg); 06722 }
static void __iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 10139 of file chan_iax2.c.
References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_peer::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iax2_sched_add(), iax2_peer::lastms, LOG_NOTICE, manager_event, iax2_peer::name, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, and sched.
Referenced by iax2_poke_noanswer().
10140 { 10141 struct iax2_peer *peer = (struct iax2_peer *)data; 10142 int callno; 10143 10144 if (peer->lastms > -1) { 10145 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); 10146 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); 10147 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 10148 } 10149 if ((callno = peer->callno) > 0) { 10150 ast_mutex_lock(&iaxsl[callno]); 10151 iax2_destroy(callno); 10152 ast_mutex_unlock(&iaxsl[callno]); 10153 } 10154 peer->callno = 0; 10155 peer->lastms = -1; 10156 /* Try again quickly */ 10157 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 10158 if (peer->pokeexpire == -1) 10159 peer_unref(peer); 10160 }
static void __iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 7482 of file chan_iax2.c.
References iax2_poke_peer(), and peer_unref().
Referenced by iax2_poke_peer_s().
07483 { 07484 struct iax2_peer *peer = (struct iax2_peer *)data; 07485 iax2_poke_peer(peer, 0); 07486 peer_unref(peer); 07487 }
static int __iax2_show_peers | ( | int | manager, | |
int | fd, | |||
struct mansession * | s, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 5134 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_cli(), ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, iax2_peer::name, name, peer_status(), peer_unref(), RESULT_SHOWUSAGE, RESULT_SUCCESS, s, status, and iax2_peer::username.
Referenced by handle_cli_iax2_show_peers(), and manager_iax2_show_peers().
05135 { 05136 regex_t regexbuf; 05137 int havepattern = 0; 05138 int total_peers = 0; 05139 int online_peers = 0; 05140 int offline_peers = 0; 05141 int unmonitored_peers = 0; 05142 struct ao2_iterator i; 05143 05144 #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" 05145 #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" 05146 05147 struct iax2_peer *peer = NULL; 05148 char name[256]; 05149 int registeredonly=0; 05150 char *term = manager ? "\r\n" : "\n"; 05151 char idtext[256] = ""; 05152 switch (argc) { 05153 case 6: 05154 if (!strcasecmp(argv[3], "registered")) 05155 registeredonly = 1; 05156 else 05157 return RESULT_SHOWUSAGE; 05158 if (!strcasecmp(argv[4], "like")) { 05159 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB)) 05160 return RESULT_SHOWUSAGE; 05161 havepattern = 1; 05162 } else 05163 return RESULT_SHOWUSAGE; 05164 break; 05165 case 5: 05166 if (!strcasecmp(argv[3], "like")) { 05167 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 05168 return RESULT_SHOWUSAGE; 05169 havepattern = 1; 05170 } else 05171 return RESULT_SHOWUSAGE; 05172 break; 05173 case 4: 05174 if (!strcasecmp(argv[3], "registered")) 05175 registeredonly = 1; 05176 else 05177 return RESULT_SHOWUSAGE; 05178 break; 05179 case 3: 05180 break; 05181 default: 05182 return RESULT_SHOWUSAGE; 05183 } 05184 05185 05186 if (!s) 05187 ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 05188 05189 i = ao2_iterator_init(peers, 0); 05190 for (peer = ao2_iterator_next(&i); peer; 05191 peer_unref(peer), peer = ao2_iterator_next(&i)) { 05192 char nm[20]; 05193 char status[20]; 05194 char srch[2000]; 05195 int retstatus; 05196 05197 if (registeredonly && !peer->addr.sin_addr.s_addr) 05198 continue; 05199 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) 05200 continue; 05201 05202 if (!ast_strlen_zero(peer->username)) 05203 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 05204 else 05205 ast_copy_string(name, peer->name, sizeof(name)); 05206 05207 retstatus = peer_status(peer, status, sizeof(status)); 05208 if (retstatus > 0) 05209 online_peers++; 05210 else if (!retstatus) 05211 offline_peers++; 05212 else 05213 unmonitored_peers++; 05214 05215 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 05216 05217 snprintf(srch, sizeof(srch), FORMAT, name, 05218 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 05219 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 05220 nm, 05221 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 05222 peer->encmethods ? "(E)" : " ", status, term); 05223 05224 if (s) 05225 astman_append(s, 05226 "Event: PeerEntry\r\n%s" 05227 "Channeltype: IAX2\r\n" 05228 "ChanObjectType: peer\r\n" 05229 "ObjectName: %s\r\n" 05230 "IPaddress: %s\r\n" 05231 "IPport: %d\r\n" 05232 "Dynamic: %s\r\n" 05233 "Status: %s\r\n\r\n", 05234 idtext, 05235 name, 05236 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-", 05237 ntohs(peer->addr.sin_port), 05238 ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no", 05239 status); 05240 05241 else 05242 ast_cli(fd, FORMAT, name, 05243 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 05244 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 05245 nm, 05246 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 05247 peer->encmethods ? "(E)" : " ", status, term); 05248 total_peers++; 05249 } 05250 05251 if (!s) 05252 ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 05253 05254 if (havepattern) 05255 regfree(®exbuf); 05256 05257 return RESULT_SUCCESS; 05258 #undef FORMAT 05259 #undef FORMAT2 05260 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 12524 of file chan_iax2.c.
static int __schedule_action | ( | void(*)(const void *data) | func, | |
const void * | data, | |||
const char * | funcname | |||
) | [static] |
Definition at line 1119 of file chan_iax2.c.
References ast_copy_string(), ast_debug, find_idle_thread(), IAX_IOSTATE_SCHEDREADY, signal_condition(), and thread.
01120 { 01121 struct iax2_thread *thread = NULL; 01122 static time_t lasterror; 01123 static time_t t; 01124 01125 thread = find_idle_thread(); 01126 01127 if (thread != NULL) { 01128 thread->schedfunc = func; 01129 thread->scheddata = data; 01130 thread->iostate = IAX_IOSTATE_SCHEDREADY; 01131 #ifdef DEBUG_SCHED_MULTITHREAD 01132 ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc)); 01133 #endif 01134 signal_condition(&thread->lock, &thread->cond); 01135 return 0; 01136 } 01137 time(&t); 01138 if (t != lasterror) 01139 ast_debug(1, "Out of idle IAX2 threads for scheduling!\n"); 01140 lasterror = t; 01141 01142 return -1; 01143 }
static int __send_command | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno, | |||
int | now, | |||
int | transfer, | |||
int | final | |||
) | [static] |
Definition at line 5936 of file chan_iax2.c.
References f, and iax2_send().
Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().
05938 { 05939 struct ast_frame f = { 0, }; 05940 05941 f.frametype = type; 05942 f.subclass = command; 05943 f.datalen = datalen; 05944 f.src = __FUNCTION__; 05945 f.data = (void *) data; 05946 05947 return iax2_send(i, &f, ts, seqno, now, transfer, final); 05948 }
static void __send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1212 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_thread::callno, iax2_sched_add(), IAX_COMMAND_LAGRQ, sched, send_command(), and send_lagrq().
Referenced by send_lagrq().
01213 { 01214 int callno = (long) data; 01215 01216 ast_mutex_lock(&iaxsl[callno]); 01217 01218 if (iaxs[callno]) { 01219 if (iaxs[callno]->peercallno) { 01220 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); 01221 iaxs[callno]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, data); 01222 } else { 01223 /* I am the schedule, so I'm allowed to do this */ 01224 iaxs[callno]->lagid = -1; 01225 } 01226 } else { 01227 ast_debug(1, "I was supposed to send a LAGRQ with callno %d, but no such call exists.\n", callno); 01228 } 01229 01230 ast_mutex_unlock(&iaxsl[callno]); 01231 }
static void __send_ping | ( | const void * | data | ) | [static] |
Definition at line 1167 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax2_thread::callno, iax2_sched_add(), IAX_COMMAND_PING, sched, send_command(), and send_ping().
Referenced by send_ping().
01168 { 01169 int callno = (long) data; 01170 01171 ast_mutex_lock(&iaxsl[callno]); 01172 01173 if (iaxs[callno]) { 01174 if (iaxs[callno]->peercallno) { 01175 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); 01176 iaxs[callno]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, data); 01177 } else { 01178 /* I am the schedule, so I'm allowed to do this */ 01179 iaxs[callno]->pingid = -1; 01180 } 01181 } else { 01182 ast_debug(1, "I was supposed to send a PING with callno %d, but no such call exists.\n", callno); 01183 } 01184 01185 ast_mutex_unlock(&iaxsl[callno]); 01186 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 12264 of file chan_iax2.c.
References ao2_ref(), ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), ast_context_destroy(), ast_context_find(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_release(), AST_PTHREADT_NULL, ast_unregister_application(), ast_unregister_switch(), cli_iax2, delete_users(), iax2_destroy(), iax2_switch, iax2_tech, iax_peercallno_pvts, iax_provision_unload(), iax_transfercallno_pvts, iaxactivethreadcount, netsock, outsock, papp, reload_firmware(), sched, sched_context_destroy(), sched_lock, and thread.
12265 { 12266 struct iax2_thread *thread = NULL; 12267 struct ast_context *con; 12268 int x; 12269 12270 /* Make sure threads do not hold shared resources when they are canceled */ 12271 12272 /* Grab the sched lock resource to keep it away from threads about to die */ 12273 /* Cancel the network thread, close the net socket */ 12274 if (netthreadid != AST_PTHREADT_NULL) { 12275 AST_LIST_LOCK(&frame_queue); 12276 ast_mutex_lock(&sched_lock); 12277 pthread_cancel(netthreadid); 12278 ast_cond_signal(&sched_cond); 12279 ast_mutex_unlock(&sched_lock); /* Release the schedule lock resource */ 12280 AST_LIST_UNLOCK(&frame_queue); 12281 pthread_join(netthreadid, NULL); 12282 } 12283 if (schedthreadid != AST_PTHREADT_NULL) { 12284 ast_mutex_lock(&sched_lock); 12285 pthread_cancel(schedthreadid); 12286 ast_cond_signal(&sched_cond); 12287 ast_mutex_unlock(&sched_lock); 12288 pthread_join(schedthreadid, NULL); 12289 } 12290 12291 /* Call for all threads to halt */ 12292 AST_LIST_LOCK(&idle_list); 12293 while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list))) 12294 pthread_cancel(thread->threadid); 12295 AST_LIST_UNLOCK(&idle_list); 12296 12297 AST_LIST_LOCK(&active_list); 12298 while ((thread = AST_LIST_REMOVE_HEAD(&active_list, list))) 12299 pthread_cancel(thread->threadid); 12300 AST_LIST_UNLOCK(&active_list); 12301 12302 AST_LIST_LOCK(&dynamic_list); 12303 while ((thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list))) 12304 pthread_cancel(thread->threadid); 12305 AST_LIST_UNLOCK(&dynamic_list); 12306 12307 /* Wait for threads to exit */ 12308 while(0 < iaxactivethreadcount) 12309 usleep(10000); 12310 12311 ast_netsock_release(netsock); 12312 ast_netsock_release(outsock); 12313 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 12314 if (iaxs[x]) { 12315 iax2_destroy(x); 12316 } 12317 } 12318 ast_manager_unregister( "IAXpeers" ); 12319 ast_manager_unregister( "IAXpeerlist" ); 12320 ast_manager_unregister( "IAXnetstats" ); 12321 ast_unregister_application(papp); 12322 ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 12323 ast_unregister_switch(&iax2_switch); 12324 ast_channel_unregister(&iax2_tech); 12325 delete_users(); 12326 iax_provision_unload(); 12327 sched_context_destroy(sched); 12328 reload_firmware(1); 12329 12330 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 12331 ast_mutex_destroy(&iaxsl[x]); 12332 } 12333 12334 ao2_ref(peers, -1); 12335 ao2_ref(users, -1); 12336 ao2_ref(iax_peercallno_pvts, -1); 12337 ao2_ref(iax_transfercallno_pvts, -1); 12338 con = ast_context_find(regcontext); 12339 if (con) 12340 ast_context_destroy(con, "IAX2"); 12341 12342 return 0; 12343 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 12524 of file chan_iax2.c.
static int acf_channel_read | ( | struct ast_channel * | chan, | |
const char * | funcname, | |||
char * | preparse, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 12051 of file chan_iax2.c.
References ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), chan, iax2_tech, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
12052 { 12053 struct chan_iax2_pvt *pvt; 12054 unsigned int callno; 12055 int res = 0; 12056 12057 if (!chan || chan->tech != &iax2_tech) { 12058 ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); 12059 return -1; 12060 } 12061 12062 callno = PTR_TO_CALLNO(chan->tech_pvt); 12063 ast_mutex_lock(&iaxsl[callno]); 12064 if (!(pvt = iaxs[callno])) { 12065 ast_mutex_unlock(&iaxsl[callno]); 12066 return -1; 12067 } 12068 12069 if (!strcasecmp(args, "osptoken")) 12070 ast_copy_string(buf, pvt->osptoken, buflen); 12071 else 12072 res = -1; 12073 12074 ast_mutex_unlock(&iaxsl[callno]); 12075 12076 return res; 12077 }
static int acf_channel_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 12023 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_set, chan, iax2_tech, LOG_ERROR, chan_iax2_pvt::osptoken, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
12024 { 12025 struct chan_iax2_pvt *pvt; 12026 unsigned int callno; 12027 int res = 0; 12028 12029 if (!chan || chan->tech != &iax2_tech) { 12030 ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); 12031 return -1; 12032 } 12033 12034 callno = PTR_TO_CALLNO(chan->tech_pvt); 12035 ast_mutex_lock(&iaxsl[callno]); 12036 if (!(pvt = iaxs[callno])) { 12037 ast_mutex_unlock(&iaxsl[callno]); 12038 return -1; 12039 } 12040 12041 if (!strcasecmp(args, "osptoken")) 12042 ast_string_field_set(pvt, osptoken, value); 12043 else 12044 res = -1; 12045 12046 ast_mutex_unlock(&iaxsl[callno]); 12047 12048 return res; 12049 }
static int acf_iaxvar_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 8165 of file chan_iax2.c.
References ast_channel_datastore_find(), ast_copy_string(), AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, chan, ast_datastore::data, ast_var_t::entries, iax2_variable_datastore_info, and var.
08166 { 08167 struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL); 08168 AST_LIST_HEAD(, ast_var_t) *varlist; 08169 struct ast_var_t *var; 08170 08171 if (!variablestore) { 08172 *buf = '\0'; 08173 return 0; 08174 } 08175 varlist = variablestore->data; 08176 08177 AST_LIST_LOCK(varlist); 08178 AST_LIST_TRAVERSE(varlist, var, entries) { 08179 if (strcmp(var->name, data) == 0) { 08180 ast_copy_string(buf, var->value, len); 08181 break; 08182 } 08183 } 08184 AST_LIST_UNLOCK(varlist); 08185 return 0; 08186 }
static int acf_iaxvar_write | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 8188 of file chan_iax2.c.
References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_find(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_delete(), chan, ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_var_t::entries, iax2_variable_datastore_info, ast_datastore::inheritance, LOG_ERROR, and var.
08189 { 08190 struct ast_datastore *variablestore = ast_channel_datastore_find(chan, &iax2_variable_datastore_info, NULL); 08191 AST_LIST_HEAD(, ast_var_t) *varlist; 08192 struct ast_var_t *var; 08193 08194 if (!variablestore) { 08195 variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); 08196 if (!variablestore) { 08197 ast_log(LOG_ERROR, "Memory allocation error\n"); 08198 return -1; 08199 } 08200 varlist = ast_calloc(1, sizeof(*varlist)); 08201 if (!varlist) { 08202 ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data); 08203 return -1; 08204 } 08205 08206 AST_LIST_HEAD_INIT(varlist); 08207 variablestore->data = varlist; 08208 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 08209 ast_channel_datastore_add(chan, variablestore); 08210 } else 08211 varlist = variablestore->data; 08212 08213 AST_LIST_LOCK(varlist); 08214 AST_LIST_TRAVERSE_SAFE_BEGIN(varlist, var, entries) { 08215 if (strcmp(var->name, data) == 0) { 08216 AST_LIST_REMOVE_CURRENT(entries); 08217 ast_var_delete(var); 08218 break; 08219 } 08220 } 08221 AST_LIST_TRAVERSE_SAFE_END; 08222 var = ast_var_assign(data, value); 08223 if (var) 08224 AST_LIST_INSERT_TAIL(varlist, var, entries); 08225 else 08226 ast_log(LOG_ERROR, "Unable to assign new variable '%s'\n", data); 08227 AST_LIST_UNLOCK(varlist); 08228 return 0; 08229 }
static int apply_context | ( | struct iax2_context * | con, | |
const char * | context | |||
) | [static] |
Definition at line 5989 of file chan_iax2.c.
References iax2_context::context, and iax2_context::next.
Referenced by check_access().
05990 { 05991 while(con) { 05992 if (!strcmp(con->context, context) || !strcmp(con->context, "*")) 05993 return -1; 05994 con = con->next; 05995 } 05996 return 0; 05997 }
static int ast_cli_netstats | ( | struct mansession * | s, | |
int | fd, | |||
int | limit_fmt | |||
) | [static] |
Definition at line 5645 of file chan_iax2.c.
References ACN_FORMAT1, ACN_FORMAT2, ARRAY_LEN, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, iax_frame_subclass2str(), IAX_USEJITTERBUF, jb_getinfo(), jb_info::jitter, jb_info::losspct, MARK_IAX_SUBCLASS_TX, jb_info::min, and s.
Referenced by handle_cli_iax2_show_netstats(), and manager_iax2_show_netstats().
05646 { 05647 int x; 05648 int numchans = 0; 05649 char first_message[10] = { 0, }; 05650 char last_message[10] = { 0, }; 05651 #define ACN_FORMAT1 "%-20.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d %s%s %4s%s\n" 05652 #define ACN_FORMAT2 "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %s%s %s%s\n" 05653 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 05654 ast_mutex_lock(&iaxsl[x]); 05655 if (iaxs[x]) { 05656 int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; 05657 jb_info jbinfo; 05658 iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message)); 05659 iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message)); 05660 05661 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 05662 jb_getinfo(iaxs[x]->jb, &jbinfo); 05663 localjitter = jbinfo.jitter; 05664 localdelay = jbinfo.current - jbinfo.min; 05665 locallost = jbinfo.frames_lost; 05666 locallosspct = jbinfo.losspct/1000; 05667 localdropped = jbinfo.frames_dropped; 05668 localooo = jbinfo.frames_ooo; 05669 } else { 05670 localjitter = -1; 05671 localdelay = 0; 05672 locallost = -1; 05673 locallosspct = -1; 05674 localdropped = 0; 05675 localooo = -1; 05676 } 05677 if (s) 05678 astman_append(s, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2, 05679 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 05680 iaxs[x]->pingtime, 05681 localjitter, 05682 localdelay, 05683 locallost, 05684 locallosspct, 05685 localdropped, 05686 localooo, 05687 iaxs[x]->frames_received/1000, 05688 iaxs[x]->remote_rr.jitter, 05689 iaxs[x]->remote_rr.delay, 05690 iaxs[x]->remote_rr.losscnt, 05691 iaxs[x]->remote_rr.losspct, 05692 iaxs[x]->remote_rr.dropped, 05693 iaxs[x]->remote_rr.ooo, 05694 iaxs[x]->remote_rr.packets/1000, 05695 (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 05696 first_message, 05697 (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 05698 last_message); 05699 else 05700 ast_cli(fd, limit_fmt ? ACN_FORMAT1 : ACN_FORMAT2, 05701 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 05702 iaxs[x]->pingtime, 05703 localjitter, 05704 localdelay, 05705 locallost, 05706 locallosspct, 05707 localdropped, 05708 localooo, 05709 iaxs[x]->frames_received/1000, 05710 iaxs[x]->remote_rr.jitter, 05711 iaxs[x]->remote_rr.delay, 05712 iaxs[x]->remote_rr.losscnt, 05713 iaxs[x]->remote_rr.losspct, 05714 iaxs[x]->remote_rr.dropped, 05715 iaxs[x]->remote_rr.ooo, 05716 iaxs[x]->remote_rr.packets/1000, 05717 (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 05718 first_message, 05719 (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 05720 last_message); 05721 numchans++; 05722 } 05723 ast_mutex_unlock(&iaxsl[x]); 05724 } 05725 05726 return numchans; 05727 }
static struct ast_channel* ast_iax2_new | ( | int | callno, | |
int | state, | |||
int | capability | |||
) | [static] |
Create new call, interface with the PBX core.
Definition at line 4237 of file chan_iax2.c.
References chan_iax2_pvt::accountcode, chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, chan_iax2_pvt::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_free(), ast_channel_free(), ast_copy_string(), ast_debug, ast_free, ast_hangup(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, chan_iax2_pvt::callno, CALLNO_TO_PTR, chan_iax2_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, chan_iax2_pvt::cid_name, chan_iax2_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, chan_iax2_pvt::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, chan_iax2_pvt::dnid, ast_var_t::entries, ast_channel::exten, chan_iax2_pvt::exten, chan_iax2_pvt::host, iax2_ami_channelupdate(), iax2_tech, iax2_variable_datastore_info, chan_iax2_pvt::iaxvars, ast_datastore::inheritance, chan_iax2_pvt::language, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), chan_iax2_pvt::peeradsicpe, ast_channel::rawreadformat, ast_channel::rawwriteformat, chan_iax2_pvt::rdnis, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, var, chan_iax2_pvt::vars, and ast_channel::writeformat.
Referenced by iax2_request(), and socket_process().
04238 { 04239 struct ast_channel *tmp; 04240 struct chan_iax2_pvt *i; 04241 struct ast_variable *v = NULL; 04242 04243 if (!(i = iaxs[callno])) { 04244 ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); 04245 return NULL; 04246 } 04247 04248 /* Don't hold call lock */ 04249 ast_mutex_unlock(&iaxsl[callno]); 04250 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "IAX2/%s-%d", i->host, i->callno); 04251 ast_mutex_lock(&iaxsl[callno]); 04252 if (i != iaxs[callno]) { 04253 if (tmp) { 04254 /* unlock and relock iaxsl[callno] to preserve locking order */ 04255 ast_mutex_unlock(&iaxsl[callno]); 04256 ast_channel_free(tmp); 04257 ast_mutex_lock(&iaxsl[callno]); 04258 } 04259 return NULL; 04260 } 04261 iax2_ami_channelupdate(i); 04262 if (!tmp) 04263 return NULL; 04264 tmp->tech = &iax2_tech; 04265 /* We can support any format by default, until we get restricted */ 04266 tmp->nativeformats = capability; 04267 tmp->readformat = tmp->rawreadformat = ast_best_codec(capability); 04268 tmp->writeformat = tmp->rawwriteformat = ast_best_codec(capability); 04269 tmp->tech_pvt = CALLNO_TO_PTR(i->callno); 04270 04271 /* Don't use ast_set_callerid() here because it will 04272 * generate a NewCallerID event before the NewChannel event */ 04273 if (!ast_strlen_zero(i->ani)) 04274 tmp->cid.cid_ani = ast_strdup(i->ani); 04275 else 04276 tmp->cid.cid_ani = ast_strdup(i->cid_num); 04277 tmp->cid.cid_dnid = ast_strdup(i->dnid); 04278 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 04279 tmp->cid.cid_pres = i->calling_pres; 04280 tmp->cid.cid_ton = i->calling_ton; 04281 tmp->cid.cid_tns = i->calling_tns; 04282 if (!ast_strlen_zero(i->language)) 04283 ast_string_field_set(tmp, language, i->language); 04284 if (!ast_strlen_zero(i->accountcode)) 04285 ast_string_field_set(tmp, accountcode, i->accountcode); 04286 if (i->amaflags) 04287 tmp->amaflags = i->amaflags; 04288 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 04289 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 04290 if (i->adsi) 04291 tmp->adsicpe = i->peeradsicpe; 04292 else 04293 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 04294 i->owner = tmp; 04295 i->capability = capability; 04296 04297 /* Set inherited variables */ 04298 if (i->vars) { 04299 for (v = i->vars ; v ; v = v->next) 04300 pbx_builtin_setvar_helper(tmp, v->name, v->value); 04301 } 04302 if (i->iaxvars) { 04303 struct ast_datastore *variablestore; 04304 struct ast_variable *var, *prev = NULL; 04305 AST_LIST_HEAD(, ast_var_t) *varlist; 04306 ast_debug(1, "Loading up the channel with IAXVARs\n"); 04307 varlist = ast_calloc(1, sizeof(*varlist)); 04308 variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); 04309 if (variablestore && varlist) { 04310 variablestore->data = varlist; 04311 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 04312 AST_LIST_HEAD_INIT(varlist); 04313 for (var = i->iaxvars; var; var = var->next) { 04314 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 04315 if (prev) 04316 ast_free(prev); 04317 prev = var; 04318 if (!newvar) { 04319 /* Don't abort list traversal, as this would leave i->iaxvars in an inconsistent state. */ 04320 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 04321 } else { 04322 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 04323 } 04324 } 04325 if (prev) 04326 ast_free(prev); 04327 i->iaxvars = NULL; 04328 ast_channel_datastore_add(i->owner, variablestore); 04329 } else { 04330 if (variablestore) { 04331 ast_channel_datastore_free(variablestore); 04332 } 04333 if (varlist) { 04334 ast_free(varlist); 04335 } 04336 } 04337 } 04338 04339 if (state != AST_STATE_DOWN) { 04340 if (ast_pbx_start(tmp)) { 04341 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 04342 ast_hangup(tmp); 04343 i->owner = NULL; 04344 return NULL; 04345 } 04346 } 04347 04348 ast_module_ref(ast_module_info->self); 04349 return tmp; 04350 }
static int attempt_transmit | ( | const void * | data | ) | [static] |
Definition at line 2499 of file chan_iax2.c.
References __attempt_transmit(), and schedule_action.
Referenced by __attempt_transmit(), and network_thread().
02500 { 02501 #ifdef SCHED_MULTITHREADED 02502 if (schedule_action(__attempt_transmit, data)) 02503 #endif 02504 __attempt_transmit(data); 02505 return 0; 02506 }
static int auth_fail | ( | int | callno, | |
int | failcode | |||
) | [static] |
Definition at line 7404 of file chan_iax2.c.
References auth_reject(), iax2_sched_replace(), and sched.
Referenced by socket_process().
07405 { 07406 /* Schedule sending the authentication failure in one second, to prevent 07407 guessing */ 07408 if (iaxs[callno]) { 07409 iaxs[callno]->authfail = failcode; 07410 if (delayreject) { 07411 iaxs[callno]->authid = iax2_sched_replace(iaxs[callno]->authid, 07412 sched, 1000, auth_reject, (void *)(long)callno); 07413 } else 07414 auth_reject((void *)(long)callno); 07415 } 07416 return 0; 07417 }
static int auth_reject | ( | const void * | data | ) | [static] |
Definition at line 7390 of file chan_iax2.c.
References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), and schedule_action.
Referenced by auth_fail().
07391 { 07392 int callno = (int)(long)(data); 07393 ast_mutex_lock(&iaxsl[callno]); 07394 if (iaxs[callno]) 07395 iaxs[callno]->authid = -1; 07396 ast_mutex_unlock(&iaxsl[callno]); 07397 #ifdef SCHED_MULTITHREADED 07398 if (schedule_action(__auth_reject, data)) 07399 #endif 07400 __auth_reject(data); 07401 return 0; 07402 }
static int authenticate | ( | const char * | challenge, | |
const char * | secret, | |||
const char * | keyn, | |||
int | authmethods, | |||
struct iax_ie_data * | ied, | |||
struct sockaddr_in * | sin, | |||
struct chan_iax2_pvt * | pvt | |||
) | [static] |
Definition at line 6549 of file chan_iax2.c.
References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_encryption_keys(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, iax_ie_append_str(), IAX_IE_MD5_RESULT, IAX_IE_PASSWORD, IAX_IE_RSA_RESULT, LOG_NOTICE, md5(), MD5Final(), MD5Init(), and MD5Update().
06550 { 06551 int res = -1; 06552 int x; 06553 if (!ast_strlen_zero(keyn)) { 06554 if (!(authmethods & IAX_AUTH_RSA)) { 06555 if (ast_strlen_zero(secret)) 06556 ast_log(LOG_NOTICE, "Asked to authenticate to %s with an RSA key, but they don't allow RSA authentication\n", ast_inet_ntoa(sin->sin_addr)); 06557 } else if (ast_strlen_zero(challenge)) { 06558 ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr)); 06559 } else { 06560 char sig[256]; 06561 struct ast_key *key; 06562 key = ast_key_get(keyn, AST_KEY_PRIVATE); 06563 if (!key) { 06564 ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); 06565 } else { 06566 if (ast_sign(key, (char*)challenge, sig)) { 06567 ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); 06568 res = -1; 06569 } else { 06570 iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); 06571 res = 0; 06572 } 06573 } 06574 } 06575 } 06576 /* Fall back */ 06577 if (res && !ast_strlen_zero(secret)) { 06578 if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) { 06579 struct MD5Context md5; 06580 unsigned char digest[16]; 06581 char digres[128]; 06582 MD5Init(&md5); 06583 MD5Update(&md5, (unsigned char *)challenge, strlen(challenge)); 06584 MD5Update(&md5, (unsigned char *)secret, strlen(secret)); 06585 MD5Final(digest, &md5); 06586 /* If they support md5, authenticate with it. */ 06587 for (x=0;x<16;x++) 06588 sprintf(digres + (x << 1), "%2.2x", digest[x]); /* safe */ 06589 if (pvt) { 06590 build_encryption_keys(digest, pvt); 06591 } 06592 iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); 06593 res = 0; 06594 } else if (authmethods & IAX_AUTH_PLAINTEXT) { 06595 iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); 06596 res = 0; 06597 } else 06598 ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods); 06599 } 06600 return res; 06601 }
static int authenticate_reply | ( | struct chan_iax2_pvt * | p, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies, | |||
const char * | override, | |||
const char * | okey | |||
) | [static] |
Definition at line 6607 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_free(), AST_FRAME_IAX, ast_free, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), authenticate(), iax2_peer::authmethods, chan_iax2_pvt::callno, ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_var_t::entries, iax2_variable_datastore_info, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, ies, ast_datastore::inheritance, LOG_ERROR, iax2_peer::mask, merge_encryption(), iax2_peer::name, iax2_peer::outkey, peer_unref(), realtime_peer(), iax2_peer::secret, send_command(), iax2_peer::username, and var.
Referenced by socket_process().
06608 { 06609 struct iax2_peer *peer = NULL; 06610 /* Start pessimistic */ 06611 int res = -1; 06612 int authmethods = 0; 06613 struct iax_ie_data ied; 06614 uint16_t callno = p->callno; 06615 06616 memset(&ied, 0, sizeof(ied)); 06617 06618 if (ies->username) 06619 ast_string_field_set(p, username, ies->username); 06620 if (ies->challenge) 06621 ast_string_field_set(p, challenge, ies->challenge); 06622 if (ies->authmethods) 06623 authmethods = ies->authmethods; 06624 if (authmethods & IAX_AUTH_MD5) 06625 merge_encryption(p, ies->encmethods); 06626 else 06627 p->encmethods = 0; 06628 06629 /* Check for override RSA authentication first */ 06630 if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) { 06631 /* Normal password authentication */ 06632 res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, p); 06633 } else { 06634 struct ao2_iterator i = ao2_iterator_init(peers, 0); 06635 while ((peer = ao2_iterator_next(&i))) { 06636 if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 06637 /* No peer specified at our end, or this is the peer */ 06638 && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) 06639 /* No username specified in peer rule, or this is the right username */ 06640 && (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr))) 06641 /* No specified host, or this is our host */ 06642 ) { 06643 res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, p); 06644 if (!res) { 06645 peer_unref(peer); 06646 break; 06647 } 06648 } 06649 peer_unref(peer); 06650 } 06651 if (!peer) { 06652 /* We checked our list and didn't find one. It's unlikely, but possible, 06653 that we're trying to authenticate *to* a realtime peer */ 06654 const char *peer_name = ast_strdupa(p->peer); 06655 ast_mutex_unlock(&iaxsl[callno]); 06656 if ((peer = realtime_peer(peer_name, NULL))) { 06657 ast_mutex_lock(&iaxsl[callno]); 06658 if (!(p = iaxs[callno])) { 06659 peer_unref(peer); 06660 return -1; 06661 } 06662 res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, p); 06663 peer_unref(peer); 06664 } 06665 if (!peer) { 06666 ast_mutex_lock(&iaxsl[callno]); 06667 if (!(p = iaxs[callno])) 06668 return -1; 06669 } 06670 } 06671 } 06672 if (ies->encmethods) 06673 ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); 06674 if (!res) { 06675 struct ast_datastore *variablestore; 06676 struct ast_variable *var, *prev = NULL; 06677 AST_LIST_HEAD(, ast_var_t) *varlist; 06678 varlist = ast_calloc(1, sizeof(*varlist)); 06679 variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); 06680 if (variablestore && varlist && p->owner) { 06681 variablestore->data = varlist; 06682 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 06683 AST_LIST_HEAD_INIT(varlist); 06684 for (var = ies->vars; var; var = var->next) { 06685 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 06686 if (prev) 06687 ast_free(prev); 06688 prev = var; 06689 if (!newvar) { 06690 /* Don't abort list traversal, as this would leave ies->vars in an inconsistent state. */ 06691 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 06692 } else { 06693 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 06694 } 06695 } 06696 if (prev) 06697 ast_free(prev); 06698 ies->vars = NULL; 06699 ast_channel_datastore_add(p->owner, variablestore); 06700 } else { 06701 if (p->owner) 06702 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 06703 if (variablestore) 06704 ast_channel_datastore_free(variablestore); 06705 if (varlist) 06706 ast_free(varlist); 06707 } 06708 } 06709 06710 if (!res) 06711 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); 06712 return res; 06713 }
static int authenticate_request | ( | int | call_num | ) | [static] |
Definition at line 6260 of file chan_iax2.c.
References ao2_find(), AST_CAUSE_CALL_REJECTED, AST_FRAME_IAX, ast_random(), ast_set_flag, ast_string_field_set, ast_test_flag, chan_iax2_pvt::authmethods, chan_iax2_pvt::challenge, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, OBJ_POINTER, send_command(), send_command_final(), user, user_unref(), and chan_iax2_pvt::username.
Referenced by socket_process().
06261 { 06262 struct iax_ie_data ied; 06263 int res = -1, authreq_restrict = 0; 06264 char challenge[10]; 06265 struct chan_iax2_pvt *p = iaxs[call_num]; 06266 06267 memset(&ied, 0, sizeof(ied)); 06268 06269 /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */ 06270 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 06271 struct iax2_user *user, tmp_user = { 06272 .name = p->username, 06273 }; 06274 06275 user = ao2_find(users, &tmp_user, OBJ_POINTER); 06276 if (user) { 06277 if (user->curauthreq == user->maxauthreq) 06278 authreq_restrict = 1; 06279 else 06280 user->curauthreq++; 06281 user = user_unref(user); 06282 } 06283 } 06284 06285 /* If the AUTHREQ limit test failed, send back an error */ 06286 if (authreq_restrict) { 06287 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached"); 06288 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED); 06289 send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); 06290 return 0; 06291 } 06292 06293 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 06294 if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) { 06295 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 06296 ast_string_field_set(p, challenge, challenge); 06297 /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */ 06298 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge); 06299 } 06300 if (p->encmethods) 06301 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods); 06302 06303 iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username); 06304 06305 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1); 06306 06307 if (p->encmethods) 06308 ast_set_flag(p, IAX_ENCRYPTED); 06309 06310 return res; 06311 }
static int authenticate_verify | ( | struct chan_iax2_pvt * | p, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6313 of file chan_iax2.c.
References ao2_find(), ast_atomic_fetchadd_int(), ast_check_signature, ast_clear_flag, ast_copy_string(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, chan_iax2_pvt::authrej, chan_iax2_pvt::challenge, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, ies, chan_iax2_pvt::inkeys, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), OBJ_POINTER, chan_iax2_pvt::secret, secret, chan_iax2_pvt::state, strsep(), user, user_unref(), and chan_iax2_pvt::username.
Referenced by socket_process().
06314 { 06315 char requeststr[256]; 06316 char md5secret[256] = ""; 06317 char secret[256] = ""; 06318 char rsasecret[256] = ""; 06319 int res = -1; 06320 int x; 06321 struct iax2_user *user, tmp_user = { 06322 .name = p->username, 06323 }; 06324 06325 if (p->authrej) { 06326 return res; 06327 } 06328 user = ao2_find(users, &tmp_user, OBJ_POINTER); 06329 if (user) { 06330 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 06331 ast_atomic_fetchadd_int(&user->curauthreq, -1); 06332 ast_clear_flag(p, IAX_MAXAUTHREQ); 06333 } 06334 ast_string_field_set(p, host, user->name); 06335 user = user_unref(user); 06336 } 06337 06338 if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) 06339 return res; 06340 if (ies->password) 06341 ast_copy_string(secret, ies->password, sizeof(secret)); 06342 if (ies->md5_result) 06343 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 06344 if (ies->rsa_result) 06345 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 06346 if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) { 06347 struct ast_key *key; 06348 char *keyn; 06349 char tmpkey[256]; 06350 char *stringp=NULL; 06351 ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey)); 06352 stringp=tmpkey; 06353 keyn = strsep(&stringp, ":"); 06354 while(keyn) { 06355 key = ast_key_get(keyn, AST_KEY_PUBLIC); 06356 if (key && !ast_check_signature(key, p->challenge, rsasecret)) { 06357 res = 0; 06358 break; 06359 } else if (!key) 06360 ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); 06361 keyn = strsep(&stringp, ":"); 06362 } 06363 } else if (p->authmethods & IAX_AUTH_MD5) { 06364 struct MD5Context md5; 06365 unsigned char digest[16]; 06366 char *tmppw, *stringp; 06367 06368 tmppw = ast_strdupa(p->secret); 06369 stringp = tmppw; 06370 while((tmppw = strsep(&stringp, ";"))) { 06371 MD5Init(&md5); 06372 MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge)); 06373 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 06374 MD5Final(digest, &md5); 06375 /* If they support md5, authenticate with it. */ 06376 for (x=0;x<16;x++) 06377 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 06378 if (!strcasecmp(requeststr, md5secret)) { 06379 res = 0; 06380 break; 06381 } 06382 } 06383 } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { 06384 if (!strcmp(secret, p->secret)) 06385 res = 0; 06386 } 06387 return res; 06388 }
static int auto_congest | ( | const void * | data | ) | [static] |
Definition at line 3540 of file chan_iax2.c.
References __auto_congest(), and schedule_action.
Referenced by iax2_call(), and sip_call().
03541 { 03542 #ifdef SCHED_MULTITHREADED 03543 if (schedule_action(__auto_congest, data)) 03544 #endif 03545 __auto_congest(data); 03546 return 0; 03547 }
static int auto_hangup | ( | const void * | data | ) | [static] |
Definition at line 7434 of file chan_iax2.c.
References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), and schedule_action.
Referenced by iax2_dprequest(), and iax2_provision().
07435 { 07436 int callno = (int)(long)(data); 07437 ast_mutex_lock(&iaxsl[callno]); 07438 if (iaxs[callno]) { 07439 iaxs[callno]->autoid = -1; 07440 } 07441 ast_mutex_unlock(&iaxsl[callno]); 07442 #ifdef SCHED_MULTITHREADED 07443 if (schedule_action(__auto_hangup, data)) 07444 #endif 07445 __auto_hangup(data); 07446 return 0; 07447 }
static struct iax2_context* build_context | ( | const char * | context | ) | [static] |
Definition at line 10455 of file chan_iax2.c.
References ast_calloc, and ast_copy_string().
Referenced by build_user().
10456 { 10457 struct iax2_context *con; 10458 10459 if ((con = ast_calloc(1, sizeof(*con)))) 10460 ast_copy_string(con->context, context, sizeof(con->context)); 10461 10462 return con; 10463 }
static void build_ecx_key | ( | const unsigned char * | digest, | |
struct chan_iax2_pvt * | pvt | |||
) | [static] |
Definition at line 4692 of file chan_iax2.c.
References ast_aes_decrypt_key, ast_aes_encrypt_key, build_rand_pad(), chan_iax2_pvt::ecx, chan_iax2_pvt::mydcx, and chan_iax2_pvt::semirand.
Referenced by build_encryption_keys().
04693 { 04694 /* it is required to hold the corresponding decrypt key to our encrypt key 04695 * in the pvt struct because queued frames occasionally need to be decrypted and 04696 * re-encrypted when updated for a retransmission */ 04697 build_rand_pad(pvt->semirand, sizeof(pvt->semirand)); 04698 ast_aes_encrypt_key(digest, &pvt->ecx); 04699 ast_aes_decrypt_key(digest, &pvt->mydcx); 04700 }
static void build_encryption_keys | ( | const unsigned char * | digest, | |
struct chan_iax2_pvt * | pvt | |||
) | [static] |
Definition at line 4686 of file chan_iax2.c.
References ast_aes_decrypt_key, build_ecx_key(), and chan_iax2_pvt::dcx.
Referenced by authenticate(), and decrypt_frame().
04687 { 04688 build_ecx_key(digest, pvt); 04689 ast_aes_decrypt_key(digest, &pvt->dcx); 04690 }
static struct iax2_peer * build_peer | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static] |
Create peer structure based on configuration.
Definition at line 10603 of file chan_iax2.c.
References ao2_alloc(), ao2_find(), ast_append_ha(), ast_callerid_split(), ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free_ha(), ast_get_ip(), ast_log(), ast_parse_allow_disallow(), AST_SCHED_DEL, ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), cid_name, cid_num, iax2_peer::dbsecret, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, get_auth_methods(), get_encrypt_methods(), globalflags, iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, inet_aton(), iax2_peer::inkeys, ast_variable::lineno, LOG_WARNING, mailbox, mwi_event_cb(), ast_variable::name, iax2_peer::name, ast_variable::next, OBJ_POINTER, iax2_peer::outkey, peer_destructor(), peer_set_srcaddr(), peer_unref(), iax2_peer::peercontext, prefs, regexten, S_OR, sched, secret, strsep(), unlink_peer(), ast_variable::value, and zonetag.
10604 { 10605 struct iax2_peer *peer = NULL; 10606 struct ast_ha *oldha = NULL; 10607 int maskfound = 0; 10608 int found = 0; 10609 int firstpass = 1; 10610 struct iax2_peer tmp_peer = { 10611 .name = name, 10612 }; 10613 10614 if (!temponly) { 10615 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 10616 if (peer && !ast_test_flag(peer, IAX_DELME)) 10617 firstpass = 0; 10618 } 10619 10620 if (peer) { 10621 found++; 10622 if (firstpass) { 10623 oldha = peer->ha; 10624 peer->ha = NULL; 10625 } 10626 unlink_peer(peer); 10627 } else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) { 10628 peer->expire = -1; 10629 peer->pokeexpire = -1; 10630 peer->sockfd = defaultsockfd; 10631 if (ast_string_field_init(peer, 32)) 10632 peer = peer_unref(peer); 10633 } 10634 10635 if (peer) { 10636 if (firstpass) { 10637 ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 10638 peer->encmethods = iax2_encryption; 10639 peer->adsi = adsi; 10640 ast_string_field_set(peer,secret,""); 10641 if (!found) { 10642 ast_string_field_set(peer, name, name); 10643 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 10644 peer->expiry = min_reg_expire; 10645 } 10646 peer->prefs = prefs; 10647 peer->capability = iax2_capability; 10648 peer->smoothing = 0; 10649 peer->pokefreqok = DEFAULT_FREQ_OK; 10650 peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; 10651 ast_string_field_set(peer,context,""); 10652 ast_string_field_set(peer,peercontext,""); 10653 ast_clear_flag(peer, IAX_HASCALLERID); 10654 ast_string_field_set(peer, cid_name, ""); 10655 ast_string_field_set(peer, cid_num, ""); 10656 ast_string_field_set(peer, mohinterpret, mohinterpret); 10657 ast_string_field_set(peer, mohsuggest, mohsuggest); 10658 } 10659 10660 if (!v) { 10661 v = alt; 10662 alt = NULL; 10663 } 10664 while(v) { 10665 if (!strcasecmp(v->name, "secret")) { 10666 ast_string_field_set(peer, secret, v->value); 10667 } else if (!strcasecmp(v->name, "mailbox")) { 10668 ast_string_field_set(peer, mailbox, v->value); 10669 } else if (!strcasecmp(v->name, "hasvoicemail")) { 10670 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) { 10671 ast_string_field_set(peer, mailbox, name); 10672 } 10673 } else if (!strcasecmp(v->name, "mohinterpret")) { 10674 ast_string_field_set(peer, mohinterpret, v->value); 10675 } else if (!strcasecmp(v->name, "mohsuggest")) { 10676 ast_string_field_set(peer, mohsuggest, v->value); 10677 } else if (!strcasecmp(v->name, "dbsecret")) { 10678 ast_string_field_set(peer, dbsecret, v->value); 10679 } else if (!strcasecmp(v->name, "trunk")) { 10680 ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); 10681 if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) { 10682 ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without DAHDI timing\n", peer->name); 10683 ast_clear_flag(peer, IAX_TRUNK); 10684 } 10685 } else if (!strcasecmp(v->name, "auth")) { 10686 peer->authmethods = get_auth_methods(v->value); 10687 } else if (!strcasecmp(v->name, "encryption")) { 10688 peer->encmethods = get_encrypt_methods(v->value); 10689 } else if (!strcasecmp(v->name, "transfer")) { 10690 if (!strcasecmp(v->value, "mediaonly")) { 10691 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 10692 } else if (ast_true(v->value)) { 10693 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 10694 } else 10695 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 10696 } else if (!strcasecmp(v->name, "jitterbuffer")) { 10697 ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF); 10698 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 10699 ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF); 10700 } else if (!strcasecmp(v->name, "host")) { 10701 if (!strcasecmp(v->value, "dynamic")) { 10702 /* They'll register with us */ 10703 ast_set_flag(peer, IAX_DYNAMIC); 10704 if (!found) { 10705 /* Initialize stuff iff we're not found, otherwise 10706 we keep going with what we had */ 10707 memset(&peer->addr.sin_addr, 0, 4); 10708 if (peer->addr.sin_port) { 10709 /* If we've already got a port, make it the default rather than absolute */ 10710 peer->defaddr.sin_port = peer->addr.sin_port; 10711 peer->addr.sin_port = 0; 10712 } 10713 } 10714 } else { 10715 /* Non-dynamic. Make sure we become that way if we're not */ 10716 AST_SCHED_DEL(sched, peer->expire); 10717 ast_clear_flag(peer, IAX_DYNAMIC); 10718 if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) 10719 return peer_unref(peer); 10720 if (!peer->addr.sin_port) 10721 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 10722 } 10723 if (!maskfound) 10724 inet_aton("255.255.255.255", &peer->mask); 10725 } else if (!strcasecmp(v->name, "defaultip")) { 10726 if (ast_get_ip(&peer->defaddr, v->value)) 10727 return peer_unref(peer); 10728 } else if (!strcasecmp(v->name, "sourceaddress")) { 10729 peer_set_srcaddr(peer, v->value); 10730 } else if (!strcasecmp(v->name, "permit") || 10731 !strcasecmp(v->name, "deny")) { 10732 peer->ha = ast_append_ha(v->name, v->value, peer->ha, NULL); 10733 } else if (!strcasecmp(v->name, "mask")) { 10734 maskfound++; 10735 inet_aton(v->value, &peer->mask); 10736 } else if (!strcasecmp(v->name, "context")) { 10737 ast_string_field_set(peer, context, v->value); 10738 } else if (!strcasecmp(v->name, "regexten")) { 10739 ast_string_field_set(peer, regexten, v->value); 10740 } else if (!strcasecmp(v->name, "peercontext")) { 10741 ast_string_field_set(peer, peercontext, v->value); 10742 } else if (!strcasecmp(v->name, "port")) { 10743 if (ast_test_flag(peer, IAX_DYNAMIC)) 10744 peer->defaddr.sin_port = htons(atoi(v->value)); 10745 else 10746 peer->addr.sin_port = htons(atoi(v->value)); 10747 } else if (!strcasecmp(v->name, "username")) { 10748 ast_string_field_set(peer, username, v->value); 10749 } else if (!strcasecmp(v->name, "allow")) { 10750 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); 10751 } else if (!strcasecmp(v->name, "disallow")) { 10752 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); 10753 } else if (!strcasecmp(v->name, "callerid")) { 10754 if (!ast_strlen_zero(v->value)) { 10755 char name2[80]; 10756 char num2[80]; 10757 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 10758 ast_string_field_set(peer, cid_name, name2); 10759 ast_string_field_set(peer, cid_num, num2); 10760 } else { 10761 ast_string_field_set(peer, cid_name, ""); 10762 ast_string_field_set(peer, cid_num, ""); 10763 } 10764 ast_set_flag(peer, IAX_HASCALLERID); 10765 } else if (!strcasecmp(v->name, "fullname")) { 10766 ast_string_field_set(peer, cid_name, S_OR(v->value, "")); 10767 ast_set_flag(peer, IAX_HASCALLERID); 10768 } else if (!strcasecmp(v->name, "cid_number")) { 10769 ast_string_field_set(peer, cid_num, S_OR(v->value, "")); 10770 ast_set_flag(peer, IAX_HASCALLERID); 10771 } else if (!strcasecmp(v->name, "sendani")) { 10772 ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 10773 } else if (!strcasecmp(v->name, "inkeys")) { 10774 ast_string_field_set(peer, inkeys, v->value); 10775 } else if (!strcasecmp(v->name, "outkey")) { 10776 ast_string_field_set(peer, outkey, v->value); 10777 } else if (!strcasecmp(v->name, "qualify")) { 10778 if (!strcasecmp(v->value, "no")) { 10779 peer->maxms = 0; 10780 } else if (!strcasecmp(v->value, "yes")) { 10781 peer->maxms = DEFAULT_MAXMS; 10782 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 10783 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of iax.conf\n", peer->name, v->lineno); 10784 peer->maxms = 0; 10785 } 10786 } else if (!strcasecmp(v->name, "qualifysmoothing")) { 10787 peer->smoothing = ast_true(v->value); 10788 } else if (!strcasecmp(v->name, "qualifyfreqok")) { 10789 if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) { 10790 ast_log(LOG_WARNING, "Qualification testing frequency of peer '%s' when OK should a number of milliseconds at line %d of iax.conf\n", peer->name, v->lineno); 10791 } 10792 } else if (!strcasecmp(v->name, "qualifyfreqnotok")) { 10793 if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) { 10794 ast_log(LOG_WARNING, "Qualification testing frequency of peer '%s' when NOT OK should be a number of milliseconds at line %d of iax.conf\n", peer->name, v->lineno); 10795 } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok); 10796 } else if (!strcasecmp(v->name, "timezone")) { 10797 ast_string_field_set(peer, zonetag, v->value); 10798 } else if (!strcasecmp(v->name, "adsi")) { 10799 peer->adsi = ast_true(v->value); 10800 }/* else if (strcasecmp(v->name,"type")) */ 10801 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 10802 v = v->next; 10803 if (!v) { 10804 v = alt; 10805 alt = NULL; 10806 } 10807 } 10808 if (!peer->authmethods) 10809 peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 10810 ast_clear_flag(peer, IAX_DELME); 10811 /* Make sure these are IPv4 addresses */ 10812 peer->addr.sin_family = AF_INET; 10813 } 10814 10815 if (oldha) 10816 ast_free_ha(oldha); 10817 10818 if (!ast_strlen_zero(peer->mailbox)) { 10819 char *mailbox, *context; 10820 context = mailbox = ast_strdupa(peer->mailbox); 10821 strsep(&context, "@"); 10822 if (ast_strlen_zero(context)) 10823 context = "default"; 10824 peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 10825 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 10826 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 10827 AST_EVENT_IE_END); 10828 } 10829 10830 return peer; 10831 }
static void build_rand_pad | ( | unsigned char * | buf, | |
ssize_t | len | |||
) | [static] |
Definition at line 4676 of file chan_iax2.c.
References ast_random().
Referenced by build_ecx_key(), and update_packet().
04677 { 04678 long tmp; 04679 for (tmp = ast_random(); len > 0; tmp = ast_random()) { 04680 memcpy(buf, (unsigned char *) &tmp, (len > sizeof(tmp)) ? sizeof(tmp) : len); 04681 buf += sizeof(tmp); 04682 len -= sizeof(tmp); 04683 } 04684 }
static struct iax2_user * build_user | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static] |
Create in-memory user structure from configuration.
Definition at line 10847 of file chan_iax2.c.
References ao2_alloc(), ao2_find(), ao2_unlink(), ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_clear_flag, ast_copy_flags, ast_free_ha(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_strdupa, ast_string_field_build, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_new(), build_context(), cid_name, cid_num, cleanup(), iax2_user::dbsecret, format, free_context(), get_auth_methods(), get_encrypt_methods(), globalflags, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_user::inkeys, ast_variable::lineno, LOG_WARNING, ast_variable::name, iax2_user::name, ast_variable::next, OBJ_POINTER, prefs, secret, user, user_destructor(), user_unref(), and ast_variable::value.
10848 { 10849 struct iax2_user *user = NULL; 10850 struct iax2_context *con, *conl = NULL; 10851 struct ast_ha *oldha = NULL; 10852 struct iax2_context *oldcon = NULL; 10853 int format; 10854 int firstpass=1; 10855 int oldcurauthreq = 0; 10856 char *varname = NULL, *varval = NULL; 10857 struct ast_variable *tmpvar = NULL; 10858 struct iax2_user tmp_user = { 10859 .name = name, 10860 }; 10861 10862 if (!temponly) { 10863 user = ao2_find(users, &tmp_user, OBJ_POINTER); 10864 if (user && !ast_test_flag(user, IAX_DELME)) 10865 firstpass = 0; 10866 } 10867 10868 if (user) { 10869 if (firstpass) { 10870 oldcurauthreq = user->curauthreq; 10871 oldha = user->ha; 10872 oldcon = user->contexts; 10873 user->ha = NULL; 10874 user->contexts = NULL; 10875 } 10876 /* Already in the list, remove it and it will be added back (or FREE'd) */ 10877 ao2_unlink(users, user); 10878 } else { 10879 user = ao2_alloc(sizeof(*user), user_destructor); 10880 } 10881 10882 if (user) { 10883 if (firstpass) { 10884 ast_string_field_free_memory(user); 10885 memset(user, 0, sizeof(struct iax2_user)); 10886 if (ast_string_field_init(user, 32)) { 10887 user = user_unref(user); 10888 goto cleanup; 10889 } 10890 user->maxauthreq = maxauthreq; 10891 user->curauthreq = oldcurauthreq; 10892 user->prefs = prefs; 10893 user->capability = iax2_capability; 10894 user->encmethods = iax2_encryption; 10895 user->adsi = adsi; 10896 ast_string_field_set(user, name, name); 10897 ast_string_field_set(user, language, language); 10898 ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); 10899 ast_clear_flag(user, IAX_HASCALLERID); 10900 ast_string_field_set(user, cid_name, ""); 10901 ast_string_field_set(user, cid_num, ""); 10902 ast_string_field_set(user, accountcode, accountcode); 10903 ast_string_field_set(user, mohinterpret, mohinterpret); 10904 ast_string_field_set(user, mohsuggest, mohsuggest); 10905 } 10906 if (!v) { 10907 v = alt; 10908 alt = NULL; 10909 } 10910 while(v) { 10911 if (!strcasecmp(v->name, "context")) { 10912 con = build_context(v->value); 10913 if (con) { 10914 if (conl) 10915 conl->next = con; 10916 else 10917 user->contexts = con; 10918 conl = con; 10919 } 10920 } else if (!strcasecmp(v->name, "permit") || 10921 !strcasecmp(v->name, "deny")) { 10922 user->ha = ast_append_ha(v->name, v->value, user->ha, NULL); 10923 } else if (!strcasecmp(v->name, "setvar")) { 10924 varname = ast_strdupa(v->value); 10925 if (varname && (varval = strchr(varname,'='))) { 10926 *varval = '\0'; 10927 varval++; 10928 if((tmpvar = ast_variable_new(varname, varval, ""))) { 10929 tmpvar->next = user->vars; 10930 user->vars = tmpvar; 10931 } 10932 } 10933 } else if (!strcasecmp(v->name, "allow")) { 10934 ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); 10935 } else if (!strcasecmp(v->name, "disallow")) { 10936 ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); 10937 } else if (!strcasecmp(v->name, "trunk")) { 10938 ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); 10939 if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) { 10940 ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without DAHDI timing\n", user->name); 10941 ast_clear_flag(user, IAX_TRUNK); 10942 } 10943 } else if (!strcasecmp(v->name, "auth")) { 10944 user->authmethods = get_auth_methods(v->value); 10945 } else if (!strcasecmp(v->name, "encryption")) { 10946 user->encmethods = get_encrypt_methods(v->value); 10947 } else if (!strcasecmp(v->name, "transfer")) { 10948 if (!strcasecmp(v->value, "mediaonly")) { 10949 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 10950 } else if (ast_true(v->value)) { 10951 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 10952 } else 10953 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 10954 } else if (!strcasecmp(v->name, "codecpriority")) { 10955 if(!strcasecmp(v->value, "caller")) 10956 ast_set_flag(user, IAX_CODEC_USER_FIRST); 10957 else if(!strcasecmp(v->value, "disabled")) 10958 ast_set_flag(user, IAX_CODEC_NOPREFS); 10959 else if(!strcasecmp(v->value, "reqonly")) { 10960 ast_set_flag(user, IAX_CODEC_NOCAP); 10961 ast_set_flag(user, IAX_CODEC_NOPREFS); 10962 } 10963 } else if (!strcasecmp(v->name, "jitterbuffer")) { 10964 ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF); 10965 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 10966 ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF); 10967 } else if (!strcasecmp(v->name, "dbsecret")) { 10968 ast_string_field_set(user, dbsecret, v->value); 10969 } else if (!strcasecmp(v->name, "secret")) { 10970 if (!ast_strlen_zero(user->secret)) { 10971 char *old = ast_strdupa(user->secret); 10972 10973 ast_string_field_build(user, secret, "%s;%s", old, v->value); 10974 } else 10975 ast_string_field_set(user, secret, v->value); 10976 } else if (!strcasecmp(v->name, "callerid")) { 10977 if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) { 10978 char name2[80]; 10979 char num2[80]; 10980 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 10981 ast_string_field_set(user, cid_name, name2); 10982 ast_string_field_set(user, cid_num, num2); 10983 ast_set_flag(user, IAX_HASCALLERID); 10984 } else { 10985 ast_clear_flag(user, IAX_HASCALLERID); 10986 ast_string_field_set(user, cid_name, ""); 10987 ast_string_field_set(user, cid_num, ""); 10988 } 10989 } else if (!strcasecmp(v->name, "fullname")) { 10990 if (!ast_strlen_zero(v->value)) { 10991 ast_string_field_set(user, cid_name, v->value); 10992 ast_set_flag(user, IAX_HASCALLERID); 10993 } else { 10994 ast_string_field_set(user, cid_name, ""); 10995 if (ast_strlen_zero(user->cid_num)) 10996 ast_clear_flag(user, IAX_HASCALLERID); 10997 } 10998 } else if (!strcasecmp(v->name, "cid_number")) { 10999 if (!ast_strlen_zero(v->value)) { 11000 ast_string_field_set(user, cid_num, v->value); 11001 ast_set_flag(user, IAX_HASCALLERID); 11002 } else { 11003 ast_string_field_set(user, cid_num, ""); 11004 if (ast_strlen_zero(user->cid_name)) 11005 ast_clear_flag(user, IAX_HASCALLERID); 11006 } 11007 } else if (!strcasecmp(v->name, "accountcode")) { 11008 ast_string_field_set(user, accountcode, v->value); 11009 } else if (!strcasecmp(v->name, "mohinterpret")) { 11010 ast_string_field_set(user, mohinterpret, v->value); 11011 } else if (!strcasecmp(v->name, "mohsuggest")) { 11012 ast_string_field_set(user, mohsuggest, v->value); 11013 } else if (!strcasecmp(v->name, "language")) { 11014 ast_string_field_set(user, language, v->value); 11015 } else if (!strcasecmp(v->name, "amaflags")) { 11016 format = ast_cdr_amaflags2int(v->value); 11017 if (format < 0) { 11018 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 11019 } else { 11020 user->amaflags = format; 11021 } 11022 } else if (!strcasecmp(v->name, "inkeys")) { 11023 ast_string_field_set(user, inkeys, v->value); 11024 } else if (!strcasecmp(v->name, "maxauthreq")) { 11025 user->maxauthreq = atoi(v->value); 11026 if (user->maxauthreq < 0) 11027 user->maxauthreq = 0; 11028 } else if (!strcasecmp(v->name, "adsi")) { 11029 user->adsi = ast_true(v->value); 11030 }/* else if (strcasecmp(v->name,"type")) */ 11031 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 11032 v = v->next; 11033 if (!v) { 11034 v = alt; 11035 alt = NULL; 11036 } 11037 } 11038 if (!user->authmethods) { 11039 if (!ast_strlen_zero(user->secret)) { 11040 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 11041 if (!ast_strlen_zero(user->inkeys)) 11042 user->authmethods |= IAX_AUTH_RSA; 11043 } else if (!ast_strlen_zero(user->inkeys)) { 11044 user->authmethods = IAX_AUTH_RSA; 11045 } else { 11046 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 11047 } 11048 } 11049 ast_clear_flag(user, IAX_DELME); 11050 } 11051 cleanup: 11052 if (oldha) 11053 ast_free_ha(oldha); 11054 if (oldcon) 11055 free_context(oldcon); 11056 return user; 11057 }
static int cache_get_callno_locked | ( | const char * | data | ) | [static] |
Definition at line 11616 of file chan_iax2.c.
References ARRAY_LEN, ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), create_addr(), find_callno_locked(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_COMMAND_NEW, iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CAPABILITY, IAX_IE_FORMAT, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, LOG_WARNING, NEW_FORCE, parse_dial_string(), secret, and send_command().
Referenced by find_cache().
11617 { 11618 struct sockaddr_in sin; 11619 int x; 11620 int callno; 11621 struct iax_ie_data ied; 11622 struct create_addr_info cai; 11623 struct parsed_dial_string pds; 11624 char *tmpstr; 11625 11626 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 11627 /* Look for an *exact match* call. Once a call is negotiated, it can only 11628 look up entries for a single context */ 11629 if (!ast_mutex_trylock(&iaxsl[x])) { 11630 if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) 11631 return x; 11632 ast_mutex_unlock(&iaxsl[x]); 11633 } 11634 } 11635 11636 /* No match found, we need to create a new one */ 11637 11638 memset(&cai, 0, sizeof(cai)); 11639 memset(&ied, 0, sizeof(ied)); 11640 memset(&pds, 0, sizeof(pds)); 11641 11642 tmpstr = ast_strdupa(data); 11643 parse_dial_string(tmpstr, &pds); 11644 11645 if (ast_strlen_zero(pds.peer)) { 11646 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data); 11647 return -1; 11648 } 11649 11650 /* Populate our address from the given */ 11651 if (create_addr(pds.peer, NULL, &sin, &cai)) 11652 return -1; 11653 11654 ast_debug(1, "peer: %s, username: %s, password: %s, context: %s\n", 11655 pds.peer, pds.username, pds.password, pds.context); 11656 11657 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 11658 if (callno < 1) { 11659 ast_log(LOG_WARNING, "Unable to create call\n"); 11660 return -1; 11661 } 11662 11663 ast_string_field_set(iaxs[callno], dproot, data); 11664 iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; 11665 11666 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 11667 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); 11668 /* the string format is slightly different from a standard dial string, 11669 because the context appears in the 'exten' position 11670 */ 11671 if (pds.exten) 11672 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); 11673 if (pds.username) 11674 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 11675 iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); 11676 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); 11677 /* Keep password handy */ 11678 if (pds.password) 11679 ast_string_field_set(iaxs[callno], secret, pds.password); 11680 if (pds.key) 11681 ast_string_field_set(iaxs[callno], outkey, pds.key); 11682 /* Start the call going */ 11683 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 11684 11685 return callno; 11686 }
static unsigned int calc_rxstamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | offset | |||
) | [static] |
Definition at line 4528 of file chan_iax2.c.
References ast_debug, ast_random(), ast_samp2tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), chan_iax2_pvt::callno, and chan_iax2_pvt::rxcore.
04529 { 04530 /* Returns where in "receive time" we are. That is, how many ms 04531 since we received (or would have received) the frame with timestamp 0 */ 04532 int ms; 04533 #ifdef IAXTESTS 04534 int jit; 04535 #endif /* IAXTESTS */ 04536 /* Setup rxcore if necessary */ 04537 if (ast_tvzero(p->rxcore)) { 04538 p->rxcore = ast_tvnow(); 04539 if (iaxdebug) 04540 ast_debug(1, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n", 04541 p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset); 04542 p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000)); 04543 #if 1 04544 if (iaxdebug) 04545 ast_debug(1, "calc_rxstamp: call=%d: works out as %d.%6.6d\n", 04546 p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec)); 04547 #endif 04548 } 04549 04550 ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore); 04551 #ifdef IAXTESTS 04552 if (test_jit) { 04553 if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) { 04554 jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0)); 04555 if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0))) 04556 jit = -jit; 04557 ms += jit; 04558 } 04559 } 04560 if (test_late) { 04561 ms += test_late; 04562 test_late = 0; 04563 } 04564 #endif /* IAXTESTS */ 04565 return ms; 04566 }
static unsigned int calc_timestamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | ts, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 4396 of file chan_iax2.c.
References ast_debug, AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_samp2tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), chan_iax2_pvt::callno, f, chan_iax2_pvt::lastsent, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, and chan_iax2_pvt::offset.
Referenced by iax2_send(), and socket_process().
04397 { 04398 int ms; 04399 int voice = 0; 04400 int genuine = 0; 04401 int adjust; 04402 struct timeval *delivery = NULL; 04403 04404 04405 /* What sort of frame do we have?: voice is self-explanatory 04406 "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK 04407 non-genuine frames are CONTROL frames [ringing etc], DTMF 04408 The "genuine" distinction is needed because genuine frames must get a clock-based timestamp, 04409 the others need a timestamp slaved to the voice frames so that they go in sequence 04410 */ 04411 if (f) { 04412 if (f->frametype == AST_FRAME_VOICE) { 04413 voice = 1; 04414 delivery = &f->delivery; 04415 } else if (f->frametype == AST_FRAME_IAX) { 04416 genuine = 1; 04417 } else if (f->frametype == AST_FRAME_CNG) { 04418 p->notsilenttx = 0; 04419 } 04420 } 04421 if (ast_tvzero(p->offset)) { 04422 p->offset = ast_tvnow(); 04423 /* Round to nearest 20ms for nice looking traces */ 04424 p->offset.tv_usec -= p->offset.tv_usec % 20000; 04425 } 04426 /* If the timestamp is specified, just send it as is */ 04427 if (ts) 04428 return ts; 04429 /* If we have a time that the frame arrived, always use it to make our timestamp */ 04430 if (delivery && !ast_tvzero(*delivery)) { 04431 ms = ast_tvdiff_ms(*delivery, p->offset); 04432 if (ms < 0) { 04433 ms = 0; 04434 } 04435 if (iaxdebug) 04436 ast_debug(3, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno); 04437 } else { 04438 ms = ast_tvdiff_ms(ast_tvnow(), p->offset); 04439 if (ms < 0) 04440 ms = 0; 04441 if (voice) { 04442 /* On a voice frame, use predicted values if appropriate */ 04443 if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) { 04444 /* Adjust our txcore, keeping voice and non-voice synchronized */ 04445 /* AN EXPLANATION: 04446 When we send voice, we usually send "calculated" timestamps worked out 04447 on the basis of the number of samples sent. When we send other frames, 04448 we usually send timestamps worked out from the real clock. 04449 The problem is that they can tend to drift out of step because the 04450 source channel's clock and our clock may not be exactly at the same rate. 04451 We fix this by continuously "tweaking" p->offset. p->offset is "time zero" 04452 for this call. Moving it adjusts timestamps for non-voice frames. 04453 We make the adjustment in the style of a moving average. Each time we 04454 adjust p->offset by 10% of the difference between our clock-derived 04455 timestamp and the predicted timestamp. That's why you see "10000" 04456 below even though IAX2 timestamps are in milliseconds. 04457 The use of a moving average avoids offset moving too radically. 04458 Generally, "adjust" roams back and forth around 0, with offset hardly 04459 changing at all. But if a consistent different starts to develop it 04460 will be eliminated over the course of 10 frames (200-300msecs) 04461 */ 04462 adjust = (ms - p->nextpred); 04463 if (adjust < 0) 04464 p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000)); 04465 else if (adjust > 0) 04466 p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000)); 04467 04468 if (!p->nextpred) { 04469 p->nextpred = ms; /*f->samples / 8;*/ 04470 if (p->nextpred <= p->lastsent) 04471 p->nextpred = p->lastsent + 3; 04472 } 04473 ms = p->nextpred; 04474 } else { 04475 /* in this case, just use the actual 04476 * time, since we're either way off 04477 * (shouldn't happen), or we're ending a 04478 * silent period -- and seed the next 04479 * predicted time. Also, round ms to the 04480 * next multiple of frame size (so our 04481 * silent periods are multiples of 04482 * frame size too) */ 04483 04484 if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW ) 04485 ast_debug(1, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n", 04486 abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW); 04487 04488 if (f->samples >= 8) /* check to make sure we dont core dump */ 04489 { 04490 int diff = ms % (f->samples / 8); 04491 if (diff) 04492 ms += f->samples/8 - diff; 04493 } 04494 04495 p->nextpred = ms; 04496 p->notsilenttx = 1; 04497 } 04498 } else if ( f->frametype == AST_FRAME_VIDEO ) { 04499 /* 04500 * IAX2 draft 03 says that timestamps MUST be in order. 04501 * It does not say anything about several frames having the same timestamp 04502 * When transporting video, we can have a frame that spans multiple iax packets 04503 * (so called slices), so it would make sense to use the same timestamp for all of 04504 * them 04505 * We do want to make sure that frames don't go backwards though 04506 */ 04507 if ( (unsigned int)ms < p->lastsent ) 04508 ms = p->lastsent; 04509 } else { 04510 /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless 04511 it's a genuine frame */ 04512 if (genuine) { 04513 /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */ 04514 if (ms <= p->lastsent) 04515 ms = p->lastsent + 3; 04516 } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) { 04517 /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */ 04518 ms = p->lastsent + 3; 04519 } 04520 } 04521 } 04522 p->lastsent = ms; 04523 if (voice) 04524 p->nextpred = p->nextpred + f->samples / 8; 04525 return ms; 04526 }
static unsigned int calc_txpeerstamp | ( | struct iax2_trunk_peer * | tpeer, | |
int | sampms, | |||
struct timeval * | tv | |||
) | [static] |
Definition at line 4352 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvzero(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lasttxtime, MAX_TIMESTAMP_SKEW, iax2_trunk_peer::trunkact, and iax2_trunk_peer::txtrunktime.
Referenced by send_trunk().
04353 { 04354 unsigned long int mssincetx; /* unsigned to handle overflows */ 04355 long int ms, pred; 04356 04357 tpeer->trunkact = *tv; 04358 mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime); 04359 if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) { 04360 /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */ 04361 tpeer->txtrunktime = *tv; 04362 tpeer->lastsent = 999999; 04363 } 04364 /* Update last transmit time now */ 04365 tpeer->lasttxtime = *tv; 04366 04367 /* Calculate ms offset */ 04368 ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime); 04369 /* Predict from last value */ 04370 pred = tpeer->lastsent + sampms; 04371 if (abs(ms - pred) < MAX_TIMESTAMP_SKEW) 04372 ms = pred; 04373 04374 /* We never send the same timestamp twice, so fudge a little if we must */ 04375 if (ms == tpeer->lastsent) 04376 ms = tpeer->lastsent + 1; 04377 tpeer->lastsent = ms; 04378 return ms; 04379 }
static int check_access | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6000 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), cid_name, cid_num, exten, ast_variable::file, iax2_getpeertrunk(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ies, LOG_WARNING, ast_variable::name, ast_variable::next, prefs, realtime_user(), secret, user, user_unref(), ast_variable::value, and version.
Referenced by socket_process().
06001 { 06002 /* Start pessimistic */ 06003 int res = -1; 06004 int version = 2; 06005 struct iax2_user *user = NULL, *best = NULL; 06006 int bestscore = 0; 06007 int gotcapability = 0; 06008 struct ast_variable *v = NULL, *tmpvar = NULL; 06009 struct ao2_iterator i; 06010 06011 if (!iaxs[callno]) 06012 return res; 06013 if (ies->called_number) 06014 ast_string_field_set(iaxs[callno], exten, ies->called_number); 06015 if (ies->calling_number) { 06016 ast_shrink_phone_number(ies->calling_number); 06017 ast_string_field_set(iaxs[callno], cid_num, ies->calling_number); 06018 } 06019 if (ies->calling_name) 06020 ast_string_field_set(iaxs[callno], cid_name, ies->calling_name); 06021 if (ies->calling_ani) 06022 ast_string_field_set(iaxs[callno], ani, ies->calling_ani); 06023 if (ies->dnid) 06024 ast_string_field_set(iaxs[callno], dnid, ies->dnid); 06025 if (ies->rdnis) 06026 ast_string_field_set(iaxs[callno], rdnis, ies->rdnis); 06027 if (ies->called_context) 06028 ast_string_field_set(iaxs[callno], context, ies->called_context); 06029 if (ies->language) 06030 ast_string_field_set(iaxs[callno], language, ies->language); 06031 if (ies->username) 06032 ast_string_field_set(iaxs[callno], username, ies->username); 06033 if (ies->calling_ton > -1) 06034 iaxs[callno]->calling_ton = ies->calling_ton; 06035 if (ies->calling_tns > -1) 06036 iaxs[callno]->calling_tns = ies->calling_tns; 06037 if (ies->calling_pres > -1) 06038 iaxs[callno]->calling_pres = ies->calling_pres; 06039 if (ies->format) 06040 iaxs[callno]->peerformat = ies->format; 06041 if (ies->adsicpe) 06042 iaxs[callno]->peeradsicpe = ies->adsicpe; 06043 if (ies->capability) { 06044 gotcapability = 1; 06045 iaxs[callno]->peercapability = ies->capability; 06046 } 06047 if (ies->version) 06048 version = ies->version; 06049 06050 /* Use provided preferences until told otherwise for actual preferences */ 06051 if(ies->codec_prefs) { 06052 ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); 06053 ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); 06054 } 06055 06056 if (!gotcapability) 06057 iaxs[callno]->peercapability = iaxs[callno]->peerformat; 06058 if (version > IAX_PROTO_VERSION) { 06059 ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 06060 ast_inet_ntoa(sin->sin_addr), version); 06061 return res; 06062 } 06063 /* Search the userlist for a compatible entry, and fill in the rest */ 06064 i = ao2_iterator_init(users, 0); 06065 while ((user = ao2_iterator_next(&i))) { 06066 if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ 06067 !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ 06068 && ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */ 06069 && (ast_strlen_zero(iaxs[callno]->context) || /* No context specified */ 06070 apply_context(user->contexts, iaxs[callno]->context))) { /* Context is permitted */ 06071 if (!ast_strlen_zero(iaxs[callno]->username)) { 06072 /* Exact match, stop right now. */ 06073 if (best) 06074 user_unref(best); 06075 best = user; 06076 break; 06077 } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->dbsecret) && ast_strlen_zero(user->inkeys)) { 06078 /* No required authentication */ 06079 if (user->ha) { 06080 /* There was host authentication and we passed, bonus! */ 06081 if (bestscore < 4) { 06082 bestscore = 4; 06083 if (best) 06084 user_unref(best); 06085 best = user; 06086 continue; 06087 } 06088 } else { 06089 /* No host access, but no secret, either, not bad */ 06090 if (bestscore < 3) { 06091 bestscore = 3; 06092 if (best) 06093 user_unref(best); 06094 best = user; 06095 continue; 06096 } 06097 } 06098 } else { 06099 if (user->ha) { 06100 /* Authentication, but host access too, eh, it's something.. */ 06101 if (bestscore < 2) { 06102 bestscore = 2; 06103 if (best) 06104 user_unref(best); 06105 best = user; 06106 continue; 06107 } 06108 } else { 06109 /* Authentication and no host access... This is our baseline */ 06110 if (bestscore < 1) { 06111 bestscore = 1; 06112 if (best) 06113 user_unref(best); 06114 best = user; 06115 continue; 06116 } 06117 } 06118 } 06119 } 06120 user_unref(user); 06121 } 06122 user = best; 06123 if (!user && !ast_strlen_zero(iaxs[callno]->username)) { 06124 user = realtime_user(iaxs[callno]->username, sin); 06125 if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ 06126 !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ 06127 user = user_unref(user); 06128 } 06129 } 06130 if (user) { 06131 /* We found our match (use the first) */ 06132 /* copy vars */ 06133 for (v = user->vars ; v ; v = v->next) { 06134 if((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 06135 tmpvar->next = iaxs[callno]->vars; 06136 iaxs[callno]->vars = tmpvar; 06137 } 06138 } 06139 /* If a max AUTHREQ restriction is in place, activate it */ 06140 if (user->maxauthreq > 0) 06141 ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ); 06142 iaxs[callno]->prefs = user->prefs; 06143 ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST); 06144 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS); 06145 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP); 06146 iaxs[callno]->encmethods = user->encmethods; 06147 /* Store the requested username if not specified */ 06148 if (ast_strlen_zero(iaxs[callno]->username)) 06149 ast_string_field_set(iaxs[callno], username, user->name); 06150 /* Store whether this is a trunked call, too, of course, and move if appropriate */ 06151 ast_copy_flags(iaxs[callno], user, IAX_TRUNK); 06152 iaxs[callno]->capability = user->capability; 06153 /* And use the default context */ 06154 if (ast_strlen_zero(iaxs[callno]->context)) { 06155 if (user->contexts) 06156 ast_string_field_set(iaxs[callno], context, user->contexts->context); 06157 else 06158 ast_string_field_set(iaxs[callno], context, context); 06159 } 06160 /* And any input keys */ 06161 ast_string_field_set(iaxs[callno], inkeys, user->inkeys); 06162 /* And the permitted authentication methods */ 06163 iaxs[callno]->authmethods = user->authmethods; 06164 iaxs[callno]->adsi = user->adsi; 06165 /* If the user has callerid, override the remote caller id. */ 06166 if (ast_test_flag(user, IAX_HASCALLERID)) { 06167 iaxs[callno]->calling_tns = 0; 06168 iaxs[callno]->calling_ton = 0; 06169 ast_string_field_set(iaxs[callno], cid_num, user->cid_num); 06170 ast_string_field_set(iaxs[callno], cid_name, user->cid_name); 06171 ast_string_field_set(iaxs[callno], ani, user->cid_num); 06172 iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 06173 } else if (ast_strlen_zero(iaxs[callno]->cid_num) && ast_strlen_zero(iaxs[callno]->cid_name)) { 06174 iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE; 06175 } /* else user is allowed to set their own CID settings */ 06176 if (!ast_strlen_zero(user->accountcode)) 06177 ast_string_field_set(iaxs[callno], accountcode, user->accountcode); 06178 if (!ast_strlen_zero(user->mohinterpret)) 06179 ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret); 06180 if (!ast_strlen_zero(user->mohsuggest)) 06181 ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest); 06182 if (user->amaflags) 06183 iaxs[callno]->amaflags = user->amaflags; 06184 if (!ast_strlen_zero(user->language)) 06185 ast_string_field_set(iaxs[callno], language, user->language); 06186 ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 06187 /* Keep this check last */ 06188 if (!ast_strlen_zero(user->dbsecret)) { 06189 char *family, *key=NULL; 06190 char buf[80]; 06191 family = ast_strdupa(user->dbsecret); 06192 key = strchr(family, '/'); 06193 if (key) { 06194 *key = '\0'; 06195 key++; 06196 } 06197 if (!key || ast_db_get(family, key, buf, sizeof(buf))) 06198 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); 06199 else 06200 ast_string_field_set(iaxs[callno], secret, buf); 06201 } else 06202 ast_string_field_set(iaxs[callno], secret, user->secret); 06203 res = 0; 06204 user = user_unref(user); 06205 } else { 06206 /* user was not found, but we should still fake an AUTHREQ. 06207 * Set authmethods to the last known authmethod used by the system 06208 * Set a fake secret, it's not looked at, just required to attempt authentication. 06209 * Set authrej so the AUTHREP is rejected without even looking at its contents */ 06210 iaxs[callno]->authmethods = last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT); 06211 ast_string_field_set(iaxs[callno], secret, "badsecret"); 06212 iaxs[callno]->authrej = 1; 06213 if (!ast_strlen_zero(iaxs[callno]->username)) { 06214 /* only send the AUTHREQ if a username was specified. */ 06215 res = 0; 06216 } 06217 } 06218 ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK); 06219 return res; 06220 }
static int check_provisioning | ( | struct sockaddr_in * | sin, | |
int | sockfd, | |||
char * | si, | |||
unsigned int | ver | |||
) | [static] |
Definition at line 7773 of file chan_iax2.c.
References ast_debug, iax2_provision(), and iax_provision_version().
Referenced by socket_process().
07774 { 07775 unsigned int ourver; 07776 char rsi[80]; 07777 snprintf(rsi, sizeof(rsi), "si-%s", si); 07778 if (iax_provision_version(&ourver, rsi, 1)) 07779 return 0; 07780 ast_debug(1, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver); 07781 if (ourver != ver) 07782 iax2_provision(sin, sockfd, NULL, rsi, 1); 07783 return 0; 07784 }
static int check_srcaddr | ( | struct sockaddr * | sa, | |
socklen_t | salen | |||
) | [static] |
Check if address can be used as packet source.
Definition at line 10481 of file chan_iax2.c.
References ast_debug, ast_log(), errno, and LOG_ERROR.
Referenced by peer_set_srcaddr().
10482 { 10483 int sd; 10484 int res; 10485 10486 sd = socket(AF_INET, SOCK_DGRAM, 0); 10487 if (sd < 0) { 10488 ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); 10489 return -1; 10490 } 10491 10492 res = bind(sd, sa, salen); 10493 if (res < 0) { 10494 ast_debug(1, "Can't bind: %s\n", strerror(errno)); 10495 close(sd); 10496 return 1; 10497 } 10498 10499 close(sd); 10500 return 0; 10501 }
static int complete_dpreply | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6763 of file chan_iax2.c.
References ARRAY_LEN, ast_copy_string(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_UNKNOWN, iax2_dpcache::callno, iax2_dpcache::expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, ies, matchmore(), iax2_dpcache::orig, iax2_dpcache::peer_list, status, and iax2_dpcache::waiters.
Referenced by socket_process().
06764 { 06765 char exten[256] = ""; 06766 int status = CACHE_FLAG_UNKNOWN, expiry = iaxdefaultdpcache, x, matchmore = 0; 06767 struct iax2_dpcache *dp = NULL; 06768 06769 if (ies->called_number) 06770 ast_copy_string(exten, ies->called_number, sizeof(exten)); 06771 06772 if (ies->dpstatus & IAX_DPSTATUS_EXISTS) 06773 status = CACHE_FLAG_EXISTS; 06774 else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST) 06775 status = CACHE_FLAG_CANEXIST; 06776 else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT) 06777 status = CACHE_FLAG_NONEXISTENT; 06778 06779 if (ies->refresh) 06780 expiry = ies->refresh; 06781 if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE) 06782 matchmore = CACHE_FLAG_MATCHMORE; 06783 06784 AST_LIST_LOCK(&dpcache); 06785 AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, peer_list) { 06786 if (strcmp(dp->exten, exten)) 06787 continue; 06788 AST_LIST_REMOVE_CURRENT(peer_list); 06789 dp->callno = 0; 06790 dp->expiry.tv_sec = dp->orig.tv_sec + expiry; 06791 if (dp->flags & CACHE_FLAG_PENDING) { 06792 dp->flags &= ~CACHE_FLAG_PENDING; 06793 dp->flags |= status; 06794 dp->flags |= matchmore; 06795 } 06796 /* Wake up waiters */ 06797 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 06798 if (dp->waiters[x] > -1) { 06799 if (write(dp->waiters[x], "asdf", 4) < 0) { 06800 } 06801 } 06802 } 06803 } 06804 AST_LIST_TRAVERSE_SAFE_END; 06805 AST_LIST_UNLOCK(&dpcache); 06806 06807 return 0; 06808 }
static char * complete_iax2_show_peer | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 2746 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_strdup, iax2_peer::name, and peer_unref().
Referenced by handle_cli_iax2_prune_realtime(), and handle_cli_iax2_show_peer().
02747 { 02748 int which = 0; 02749 struct iax2_peer *peer; 02750 char *res = NULL; 02751 int wordlen = strlen(word); 02752 struct ao2_iterator i; 02753 02754 /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */ 02755 if (pos != 3) 02756 return NULL; 02757 02758 i = ao2_iterator_init(peers, 0); 02759 while ((peer = ao2_iterator_next(&i))) { 02760 if (!strncasecmp(peer->name, word, wordlen) && ++which > state) { 02761 res = ast_strdup(peer->name); 02762 peer_unref(peer); 02763 break; 02764 } 02765 peer_unref(peer); 02766 } 02767 02768 return res; 02769 }
static char * complete_iax2_unregister | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 5374 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_strdup, iax2_peer::expire, iax2_peer::name, and peer_unref().
Referenced by handle_cli_iax2_unregister().
05375 { 05376 int which = 0; 05377 struct iax2_peer *p = NULL; 05378 char *res = NULL; 05379 int wordlen = strlen(word); 05380 05381 /* 0 - iax2; 1 - unregister; 2 - <peername> */ 05382 if (pos == 2) { 05383 struct ao2_iterator i = ao2_iterator_init(peers, 0); 05384 while ((p = ao2_iterator_next(&i))) { 05385 if (!strncasecmp(p->name, word, wordlen) && 05386 ++which > state && p->expire > 0) { 05387 res = ast_strdup(p->name); 05388 peer_unref(p); 05389 break; 05390 } 05391 peer_unref(p); 05392 } 05393 } 05394 05395 return res; 05396 }
static int complete_transfer | ( | int | callno, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6810 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), ies, chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, iax_frame::list, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, remove_by_peercallno(), remove_by_transfercallno(), iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, store_by_peercallno(), chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, TRANSFER_NONE, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, chan_iax2_pvt::videoformat, and chan_iax2_pvt::voiceformat.
Referenced by socket_process().
06811 { 06812 int peercallno = 0; 06813 struct chan_iax2_pvt *pvt = iaxs[callno]; 06814 struct iax_frame *cur; 06815 jb_frame frame; 06816 06817 if (ies->callno) 06818 peercallno = ies->callno; 06819 06820 if (peercallno < 1) { 06821 ast_log(LOG_WARNING, "Invalid transfer request\n"); 06822 return -1; 06823 } 06824 remove_by_transfercallno(pvt); 06825 memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr)); 06826 memset(&pvt->transfer, 0, sizeof(pvt->transfer)); 06827 /* Reset sequence numbers */ 06828 pvt->oseqno = 0; 06829 pvt->rseqno = 0; 06830 pvt->iseqno = 0; 06831 pvt->aseqno = 0; 06832 06833 if (pvt->peercallno) { 06834 remove_by_peercallno(pvt); 06835 } 06836 pvt->peercallno = peercallno; 06837 /*this is where the transfering call swiches hash tables */ 06838 store_by_peercallno(pvt); 06839 pvt->transferring = TRANSFER_NONE; 06840 pvt->svoiceformat = -1; 06841 pvt->voiceformat = 0; 06842 pvt->svideoformat = -1; 06843 pvt->videoformat = 0; 06844 pvt->transfercallno = -1; 06845 memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); 06846 memset(&pvt->offset, 0, sizeof(pvt->offset)); 06847 /* reset jitterbuffer */ 06848 while(jb_getall(pvt->jb,&frame) == JB_OK) 06849 iax2_frame_free(frame.data); 06850 jb_reset(pvt->jb); 06851 pvt->lag = 0; 06852 pvt->last = 0; 06853 pvt->lastsent = 0; 06854 pvt->nextpred = 0; 06855 pvt->pingtime = DEFAULT_RETRY_TIME; 06856 AST_LIST_LOCK(&frame_queue); 06857 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 06858 /* We must cancel any packets that would have been transmitted 06859 because now we're talking to someone new. It's okay, they 06860 were transmitted to someone that didn't care anyway. */ 06861 if (callno == cur->callno) 06862 cur->retries = -1; 06863 } 06864 AST_LIST_UNLOCK(&frame_queue); 06865 return 0; 06866 }
static unsigned char compress_subclass | ( | int | subclass | ) | [static] |
Definition at line 1243 of file chan_iax2.c.
References ast_log(), IAX_FLAG_SC_LOG, IAX_MAX_SHIFT, and LOG_WARNING.
Referenced by iax2_send(), raw_hangup(), and send_apathetic_reply().
01244 { 01245 int x; 01246 int power=-1; 01247 /* If it's 128 or smaller, just return it */ 01248 if (subclass < IAX_FLAG_SC_LOG) 01249 return subclass; 01250 /* Otherwise find its power */ 01251 for (x = 0; x < IAX_MAX_SHIFT; x++) { 01252 if (subclass & (1 << x)) { 01253 if (power > -1) { 01254 ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass); 01255 return 0; 01256 } else 01257 power = x; 01258 } 01259 } 01260 return power | IAX_FLAG_SC_LOG; 01261 }
static void construct_rr | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ie_data * | iep | |||
) | [static] |
Definition at line 7786 of file chan_iax2.c.
References jb_info::current, jb_info::frames_dropped, jb_info::frames_in, jb_info::frames_lost, jb_info::frames_ooo, iax_ie_append_int(), iax_ie_append_short(), IAX_IE_RR_DELAY, IAX_IE_RR_DROPPED, IAX_IE_RR_JITTER, IAX_IE_RR_LOSS, IAX_IE_RR_OOO, IAX_IE_RR_PKTS, chan_iax2_pvt::jb, jb_getinfo(), jb_info::jitter, jb_info::losspct, and jb_info::min.
Referenced by socket_process().
07787 { 07788 jb_info stats; 07789 jb_getinfo(pvt->jb, &stats); 07790 07791 memset(iep, 0, sizeof(*iep)); 07792 07793 iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter); 07794 if(stats.frames_in == 0) stats.frames_in = 1; 07795 iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff))); 07796 iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in); 07797 iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min); 07798 iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped); 07799 iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo); 07800 }
static int create_addr | ( | const char * | peername, | |
struct ast_channel * | c, | |||
struct sockaddr_in * | sin, | |||
struct create_addr_info * | cai | |||
) | [static] |
Definition at line 3438 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_codec_pref_prepend(), ast_copy_flags, ast_copy_string(), ast_db_get(), ast_get_ip_or_srv(), ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::capability, create_addr_info::capability, iax2_peer::context, create_addr_info::context, iax2_peer::dbsecret, iax2_peer::defaddr, iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iax2_peer::lastms, LOG_DEBUG, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, iax2_peer::mohinterpret, create_addr_info::mohinterpret, iax2_peer::mohsuggest, create_addr_info::mohsuggest, ast_channel::nativeformats, iax2_peer::outkey, create_addr_info::outkey, peer_unref(), iax2_peer::peercontext, create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, prefs, iax2_peer::secret, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, iax2_peer::username, create_addr_info::username, and iax2_peer::zonetag.
03439 { 03440 struct iax2_peer *peer; 03441 int res = -1; 03442 struct ast_codec_pref ourprefs; 03443 03444 ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); 03445 cai->sockfd = defaultsockfd; 03446 cai->maxtime = 0; 03447 sin->sin_family = AF_INET; 03448 03449 if (!(peer = find_peer(peername, 1))) { 03450 cai->found = 0; 03451 if (ast_get_ip_or_srv(sin, peername, srvlookup ? "_iax._udp" : NULL)) { 03452 ast_log(LOG_WARNING, "No such host: %s\n", peername); 03453 return -1; 03454 } 03455 sin->sin_port = htons(IAX_DEFAULT_PORTNO); 03456 /* use global iax prefs for unknown peer/user */ 03457 /* But move the calling channel's native codec to the top of the preference list */ 03458 memcpy(&ourprefs, &prefs, sizeof(ourprefs)); 03459 if (c) 03460 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03461 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03462 return 0; 03463 } 03464 03465 cai->found = 1; 03466 03467 /* if the peer has no address (current or default), return failure */ 03468 if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) 03469 goto return_unref; 03470 03471 /* if the peer is being monitored and is currently unreachable, return failure */ 03472 if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) 03473 goto return_unref; 03474 03475 ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 03476 cai->maxtime = peer->maxms; 03477 cai->capability = peer->capability; 03478 cai->encmethods = peer->encmethods; 03479 cai->sockfd = peer->sockfd; 03480 cai->adsi = peer->adsi; 03481 memcpy(&ourprefs, &peer->prefs, sizeof(ourprefs)); 03482 /* Move the calling channel's native codec to the top of the preference list */ 03483 if (c) { 03484 ast_log(LOG_DEBUG, "prepending %x to prefs\n", c->nativeformats); 03485 ast_codec_pref_prepend(&ourprefs, c->nativeformats, 1); 03486 } 03487 ast_codec_pref_convert(&ourprefs, cai->prefs, sizeof(cai->prefs), 1); 03488 ast_copy_string(cai->context, peer->context, sizeof(cai->context)); 03489 ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); 03490 ast_copy_string(cai->username, peer->username, sizeof(cai->username)); 03491 ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); 03492 ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); 03493 ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret)); 03494 ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest)); 03495 if (ast_strlen_zero(peer->dbsecret)) { 03496 ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); 03497 } else { 03498 char *family; 03499 char *key = NULL; 03500 03501 family = ast_strdupa(peer->dbsecret); 03502 key = strchr(family, '/'); 03503 if (key) 03504 *key++ = '\0'; 03505 if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { 03506 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); 03507 goto return_unref; 03508 } 03509 } 03510 03511 if (peer->addr.sin_addr.s_addr) { 03512 sin->sin_addr = peer->addr.sin_addr; 03513 sin->sin_port = peer->addr.sin_port; 03514 } else { 03515 sin->sin_addr = peer->defaddr.sin_addr; 03516 sin->sin_port = peer->defaddr.sin_port; 03517 } 03518 03519 res = 0; 03520 03521 return_unref: 03522 peer_unref(peer); 03523 03524 return res; 03525 }
static int decode_frame | ( | ast_aes_decrypt_key * | dcx, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4750 of file chan_iax2.c.
References ast_debug, AST_FRAME_VIDEO, ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, f, IAX_FLAG_FULL, memcpy_decrypt(), ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::type, and uncompress_subclass().
Referenced by decrypt_frame(), and update_packet().
04751 { 04752 int padding; 04753 unsigned char *workspace; 04754 04755 workspace = alloca(*datalen); 04756 memset(f, 0, sizeof(*f)); 04757 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04758 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04759 if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr)) 04760 return -1; 04761 /* Decrypt */ 04762 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx); 04763 04764 padding = 16 + (workspace[15] & 0x0f); 04765 if (iaxdebug) 04766 ast_debug(1, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]); 04767 if (*datalen < padding + sizeof(struct ast_iax2_full_hdr)) 04768 return -1; 04769 04770 *datalen -= padding; 04771 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04772 f->frametype = fh->type; 04773 if (f->frametype == AST_FRAME_VIDEO) { 04774 f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 04775 } else { 04776 f->subclass = uncompress_subclass(fh->csub); 04777 } 04778 } else { 04779 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04780 if (iaxdebug) 04781 ast_debug(1, "Decoding mini with length %d\n", *datalen); 04782 if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr)) 04783 return -1; 04784 /* Decrypt */ 04785 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx); 04786 padding = 16 + (workspace[15] & 0x0f); 04787 if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr)) 04788 return -1; 04789 *datalen -= padding; 04790 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04791 } 04792 return 0; 04793 }
static int decrypt_frame | ( | int | callno, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 4836 of file chan_iax2.c.
References ast_set_flag, ast_strdupa, ast_test_flag, build_encryption_keys(), decode_frame(), f, IAX_KEYPOPULATED, md5(), MD5Final(), MD5Init(), MD5Update(), secret, and strsep().
Referenced by socket_process().
04837 { 04838 int res=-1; 04839 if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) { 04840 /* Search for possible keys, given secrets */ 04841 struct MD5Context md5; 04842 unsigned char digest[16]; 04843 char *tmppw, *stringp; 04844 04845 tmppw = ast_strdupa(iaxs[callno]->secret); 04846 stringp = tmppw; 04847 while ((tmppw = strsep(&stringp, ";"))) { 04848 MD5Init(&md5); 04849 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 04850 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 04851 MD5Final(digest, &md5); 04852 build_encryption_keys(digest, iaxs[callno]); 04853 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04854 if (!res) { 04855 ast_set_flag(iaxs[callno], IAX_KEYPOPULATED); 04856 break; 04857 } 04858 } 04859 } else 04860 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 04861 return res; 04862 }
static void defer_full_frame | ( | struct iax2_thread * | from_here, | |
struct iax2_thread * | to_here | |||
) | [static] |
Queue the last read full frame for processing by a certain thread.
If there are already any full frames queued, they are sorted by sequence number.
Definition at line 7933 of file chan_iax2.c.
References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), iax2_pkt_buf::buf, iax2_thread::buf, iax2_thread::buf_len, iax2_thread::full_frames, iax2_thread::lock, and ast_iax2_full_hdr::oseqno.
Referenced by socket_read().
07934 { 07935 struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf; 07936 struct ast_iax2_full_hdr *fh, *cur_fh; 07937 07938 if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len))) 07939 return; 07940 07941 pkt_buf->len = from_here->buf_len; 07942 memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len); 07943 07944 fh = (struct ast_iax2_full_hdr *) pkt_buf->buf; 07945 ast_mutex_lock(&to_here->lock); 07946 AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) { 07947 cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf; 07948 if (fh->oseqno < cur_fh->oseqno) { 07949 AST_LIST_INSERT_BEFORE_CURRENT(pkt_buf, entry); 07950 break; 07951 } 07952 } 07953 AST_LIST_TRAVERSE_SAFE_END 07954 07955 if (!cur_pkt_buf) 07956 AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry); 07957 07958 ast_mutex_unlock(&to_here->lock); 07959 }
static void delete_users | ( | void | ) | [static] |
Definition at line 11077 of file chan_iax2.c.
References ao2_callback(), ast_dnsmgr_release(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::entry, iax2_registry::expire, iax2_destroy(), peer_delme_cb(), sched, and user_delme_cb().
11078 { 11079 struct iax2_registry *reg; 11080 11081 ao2_callback(users, 0, user_delme_cb, NULL); 11082 11083 AST_LIST_LOCK(®istrations); 11084 while ((reg = AST_LIST_REMOVE_HEAD(®istrations, entry))) { 11085 AST_SCHED_DEL(sched, reg->expire); 11086 if (reg->callno) { 11087 int callno = reg->callno; 11088 ast_mutex_lock(&iaxsl[callno]); 11089 if (iaxs[callno]) { 11090 iaxs[callno]->reg = NULL; 11091 iax2_destroy(callno); 11092 } 11093 ast_mutex_unlock(&iaxsl[callno]); 11094 } 11095 if (reg->dnsmgr) 11096 ast_dnsmgr_release(reg->dnsmgr); 11097 ast_free(reg); 11098 } 11099 AST_LIST_UNLOCK(®istrations); 11100 11101 ao2_callback(peers, 0, peer_delme_cb, NULL); 11102 }
static void destroy_firmware | ( | struct iax_firmware * | cur | ) | [static] |
Definition at line 1954 of file chan_iax2.c.
References ast_free, ast_iax2_firmware_header::datalen, iax_firmware::fd, and iax_firmware::fwh.
Referenced by reload_firmware().
01955 { 01956 /* Close firmware */ 01957 if (cur->fwh) { 01958 munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh))); 01959 } 01960 close(cur->fd); 01961 ast_free(cur); 01962 }
static void dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid, | |||
int | skiplock | |||
) | [static] |
Definition at line 7634 of file chan_iax2.c.
References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_IAX, ast_ignore_pattern(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), IAX_COMMAND_DPREP, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_NUMBER, IAX_IE_DPSTATUS, IAX_IE_REFRESH, and send_command().
Referenced by dp_lookup_thread(), and socket_process().
07635 { 07636 unsigned short dpstatus = 0; 07637 struct iax_ie_data ied1; 07638 int mm; 07639 07640 memset(&ied1, 0, sizeof(ied1)); 07641 mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); 07642 /* Must be started */ 07643 if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) { 07644 dpstatus = IAX_DPSTATUS_EXISTS; 07645 } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { 07646 dpstatus = IAX_DPSTATUS_CANEXIST; 07647 } else { 07648 dpstatus = IAX_DPSTATUS_NONEXISTENT; 07649 } 07650 if (ast_ignore_pattern(context, callednum)) 07651 dpstatus |= IAX_DPSTATUS_IGNOREPAT; 07652 if (mm) 07653 dpstatus |= IAX_DPSTATUS_MATCHMORE; 07654 if (!skiplock) 07655 ast_mutex_lock(&iaxsl[callno]); 07656 if (iaxs[callno]) { 07657 iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); 07658 iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); 07659 iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); 07660 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); 07661 } 07662 if (!skiplock) 07663 ast_mutex_unlock(&iaxsl[callno]); 07664 }
static void* dp_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 7666 of file chan_iax2.c.
References ast_free, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, and dp_lookup().
Referenced by spawn_dp_lookup().
07667 { 07668 /* Look up for dpreq */ 07669 struct dpreq_data *dpr = data; 07670 dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0); 07671 if (dpr->callerid) 07672 ast_free(dpr->callerid); 07673 ast_free(dpr); 07674 return NULL; 07675 }
static int encrypt_frame | ( | ast_aes_encrypt_key * | ecx, | |
struct ast_iax2_full_hdr * | fh, | |||
unsigned char * | poo, | |||
int * | datalen | |||
) | [static] |
Definition at line 4795 of file chan_iax2.c.
References ast_debug, ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, memcpy_encrypt(), ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.
Referenced by iax2_send(), and update_packet().
04796 { 04797 int padding; 04798 unsigned char *workspace; 04799 workspace = alloca(*datalen + 32); 04800 if (!workspace) 04801 return -1; 04802 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 04803 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 04804 if (iaxdebug) 04805 ast_debug(1, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen); 04806 padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16); 04807 padding = 16 + (padding & 0xf); 04808 memcpy(workspace, poo, padding); 04809 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 04810 workspace[15] &= 0xf0; 04811 workspace[15] |= (padding & 0xf); 04812 if (iaxdebug) 04813 ast_debug(1, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]); 04814 *datalen += padding; 04815 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx); 04816 if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr)) 04817 memcpy(poo, workspace + *datalen - 32, 32); 04818 } else { 04819 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 04820 if (iaxdebug) 04821 ast_debug(1, "Encoding mini frame with length %d\n", *datalen); 04822 padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16); 04823 padding = 16 + (padding & 0xf); 04824 memcpy(workspace, poo, padding); 04825 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 04826 workspace[15] &= 0xf0; 04827 workspace[15] |= (padding & 0x0f); 04828 *datalen += padding; 04829 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx); 04830 if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr)) 04831 memcpy(poo, workspace + *datalen - 32, 32); 04832 } 04833 return 0; 04834 }
static int expire_registry | ( | const void * | data | ) | [static] |
Definition at line 7062 of file chan_iax2.c.
References __expire_registry(), and schedule_action.
Referenced by handle_cli_iax2_prune_realtime(), handle_cli_iax2_unregister(), reg_source_db(), and update_registry().
07063 { 07064 #ifdef SCHED_MULTITHREADED 07065 if (schedule_action(__expire_registry, data)) 07066 #endif 07067 __expire_registry(data); 07068 return 0; 07069 }
static struct iax2_dpcache* find_cache | ( | struct ast_channel * | chan, | |
const char * | data, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) | [static] |
Definition at line 11688 of file chan_iax2.c.
References ARRAY_LEN, ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_copy_string(), ast_free, ast_frfree, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_tvcmp(), ast_tvnow(), ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, chan, errno, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, iax2_dprequest(), IAX_STATE_STARTED, LOG_WARNING, iax2_dpcache::orig, iax2_dpcache::peercontext, and iax2_dpcache::waiters.
Referenced by iax2_canmatch(), iax2_exec(), iax2_exists(), and iax2_matchmore().
11689 { 11690 struct iax2_dpcache *dp = NULL; 11691 struct timeval tv = ast_tvnow(); 11692 int x, com[2], timeout, old = 0, outfd, abort, callno; 11693 struct ast_channel *c = NULL; 11694 struct ast_frame *f = NULL; 11695 11696 AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) { 11697 if (ast_tvcmp(tv, dp->expiry) > 0) { 11698 AST_LIST_REMOVE_CURRENT(cache_list); 11699 if ((dp->flags & CACHE_FLAG_PENDING) || dp->callno) 11700 ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = blah, callno = %d)\n", dp->flags, dp->callno); 11701 else 11702 ast_free(dp); 11703 continue; 11704 } 11705 if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 11706 break; 11707 } 11708 AST_LIST_TRAVERSE_SAFE_END; 11709 11710 if (!dp) { 11711 /* No matching entry. Create a new one. */ 11712 /* First, can we make a callno? */ 11713 if ((callno = cache_get_callno_locked(data)) < 0) { 11714 ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data); 11715 return NULL; 11716 } 11717 if (!(dp = ast_calloc(1, sizeof(*dp)))) { 11718 ast_mutex_unlock(&iaxsl[callno]); 11719 return NULL; 11720 } 11721 ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext)); 11722 ast_copy_string(dp->exten, exten, sizeof(dp->exten)); 11723 dp->expiry = ast_tvnow(); 11724 dp->orig = dp->expiry; 11725 /* Expires in 30 mins by default */ 11726 dp->expiry.tv_sec += iaxdefaultdpcache; 11727 dp->flags = CACHE_FLAG_PENDING; 11728 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) 11729 dp->waiters[x] = -1; 11730 /* Insert into the lists */ 11731 AST_LIST_INSERT_TAIL(&dpcache, dp, cache_list); 11732 AST_LIST_INSERT_TAIL(&iaxs[callno]->dpentries, dp, peer_list); 11733 /* Send the request if we're already up */ 11734 if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 11735 iax2_dprequest(dp, callno); 11736 ast_mutex_unlock(&iaxsl[callno]); 11737 } 11738 11739 /* By here we must have a dp */ 11740 if (dp->flags & CACHE_FLAG_PENDING) { 11741 /* Okay, here it starts to get nasty. We need a pipe now to wait 11742 for a reply to come back so long as it's pending */ 11743 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 11744 /* Find an empty slot */ 11745 if (dp->waiters[x] < 0) 11746 break; 11747 } 11748 if (x >= ARRAY_LEN(dp->waiters)) { 11749 ast_log(LOG_WARNING, "No more waiter positions available\n"); 11750 return NULL; 11751 } 11752 if (pipe(com)) { 11753 ast_log(LOG_WARNING, "Unable to create pipe for comm\n"); 11754 return NULL; 11755 } 11756 dp->waiters[x] = com[1]; 11757 /* Okay, now we wait */ 11758 timeout = iaxdefaulttimeout * 1000; 11759 /* Temporarily unlock */ 11760 AST_LIST_UNLOCK(&dpcache); 11761 /* Defer any dtmf */ 11762 if (chan) 11763 old = ast_channel_defer_dtmf(chan); 11764 abort = 0; 11765 while(timeout) { 11766 c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout); 11767 if (outfd > -1) 11768 break; 11769 if (!c) 11770 continue; 11771 if (!(f = ast_read(c))) { 11772 abort = 1; 11773 break; 11774 } 11775 ast_frfree(f); 11776 } 11777 if (!timeout) { 11778 ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten); 11779 } 11780 AST_LIST_LOCK(&dpcache); 11781 dp->waiters[x] = -1; 11782 close(com[1]); 11783 close(com[0]); 11784 if (abort) { 11785 /* Don't interpret anything, just abort. Not sure what th epoint 11786 of undeferring dtmf on a hung up channel is but hey whatever */ 11787 if (!old && chan) 11788 ast_channel_undefer_dtmf(chan); 11789 return NULL; 11790 } 11791 if (!(dp->flags & CACHE_FLAG_TIMEOUT)) { 11792 /* Now to do non-independent analysis the results of our wait */ 11793 if (dp->flags & CACHE_FLAG_PENDING) { 11794 /* Still pending... It's a timeout. Wake everybody up. Consider it no longer 11795 pending. Don't let it take as long to timeout. */ 11796 dp->flags &= ~CACHE_FLAG_PENDING; 11797 dp->flags |= CACHE_FLAG_TIMEOUT; 11798 /* Expire after only 60 seconds now. This is designed to help reduce backlog in heavily loaded 11799 systems without leaving it unavailable once the server comes back online */ 11800 dp->expiry.tv_sec = dp->orig.tv_sec + 60; 11801 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 11802 if (dp->waiters[x] > -1) { 11803 if (write(dp->waiters[x], "asdf", 4) < 0) { 11804 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 11805 } 11806 } 11807 } 11808 } 11809 } 11810 /* Our caller will obtain the rest */ 11811 if (!old && chan) 11812 ast_channel_undefer_dtmf(chan); 11813 } 11814 return dp; 11815 }
static int find_callno | ( | unsigned short | callno, | |
unsigned short | dcallno, | |||
struct sockaddr_in * | sin, | |||
int | new, | |||
int | sockfd, | |||
int | full_frame | |||
) | [static] |
Definition at line 1854 of file chan_iax2.c.
References __find_callno().
Referenced by iax2_poke_peer(), and socket_process().
01854 { 01855 01856 return __find_callno(callno, dcallno, sin, new, sockfd, 0, full_frame); 01857 }
static int find_callno_locked | ( | unsigned short | callno, | |
unsigned short | dcallno, | |||
struct sockaddr_in * | sin, | |||
int | new, | |||
int | sockfd, | |||
int | full_frame | |||
) | [static] |
Definition at line 1859 of file chan_iax2.c.
References __find_callno().
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_provision(), iax2_request(), and socket_process_meta().
01859 { 01860 01861 return __find_callno(callno, dcallno, sin, new, sockfd, 1, full_frame); 01862 }
static struct iax2_thread* find_idle_thread | ( | void | ) | [static] |
Definition at line 1060 of file chan_iax2.c.
References ast_atomic_fetchadd_int(), ast_calloc, ast_cond_destroy(), ast_cond_init(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_mutex_init(), ast_pthread_create_detached_background, iax2_process_thread(), IAX_THREAD_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxdynamicthreadnum, iaxmaxthreadcount, iax2_trunk_peer::list, and thread.
Referenced by __schedule_action(), and socket_read().
01061 { 01062 struct iax2_thread *thread = NULL; 01063 01064 /* Pop the head of the idle list off */ 01065 AST_LIST_LOCK(&idle_list); 01066 thread = AST_LIST_REMOVE_HEAD(&idle_list, list); 01067 AST_LIST_UNLOCK(&idle_list); 01068 01069 /* If we popped a thread off the idle list, just return it */ 01070 if (thread) { 01071 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01072 return thread; 01073 } 01074 01075 /* Pop the head of the dynamic list off */ 01076 AST_LIST_LOCK(&dynamic_list); 01077 thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list); 01078 AST_LIST_UNLOCK(&dynamic_list); 01079 01080 /* If we popped a thread off the dynamic list, just return it */ 01081 if (thread) { 01082 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01083 return thread; 01084 } 01085 01086 /* If we can't create a new dynamic thread for any reason, return no thread at all */ 01087 if (iaxdynamicthreadcount >= iaxmaxthreadcount || !(thread = ast_calloc(1, sizeof(*thread)))) 01088 return NULL; 01089 01090 /* Set default values */ 01091 ast_atomic_fetchadd_int(&iaxdynamicthreadcount, 1); 01092 thread->threadnum = ast_atomic_fetchadd_int(&iaxdynamicthreadnum, 1); 01093 thread->type = IAX_THREAD_TYPE_DYNAMIC; 01094 01095 /* Initialize lock and condition */ 01096 ast_mutex_init(&thread->lock); 01097 ast_cond_init(&thread->cond, NULL); 01098 01099 /* Create thread and send it on it's way */ 01100 if (ast_pthread_create_detached_background(&thread->threadid, NULL, iax2_process_thread, thread)) { 01101 ast_cond_destroy(&thread->cond); 01102 ast_mutex_destroy(&thread->lock); 01103 ast_free(thread); 01104 return NULL; 01105 } 01106 01107 /* this thread is not processing a full frame (since it is idle), 01108 so ensure that the field for the full frame call number is empty */ 01109 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 01110 01111 /* Wait for the thread to be ready before returning it to the caller */ 01112 while (!thread->ready_for_signal) 01113 usleep(1); 01114 01115 return thread; 01116 }
static struct iax2_peer* find_peer | ( | const char * | name, | |
int | realtime | |||
) | [static] |
Definition at line 1321 of file chan_iax2.c.
References ao2_find(), iax2_peer::name, OBJ_POINTER, and realtime_peer().
01322 { 01323 struct iax2_peer *peer = NULL; 01324 struct iax2_peer tmp_peer = { 01325 .name = name, 01326 }; 01327 01328 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 01329 01330 /* Now go for realtime if applicable */ 01331 if(!peer && realtime) 01332 peer = realtime_peer(name, NULL); 01333 01334 return peer; 01335 }
static struct iax2_trunk_peer* find_tpeer | ( | struct sockaddr_in * | sin, | |
int | fd | |||
) | [static] |
Definition at line 4568 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_calloc, ast_debug, ast_inet_ntoa(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_init(), ast_mutex_lock(), ast_tvnow(), inaddrcmp(), iax2_trunk_peer::list, and iax2_trunk_peer::lock.
Referenced by iax2_trunk_queue(), and socket_process_meta().
04569 { 04570 struct iax2_trunk_peer *tpeer = NULL; 04571 04572 /* Finds and locks trunk peer */ 04573 AST_LIST_LOCK(&tpeers); 04574 04575 AST_LIST_TRAVERSE(&tpeers, tpeer, list) { 04576 if (!inaddrcmp(&tpeer->addr, sin)) { 04577 ast_mutex_lock(&tpeer->lock); 04578 break; 04579 } 04580 } 04581 04582 if (!tpeer) { 04583 if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) { 04584 ast_mutex_init(&tpeer->lock); 04585 tpeer->lastsent = 9999; 04586 memcpy(&tpeer->addr, sin, sizeof(tpeer->addr)); 04587 tpeer->trunkact = ast_tvnow(); 04588 ast_mutex_lock(&tpeer->lock); 04589 tpeer->sockfd = fd; 04590 #ifdef SO_NO_CHECK 04591 setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 04592 #endif 04593 ast_debug(1, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 04594 AST_LIST_INSERT_TAIL(&tpeers, tpeer, list); 04595 } 04596 } 04597 04598 AST_LIST_UNLOCK(&tpeers); 04599 04600 return tpeer; 04601 }
static struct iax2_user* find_user | ( | const char * | name | ) | [static] |
Definition at line 1349 of file chan_iax2.c.
References ao2_find(), iax2_user::name, and OBJ_POINTER.
01350 { 01351 struct iax2_user tmp_user = { 01352 .name = name, 01353 }; 01354 01355 return ao2_find(users, &tmp_user, OBJ_POINTER); 01356 }
static unsigned int fix_peerts | ( | struct timeval * | tv, | |
int | callno, | |||
unsigned int | ts | |||
) | [static] |
Definition at line 4381 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvnow(), and ast_tvzero().
Referenced by socket_process_meta().
04382 { 04383 long ms; /* NOT unsigned */ 04384 if (ast_tvzero(iaxs[callno]->rxcore)) { 04385 /* Initialize rxcore time if appropriate */ 04386 iaxs[callno]->rxcore = ast_tvnow(); 04387 /* Round to nearest 20ms so traces look pretty */ 04388 iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000; 04389 } 04390 /* Calculate difference between trunk and channel */ 04391 ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore); 04392 /* Return as the sum of trunk time and the difference between trunk and real time */ 04393 return ms + ts; 04394 }
static void free_context | ( | struct iax2_context * | con | ) | [static] |
Definition at line 10244 of file chan_iax2.c.
References ast_free, and iax2_context::next.
Referenced by build_user(), and user_destructor().
10245 { 10246 struct iax2_context *conl; 10247 while(con) { 10248 conl = con; 10249 con = con->next; 10250 ast_free(conl); 10251 } 10252 }
static int function_iaxpeer | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 11938 of file chan_iax2.c.
References iax2_peer::addr, ast_codec_pref_index(), ast_copy_string(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_peer::capability, chan, iax2_peer::cid_name, iax2_peer::cid_num, iax2_peer::context, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iax2_peer::mailbox, peer_status(), peer_unref(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
11939 { 11940 struct iax2_peer *peer; 11941 char *peername, *colname; 11942 11943 peername = ast_strdupa(data); 11944 11945 /* if our channel, return the IP address of the endpoint of current channel */ 11946 if (!strcmp(peername,"CURRENTCHANNEL")) { 11947 unsigned short callno; 11948 if (chan->tech != &iax2_tech) 11949 return -1; 11950 callno = PTR_TO_CALLNO(chan->tech_pvt); 11951 ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len); 11952 return 0; 11953 } 11954 11955 if ((colname = strchr(peername, ','))) 11956 *colname++ = '\0'; 11957 else 11958 colname = "ip"; 11959 11960 if (!(peer = find_peer(peername, 1))) 11961 return -1; 11962 11963 if (!strcasecmp(colname, "ip")) { 11964 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 11965 } else if (!strcasecmp(colname, "status")) { 11966 peer_status(peer, buf, len); 11967 } else if (!strcasecmp(colname, "mailbox")) { 11968 ast_copy_string(buf, peer->mailbox, len); 11969 } else if (!strcasecmp(colname, "context")) { 11970 ast_copy_string(buf, peer->context, len); 11971 } else if (!strcasecmp(colname, "expire")) { 11972 snprintf(buf, len, "%d", peer->expire); 11973 } else if (!strcasecmp(colname, "dynamic")) { 11974 ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len); 11975 } else if (!strcasecmp(colname, "callerid_name")) { 11976 ast_copy_string(buf, peer->cid_name, len); 11977 } else if (!strcasecmp(colname, "callerid_num")) { 11978 ast_copy_string(buf, peer->cid_num, len); 11979 } else if (!strcasecmp(colname, "codecs")) { 11980 ast_getformatname_multiple(buf, len -1, peer->capability); 11981 } else if (!strncasecmp(colname, "codec[", 6)) { 11982 char *codecnum, *ptr; 11983 int index = 0, codec = 0; 11984 11985 codecnum = strchr(colname, '['); 11986 *codecnum = '\0'; 11987 codecnum++; 11988 if ((ptr = strchr(codecnum, ']'))) { 11989 *ptr = '\0'; 11990 } 11991 index = atoi(codecnum); 11992 if((codec = ast_codec_pref_index(&peer->prefs, index))) { 11993 ast_copy_string(buf, ast_getformatname(codec), len); 11994 } 11995 } 11996 11997 peer_unref(peer); 11998 11999 return 0; 12000 }
static int get_auth_methods | ( | const char * | value | ) | [static] |
Definition at line 10465 of file chan_iax2.c.
References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.
Referenced by build_peer(), and build_user().
10466 { 10467 int methods = 0; 10468 if (strstr(value, "rsa")) 10469 methods |= IAX_AUTH_RSA; 10470 if (strstr(value, "md5")) 10471 methods |= IAX_AUTH_MD5; 10472 if (strstr(value, "plaintext")) 10473 methods |= IAX_AUTH_PLAINTEXT; 10474 return methods; 10475 }
static int get_encrypt_methods | ( | const char * | s | ) | [static] |
Definition at line 1198 of file chan_iax2.c.
References ast_true(), and IAX_ENCRYPT_AES128.
Referenced by build_peer(), build_user(), and set_config().
01199 { 01200 int e; 01201 if (!strcasecmp(s, "aes128")) 01202 e = IAX_ENCRYPT_AES128; 01203 else if (ast_true(s)) 01204 e = IAX_ENCRYPT_AES128; 01205 else 01206 e = 0; 01207 return e; 01208 }
static int get_from_jb | ( | const void * | p | ) | [static] |
Definition at line 3056 of file chan_iax2.c.
References __get_from_jb(), and schedule_action.
Referenced by update_jbsched().
03057 { 03058 #ifdef SCHED_MULTITHREADED 03059 if (schedule_action(__get_from_jb, data)) 03060 #endif 03061 __get_from_jb(data); 03062 return 0; 03063 }
static char* handle_cli_iax2_provision | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 10100 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax2_provision(), iax_prov_complete_template(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
10101 { 10102 int force = 0; 10103 int res; 10104 10105 switch (cmd) { 10106 case CLI_INIT: 10107 e->command = "iax2 provision"; 10108 e->usage = 10109 "Usage: iax2 provision <host> <template> [forced]\n" 10110 " Provisions the given peer or IP address using a template\n" 10111 " matching either 'template' or '*' if the template is not\n" 10112 " found. If 'forced' is specified, even empty provisioning\n" 10113 " fields will be provisioned as empty fields.\n"; 10114 return NULL; 10115 case CLI_GENERATE: 10116 if (a->pos == 3) 10117 return iax_prov_complete_template(a->line, a->word, a->pos, a->n); 10118 return NULL; 10119 } 10120 10121 if (a->argc < 4) 10122 return CLI_SHOWUSAGE; 10123 if (a->argc > 4) { 10124 if (!strcasecmp(a->argv[4], "forced")) 10125 force = 1; 10126 else 10127 return CLI_SHOWUSAGE; 10128 } 10129 res = iax2_provision(NULL, -1, a->argv[2], a->argv[3], force); 10130 if (res < 0) 10131 ast_cli(a->fd, "Unable to find peer/address '%s'\n", a->argv[2]); 10132 else if (res < 1) 10133 ast_cli(a->fd, "No template (including wildcard) matching '%s'\n", a->argv[3]); 10134 else 10135 ast_cli(a->fd, "Provisioning '%s' with template '%s'%s\n", a->argv[2], a->argv[3], force ? ", forced" : ""); 10136 return CLI_SUCCESS; 10137 }
static char* handle_cli_iax2_prune_realtime | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2508 of file chan_iax2.c.
References ao2_unlink(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_set_flag, ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_show_peer(), expire_registry(), ast_cli_args::fd, find_peer(), find_user(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, ast_cli_args::line, ast_cli_args::n, peer_ref(), peer_unref(), ast_cli_args::pos, prune_peers(), prune_users(), ast_cli_entry::usage, user, user_unref(), and ast_cli_args::word.
02509 { 02510 struct iax2_peer *peer = NULL; 02511 struct iax2_user *user = NULL; 02512 02513 switch (cmd) { 02514 case CLI_INIT: 02515 e->command = "iax2 prune realtime"; 02516 e->usage = 02517 "Usage: iax2 prune realtime [<peername>|all]\n" 02518 " Prunes object(s) from the cache\n"; 02519 return NULL; 02520 case CLI_GENERATE: 02521 return complete_iax2_show_peer(a->line, a->word, a->pos, a->n); 02522 } 02523 if (a->argc != 4) 02524 return CLI_SHOWUSAGE; 02525 if (!strcmp(a->argv[3], "all")) { 02526 prune_users(); 02527 prune_peers(); 02528 ast_cli(a->fd, "Cache flushed successfully.\n"); 02529 return CLI_SUCCESS; 02530 } 02531 peer = find_peer(a->argv[3], 0); 02532 user = find_user(a->argv[3]); 02533 if (peer || user) { 02534 if (peer) { 02535 if (ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 02536 ast_set_flag(peer, IAX_RTAUTOCLEAR); 02537 expire_registry(peer_ref(peer)); 02538 ast_cli(a->fd, "Peer %s was removed from the cache.\n", a->argv[3]); 02539 } else { 02540 ast_cli(a->fd, "Peer %s is not eligible for this operation.\n", a->argv[3]); 02541 } 02542 peer_unref(peer); 02543 } 02544 if (user) { 02545 if (ast_test_flag(user, IAX_RTCACHEFRIENDS)) { 02546 ast_set_flag(user, IAX_RTAUTOCLEAR); 02547 ast_cli(a->fd, "User %s was removed from the cache.\n", a->argv[3]); 02548 } else { 02549 ast_cli(a->fd, "User %s is not eligible for this operation.\n", a->argv[3]); 02550 } 02551 ao2_unlink(users,user); 02552 user_unref(user); 02553 } 02554 } else { 02555 ast_cli(a->fd, "%s was not found in the cache.\n", a->argv[3]); 02556 } 02557 02558 return CLI_SUCCESS; 02559 }
static char* handle_cli_iax2_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 11593 of file chan_iax2.c.
References CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, reload_config(), and ast_cli_entry::usage.
11594 { 11595 switch (cmd) { 11596 case CLI_INIT: 11597 e->command = "iax2 reload"; 11598 e->usage = 11599 "Usage: iax2 reload\n" 11600 " Reloads IAX configuration from iax.conf\n"; 11601 return NULL; 11602 case CLI_GENERATE: 11603 return NULL; 11604 } 11605 11606 reload_config(); 11607 11608 return CLI_SUCCESS; 11609 }
static char* handle_cli_iax2_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5776 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
05777 { 05778 switch (cmd) { 05779 case CLI_INIT: 05780 e->command = "iax2 set debug {on|off}"; 05781 e->usage = 05782 "Usage: iax2 set debug {on|off}\n" 05783 " Enables/Disables dumping of IAX packets for debugging purposes.\n"; 05784 return NULL; 05785 case CLI_GENERATE: 05786 return NULL; 05787 } 05788 05789 if (a->argc != e->args) 05790 return CLI_SHOWUSAGE; 05791 05792 if (!strncasecmp(a->argv[e->args -1], "on", 2)) { 05793 iaxdebug = 1; 05794 ast_cli(a->fd, "IAX2 Debugging Enabled\n"); 05795 } else { 05796 iaxdebug = 0; 05797 ast_cli(a->fd, "IAX2 Debugging Disabled\n"); 05798 } 05799 return CLI_SUCCESS; 05800 }
static char* handle_cli_iax2_set_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5752 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
05753 { 05754 switch (cmd) { 05755 case CLI_INIT: 05756 e->command = "iax2 set debug [off]"; 05757 e->usage = 05758 "Usage: iax2 set debug [off]\n" 05759 " Enables/Disables dumping of IAX packets for debugging purposes.\n"; 05760 return NULL; 05761 case CLI_GENERATE: 05762 return NULL; 05763 } 05764 if (a->argc < 3 || a->argc > 4) 05765 return CLI_SHOWUSAGE; 05766 if (a->argc == 3) { 05767 iaxdebug = 1; 05768 ast_cli(a->fd, "IAX2 Debugging Enabled\n"); 05769 } else { 05770 iaxdebug = 0; 05771 ast_cli(a->fd, "IAX2 Debugging Disabled\n"); 05772 } 05773 return CLI_SUCCESS; 05774 }
static char* handle_cli_iax2_set_debug_jb | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5881 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), and ast_cli_entry::usage.
05882 { 05883 switch (cmd) { 05884 case CLI_INIT: 05885 e->command = "iax2 set debug jb {on|off}"; 05886 e->usage = 05887 "Usage: iax2 set debug jb {on|off}\n" 05888 " Enables/Disables jitterbuffer debugging information\n"; 05889 return NULL; 05890 case CLI_GENERATE: 05891 return NULL; 05892 } 05893 05894 if (a->argc != e->args) 05895 return CLI_SHOWUSAGE; 05896 05897 if (!strncasecmp(a->argv[e->args -1], "on", 2)) { 05898 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 05899 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 05900 } else { 05901 jb_setoutput(jb_error_output, jb_warning_output, NULL); 05902 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 05903 } 05904 return CLI_SUCCESS; 05905 }
static char* handle_cli_iax2_set_debug_jb_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5855 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), and ast_cli_entry::usage.
05856 { 05857 switch (cmd) { 05858 case CLI_INIT: 05859 e->command = "iax2 set debug jb [off]"; 05860 e->usage = 05861 "Usage: iax2 set debug jb [off]\n" 05862 " Enables/Disables jitterbuffer debugging information\n"; 05863 return NULL; 05864 case CLI_GENERATE: 05865 return NULL; 05866 } 05867 05868 if (a->argc < 4 || a->argc > 5) 05869 return CLI_SHOWUSAGE; 05870 05871 if (a->argc == 4) { 05872 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 05873 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 05874 } else { 05875 jb_setoutput(jb_error_output, jb_warning_output, NULL); 05876 ast_cli(a->fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 05877 } 05878 return CLI_SUCCESS; 05879 }
static char* handle_cli_iax2_set_debug_trunk | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5829 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
05830 { 05831 switch (cmd) { 05832 case CLI_INIT: 05833 e->command = "iax2 set debug trunk {on|off}"; 05834 e->usage = 05835 "Usage: iax2 set debug trunk {on|off}\n" 05836 " Enables/Disables debugging of IAX trunking\n"; 05837 return NULL; 05838 case CLI_GENERATE: 05839 return NULL; 05840 } 05841 05842 if (a->argc != e->args) 05843 return CLI_SHOWUSAGE; 05844 05845 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 05846 iaxtrunkdebug = 1; 05847 ast_cli(a->fd, "IAX2 Trunk Debugging Enabled\n"); 05848 } else { 05849 iaxtrunkdebug = 0; 05850 ast_cli(a->fd, "IAX2 Trunk Debugging Disabled\n"); 05851 } 05852 return CLI_SUCCESS; 05853 }
static char* handle_cli_iax2_set_debug_trunk_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5803 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
05804 { 05805 switch (cmd) { 05806 case CLI_INIT: 05807 e->command = "iax2 set debug trunk [off]"; 05808 e->usage = 05809 "Usage: iax2 set debug trunk [off]\n" 05810 " Enables/Disables debugging of IAX trunking\n"; 05811 return NULL; 05812 case CLI_GENERATE: 05813 return NULL; 05814 } 05815 05816 if (a->argc < 4 || a->argc > 5) 05817 return CLI_SHOWUSAGE; 05818 05819 if (a->argc == 4) { 05820 iaxtrunkdebug = 1; 05821 ast_cli(a->fd, "IAX2 Trunk Debugging Enabled\n"); 05822 } else { 05823 iaxtrunkdebug = 0; 05824 ast_cli(a->fd, "IAX2 Trunk Debugging Disabled\n"); 05825 } 05826 return CLI_SUCCESS; 05827 }
static char* handle_cli_iax2_set_mtu | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Set trunk MTU from CLI.
Definition at line 2815 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, MAX_TRUNK_MTU, and ast_cli_entry::usage.
02816 { 02817 int mtuv; 02818 02819 switch (cmd) { 02820 case CLI_INIT: 02821 e->command = "iax2 set mtu"; 02822 e->usage = 02823 "Usage: iax2 set mtu <value>\n" 02824 " Set the system-wide IAX IP mtu to <value> bytes net or\n" 02825 " zero to disable. Disabling means that the operating system\n" 02826 " must handle fragmentation of UDP packets when the IAX2 trunk\n" 02827 " packet exceeds the UDP payload size. This is substantially\n" 02828 " below the IP mtu. Try 1240 on ethernets. Must be 172 or\n" 02829 " greater for G.711 samples.\n"; 02830 return NULL; 02831 case CLI_GENERATE: 02832 return NULL; 02833 } 02834 02835 if (a->argc != 4) 02836 return CLI_SHOWUSAGE; 02837 if (strncasecmp(a->argv[3], "default", strlen(a->argv[3])) == 0) 02838 mtuv = MAX_TRUNK_MTU; 02839 else 02840 mtuv = atoi(a->argv[3]); 02841 02842 if (mtuv == 0) { 02843 ast_cli(a->fd, "Trunk MTU control disabled (mtu was %d)\n", global_max_trunk_mtu); 02844 global_max_trunk_mtu = 0; 02845 return CLI_SUCCESS; 02846 } 02847 if (mtuv < 172 || mtuv > 4000) { 02848 ast_cli(a->fd, "Trunk MTU must be between 172 and 4000\n"); 02849 return CLI_SHOWUSAGE; 02850 } 02851 ast_cli(a->fd, "Trunk MTU changed from %d to %d\n", global_max_trunk_mtu, mtuv); 02852 global_max_trunk_mtu = mtuv; 02853 return CLI_SUCCESS; 02854 }
static char* handle_cli_iax2_show_cache | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2856 of file chan_iax2.c.
References ARRAY_LEN, ast_cli(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_tvnow(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, CACHE_FLAG_TRANSMITTED, CACHE_FLAG_UNKNOWN, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, iax2_dpcache::expiry, iax2_dpcache::exten, ast_cli_args::fd, iax2_dpcache::flags, iax2_dpcache::peercontext, s, ast_cli_entry::usage, and iax2_dpcache::waiters.
02857 { 02858 struct iax2_dpcache *dp = NULL; 02859 char tmp[1024], *pc = NULL; 02860 int s, x, y; 02861 struct timeval tv = ast_tvnow(); 02862 02863 switch (cmd) { 02864 case CLI_INIT: 02865 e->command = "iax2 show cache"; 02866 e->usage = 02867 "Usage: iax2 show cache\n" 02868 " Display currently cached IAX Dialplan results.\n"; 02869 return NULL; 02870 case CLI_GENERATE: 02871 return NULL; 02872 } 02873 02874 AST_LIST_LOCK(&dpcache); 02875 02876 ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags"); 02877 02878 AST_LIST_TRAVERSE(&dpcache, dp, cache_list) { 02879 s = dp->expiry.tv_sec - tv.tv_sec; 02880 tmp[0] = '\0'; 02881 if (dp->flags & CACHE_FLAG_EXISTS) 02882 strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1); 02883 if (dp->flags & CACHE_FLAG_NONEXISTENT) 02884 strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1); 02885 if (dp->flags & CACHE_FLAG_CANEXIST) 02886 strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1); 02887 if (dp->flags & CACHE_FLAG_PENDING) 02888 strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1); 02889 if (dp->flags & CACHE_FLAG_TIMEOUT) 02890 strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1); 02891 if (dp->flags & CACHE_FLAG_TRANSMITTED) 02892 strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1); 02893 if (dp->flags & CACHE_FLAG_MATCHMORE) 02894 strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1); 02895 if (dp->flags & CACHE_FLAG_UNKNOWN) 02896 strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1); 02897 /* Trim trailing pipe */ 02898 if (!ast_strlen_zero(tmp)) { 02899 tmp[strlen(tmp) - 1] = '\0'; 02900 } else { 02901 ast_copy_string(tmp, "(none)", sizeof(tmp)); 02902 } 02903 y = 0; 02904 pc = strchr(dp->peercontext, '@'); 02905 if (!pc) { 02906 pc = dp->peercontext; 02907 } else { 02908 pc++; 02909 } 02910 for (x = 0; x < ARRAY_LEN(dp->waiters); x++) { 02911 if (dp->waiters[x] > -1) 02912 y++; 02913 } 02914 if (s > 0) { 02915 ast_cli(a->fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp); 02916 } else { 02917 ast_cli(a->fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp); 02918 } 02919 } 02920 02921 AST_LIST_LOCK(&dpcache); 02922 02923 return CLI_SUCCESS; 02924 }
static char* handle_cli_iax2_show_channels | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5579 of file chan_iax2.c.
References ast_cli_args::argc, ARRAY_LEN, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, jb_info::current, ast_cli_args::fd, FORMAT, FORMAT2, iax_frame_subclass2str(), IAX_USEJITTERBUF, jb_getinfo(), jb_info::jitter, MARK_IAX_SUBCLASS_TX, jb_info::min, S_OR, and ast_cli_entry::usage.
05580 { 05581 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s %s %9s\n" 05582 #define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s %s%s %3s%s\n" 05583 #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" 05584 int x; 05585 int numchans = 0; 05586 char first_message[10] = { 0, }; 05587 char last_message[10] = { 0, }; 05588 05589 switch (cmd) { 05590 case CLI_INIT: 05591 e->command = "iax2 show channels"; 05592 e->usage = 05593 "Usage: iax2 show channels\n" 05594 " Lists all currently active IAX channels.\n"; 05595 return NULL; 05596 case CLI_GENERATE: 05597 return NULL; 05598 } 05599 05600 if (a->argc != 3) 05601 return CLI_SHOWUSAGE; 05602 ast_cli(a->fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format", "FirstMsg", "LastMsg"); 05603 for (x = 0; x < ARRAY_LEN(iaxs); x++) { 05604 ast_mutex_lock(&iaxsl[x]); 05605 if (iaxs[x]) { 05606 int lag, jitter, localdelay; 05607 jb_info jbinfo; 05608 if (ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 05609 jb_getinfo(iaxs[x]->jb, &jbinfo); 05610 jitter = jbinfo.jitter; 05611 localdelay = jbinfo.current - jbinfo.min; 05612 } else { 05613 jitter = -1; 05614 localdelay = 0; 05615 } 05616 05617 iax_frame_subclass2str(iaxs[x]->first_iax_message & ~MARK_IAX_SUBCLASS_TX, first_message, sizeof(first_message)); 05618 iax_frame_subclass2str(iaxs[x]->last_iax_message & ~MARK_IAX_SUBCLASS_TX, last_message, sizeof(last_message)); 05619 lag = iaxs[x]->remote_rr.delay; 05620 ast_cli(a->fd, FORMAT, 05621 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 05622 ast_inet_ntoa(iaxs[x]->addr.sin_addr), 05623 S_OR(iaxs[x]->username, "(None)"), 05624 iaxs[x]->callno, iaxs[x]->peercallno, 05625 iaxs[x]->oseqno, iaxs[x]->iseqno, 05626 lag, 05627 jitter, 05628 localdelay, 05629 ast_getformatname(iaxs[x]->voiceformat), 05630 (iaxs[x]->first_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 05631 first_message, 05632 (iaxs[x]->last_iax_message & MARK_IAX_SUBCLASS_TX) ? "Tx:" : "Rx:", 05633 last_message); 05634 numchans++; 05635 } 05636 ast_mutex_unlock(&iaxsl[x]); 05637 } 05638 ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 05639 return CLI_SUCCESS; 05640 #undef FORMAT 05641 #undef FORMAT2 05642 #undef FORMATB 05643 }
static char* handle_cli_iax2_show_firmware | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5430 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, ast_cli_args::fd, iax_firmware::fwh, iax_firmware::list, ast_cli_entry::usage, and ast_iax2_firmware_header::version.
05431 { 05432 struct iax_firmware *cur = NULL; 05433 05434 switch (cmd) { 05435 case CLI_INIT: 05436 e->command = "iax2 show firmware"; 05437 e->usage = 05438 "Usage: iax2 show firmware\n" 05439 " Lists all known IAX firmware images.\n"; 05440 return NULL; 05441 case CLI_GENERATE: 05442 return NULL; 05443 } 05444 05445 if (a->argc != 3 && a->argc != 4) 05446 return CLI_SHOWUSAGE; 05447 05448 ast_cli(a->fd, "%-15.15s %-15.15s %-15.15s\n", "Device", "Version", "Size"); 05449 AST_LIST_LOCK(&firmwares); 05450 AST_LIST_TRAVERSE(&firmwares, cur, list) { 05451 if ((a->argc == 3) || (!strcasecmp(a->argv[3], (char *) cur->fwh->devname))) { 05452 ast_cli(a->fd, "%-15.15s %-15d %-15d\n", cur->fwh->devname, 05453 ntohs(cur->fwh->version), (int)ntohl(cur->fwh->datalen)); 05454 } 05455 } 05456 AST_LIST_UNLOCK(&firmwares); 05457 05458 return CLI_SUCCESS; 05459 }
static char* handle_cli_iax2_show_netstats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5729 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), ast_cli_netstats(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
05730 { 05731 int numchans = 0; 05732 05733 switch (cmd) { 05734 case CLI_INIT: 05735 e->command = "iax2 show netstats"; 05736 e->usage = 05737 "Usage: iax2 show netstats\n" 05738 " Lists network status for all currently active IAX channels.\n"; 05739 return NULL; 05740 case CLI_GENERATE: 05741 return NULL; 05742 } 05743 if (a->argc != 3) 05744 return CLI_SHOWUSAGE; 05745 ast_cli(a->fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); 05746 ast_cli(a->fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts FirstMsg LastMsg\n"); 05747 numchans = ast_cli_netstats(NULL, a->fd, 1); 05748 ast_cli(a->fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 05749 return CLI_SUCCESS; 05750 }
static char* handle_cli_iax2_show_peer | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show one peer in detail.
Definition at line 2675 of file chan_iax2.c.
References iax2_peer::addr, ast_cli_args::argc, ast_cli_args::argv, ast_callerid_merge(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, iax2_peer::capability, iax2_peer::cid_name, iax2_peer::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_show_peer(), iax2_peer::context, iax2_peer::defaddr, iax2_peer::expire, ast_cli_args::fd, find_peer(), iax2_peer::ha, IAX_DYNAMIC, IAX_TRUNK, ast_cli_args::line, iax2_peer::mailbox, ast_cli_args::n, iax2_peer::name, peer_status(), peer_unref(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, ast_cli_args::pos, iax2_peer::prefs, iax2_peer::secret, iax2_peer::smoothing, status, ast_cli_entry::usage, iax2_peer::username, and ast_cli_args::word.
02676 { 02677 char status[30]; 02678 char cbuf[256]; 02679 struct iax2_peer *peer; 02680 char codec_buf[512]; 02681 int x = 0, codec = 0, load_realtime = 0; 02682 02683 switch (cmd) { 02684 case CLI_INIT: 02685 e->command = "iax2 show peer"; 02686 e->usage = 02687 "Usage: iax2 show peer <name>\n" 02688 " Display details on specific IAX peer\n"; 02689 return NULL; 02690 case CLI_GENERATE: 02691 return complete_iax2_show_peer(a->line, a->word, a->pos, a->n); 02692 } 02693 02694 if (a->argc < 4) 02695 return CLI_SHOWUSAGE; 02696 02697 load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? 1 : 0; 02698 02699 peer = find_peer(a->argv[3], load_realtime); 02700 if (peer) { 02701 ast_cli(a->fd, "\n\n"); 02702 ast_cli(a->fd, " * Name : %s\n", peer->name); 02703 ast_cli(a->fd, " Secret : %s\n", ast_strlen_zero(peer->secret) ? "<Not set>" : "<Set>"); 02704 ast_cli(a->fd, " Context : %s\n", peer->context); 02705 ast_cli(a->fd, " Mailbox : %s\n", peer->mailbox); 02706 ast_cli(a->fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No"); 02707 ast_cli(a->fd, " Trunk : %s\n", ast_test_flag(peer, IAX_TRUNK) ? "Yes" : "No"); 02708 ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 02709 ast_cli(a->fd, " Expire : %d\n", peer->expire); 02710 ast_cli(a->fd, " ACL : %s\n", (peer->ha ? "Yes" : "No")); 02711 ast_cli(a->fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port)); 02712 ast_cli(a->fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 02713 ast_cli(a->fd, " Username : %s\n", peer->username); 02714 ast_cli(a->fd, " Codecs : "); 02715 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 02716 ast_cli(a->fd, "%s\n", codec_buf); 02717 02718 ast_cli(a->fd, " Codec Order : ("); 02719 for(x = 0; x < 32 ; x++) { 02720 codec = ast_codec_pref_index(&peer->prefs,x); 02721 if(!codec) 02722 break; 02723 ast_cli(a->fd, "%s", ast_getformatname(codec)); 02724 if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) 02725 ast_cli(a->fd, "|"); 02726 } 02727 02728 if (!x) 02729 ast_cli(a->fd, "none"); 02730 ast_cli(a->fd, ")\n"); 02731 02732 ast_cli(a->fd, " Status : "); 02733 peer_status(peer, status, sizeof(status)); 02734 ast_cli(a->fd, "%s\n",status); 02735 ast_cli(a->fd, " Qualify : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off"); 02736 ast_cli(a->fd, "\n"); 02737 peer_unref(peer); 02738 } else { 02739 ast_cli(a->fd, "Peer %s not found.\n", a->argv[3]); 02740 ast_cli(a->fd, "\n"); 02741 } 02742 02743 return CLI_SUCCESS; 02744 }
static char* handle_cli_iax2_show_peers | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5398 of file chan_iax2.c.
References __iax2_show_peers(), ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and ast_cli_entry::usage.
05399 { 05400 switch (cmd) { 05401 case CLI_INIT: 05402 e->command = "iax2 show peers"; 05403 e->usage = 05404 "Usage: iax2 show peers [registered] [like <pattern>]\n" 05405 " Lists all known IAX2 peers.\n" 05406 " Optional 'registered' argument lists only peers with known addresses.\n" 05407 " Optional regular expression pattern is used to filter the peer list.\n"; 05408 return NULL; 05409 case CLI_GENERATE: 05410 return NULL; 05411 } 05412 05413 switch (__iax2_show_peers(0, a->fd, NULL, a->argc, a->argv)) { 05414 case RESULT_SHOWUSAGE: 05415 return CLI_SHOWUSAGE; 05416 case RESULT_FAILURE: 05417 return CLI_FAILURE; 05418 default: 05419 return CLI_SUCCESS; 05420 } 05421 }
static char* handle_cli_iax2_show_registry | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5538 of file chan_iax2.c.
References iax2_registry::addr, ast_cli_args::argc, ast_cli(), ast_copy_string(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, iax2_registry::dnsmgr, iax2_registry::entry, ast_cli_args::fd, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), iax2_registry::us, ast_cli_entry::usage, and iax2_registry::username.
05539 { 05540 #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" 05541 #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" 05542 struct iax2_registry *reg = NULL; 05543 char host[80]; 05544 char perceived[80]; 05545 int counter = 0; 05546 05547 switch (cmd) { 05548 case CLI_INIT: 05549 e->command = "iax2 show registry"; 05550 e->usage = 05551 "Usage: iax2 show registry\n" 05552 " Lists all registration requests and status.\n"; 05553 return NULL; 05554 case CLI_GENERATE: 05555 return NULL; 05556 } 05557 if (a->argc != 3) 05558 return CLI_SHOWUSAGE; 05559 ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); 05560 AST_LIST_LOCK(®istrations); 05561 AST_LIST_TRAVERSE(®istrations, reg, entry) { 05562 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); 05563 if (reg->us.sin_addr.s_addr) 05564 snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 05565 else 05566 ast_copy_string(perceived, "<Unregistered>", sizeof(perceived)); 05567 ast_cli(a->fd, FORMAT, host, 05568 (reg->dnsmgr) ? "Y" : "N", 05569 reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); 05570 counter++; 05571 } 05572 AST_LIST_UNLOCK(®istrations); 05573 ast_cli(a->fd, "%d IAX2 registrations.\n", counter); 05574 return CLI_SUCCESS; 05575 #undef FORMAT 05576 #undef FORMAT2 05577 }
static char* handle_cli_iax2_show_stats | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2771 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, iax_frame::final, iax_get_frames(), iax_get_iframes(), iax_get_oframes(), iax2_trunk_peer::list, iax_frame::retries, and ast_cli_entry::usage.
02772 { 02773 struct iax_frame *cur; 02774 int cnt = 0, dead = 0, final = 0; 02775 02776 switch (cmd) { 02777 case CLI_INIT: 02778 e->command = "iax2 show stats"; 02779 e->usage = 02780 "Usage: iax2 show stats\n" 02781 " Display statistics on IAX channel driver.\n"; 02782 return NULL; 02783 case CLI_GENERATE: 02784 return NULL; 02785 } 02786 02787 if (a->argc != 3) 02788 return CLI_SHOWUSAGE; 02789 02790 AST_LIST_LOCK(&frame_queue); 02791 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 02792 if (cur->retries < 0) 02793 dead++; 02794 if (cur->final) 02795 final++; 02796 cnt++; 02797 } 02798 AST_LIST_UNLOCK(&frame_queue); 02799 02800 ast_cli(a->fd, " IAX Statistics\n"); 02801 ast_cli(a->fd, "---------------------\n"); 02802 ast_cli(a->fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); 02803 ast_cli(a->fd, "%d timed and %d untimed transmits; MTU %d/%d/%d\n", trunk_timed, trunk_untimed, 02804 trunk_maxmtu, trunk_nmaxmtu, global_max_trunk_mtu); 02805 ast_cli(a->fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); 02806 02807 trunk_timed = trunk_untimed = 0; 02808 if (trunk_maxmtu > trunk_nmaxmtu) 02809 trunk_nmaxmtu = trunk_maxmtu; 02810 02811 return CLI_SUCCESS; 02812 }
static char* handle_cli_iax2_show_threads | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5262 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, IAX_THREAD_TYPE_DYNAMIC, iaxthreadcount, iax2_thread::list, thread, and ast_cli_entry::usage.
05263 { 05264 struct iax2_thread *thread = NULL; 05265 time_t t; 05266 int threadcount = 0, dynamiccount = 0; 05267 char type; 05268 05269 switch (cmd) { 05270 case CLI_INIT: 05271 e->command = "iax2 show threads"; 05272 e->usage = 05273 "Usage: iax2 show threads\n" 05274 " Lists status of IAX helper threads\n"; 05275 return NULL; 05276 case CLI_GENERATE: 05277 return NULL; 05278 } 05279 if (a->argc != 3) 05280 return CLI_SHOWUSAGE; 05281 05282 ast_cli(a->fd, "IAX2 Thread Information\n"); 05283 time(&t); 05284 ast_cli(a->fd, "Idle Threads:\n"); 05285 AST_LIST_LOCK(&idle_list); 05286 AST_LIST_TRAVERSE(&idle_list, thread, list) { 05287 #ifdef DEBUG_SCHED_MULTITHREAD 05288 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n", 05289 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 05290 #else 05291 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n", 05292 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 05293 #endif 05294 threadcount++; 05295 } 05296 AST_LIST_UNLOCK(&idle_list); 05297 ast_cli(a->fd, "Active Threads:\n"); 05298 AST_LIST_LOCK(&active_list); 05299 AST_LIST_TRAVERSE(&active_list, thread, list) { 05300 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) 05301 type = 'D'; 05302 else 05303 type = 'P'; 05304 #ifdef DEBUG_SCHED_MULTITHREAD 05305 ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d, func='%s'\n", 05306 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 05307 #else 05308 ast_cli(a->fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 05309 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 05310 #endif 05311 threadcount++; 05312 } 05313 AST_LIST_UNLOCK(&active_list); 05314 ast_cli(a->fd, "Dynamic Threads:\n"); 05315 AST_LIST_LOCK(&dynamic_list); 05316 AST_LIST_TRAVERSE(&dynamic_list, thread, list) { 05317 #ifdef DEBUG_SCHED_MULTITHREAD 05318 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d, func='%s'\n", 05319 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 05320 #else 05321 ast_cli(a->fd, "Thread %d: state=%d, update=%d, actions=%d\n", 05322 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 05323 #endif 05324 dynamiccount++; 05325 } 05326 AST_LIST_UNLOCK(&dynamic_list); 05327 ast_cli(a->fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount); 05328 return CLI_SUCCESS; 05329 }
static char* handle_cli_iax2_show_users | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5061 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_strlen_zero(), ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, FORMAT2, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, ast_cli_entry::usage, user, and user_unref().
05062 { 05063 regex_t regexbuf; 05064 int havepattern = 0; 05065 05066 #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" 05067 #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" 05068 05069 struct iax2_user *user = NULL; 05070 char auth[90]; 05071 char *pstr = ""; 05072 struct ao2_iterator i; 05073 05074 switch (cmd) { 05075 case CLI_INIT: 05076 e->command = "iax2 show users [like]"; 05077 e->usage = 05078 "Usage: iax2 show users [like <pattern>]\n" 05079 " Lists all known IAX2 users.\n" 05080 " Optional regular expression pattern is used to filter the user list.\n"; 05081 return NULL; 05082 case CLI_GENERATE: 05083 return NULL; 05084 } 05085 05086 switch (a->argc) { 05087 case 5: 05088 if (!strcasecmp(a->argv[3], "like")) { 05089 if (regcomp(®exbuf, a->argv[4], REG_EXTENDED | REG_NOSUB)) 05090 return CLI_SHOWUSAGE; 05091 havepattern = 1; 05092 } else 05093 return CLI_SHOWUSAGE; 05094 case 3: 05095 break; 05096 default: 05097 return CLI_SHOWUSAGE; 05098 } 05099 05100 ast_cli(a->fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); 05101 i = ao2_iterator_init(users, 0); 05102 for (user = ao2_iterator_next(&i); user; 05103 user_unref(user), user = ao2_iterator_next(&i)) { 05104 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) 05105 continue; 05106 05107 if (!ast_strlen_zero(user->secret)) { 05108 ast_copy_string(auth,user->secret, sizeof(auth)); 05109 } else if (!ast_strlen_zero(user->inkeys)) { 05110 snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys); 05111 } else 05112 ast_copy_string(auth, "-no secret-", sizeof(auth)); 05113 05114 if(ast_test_flag(user,IAX_CODEC_NOCAP)) 05115 pstr = "REQ Only"; 05116 else if(ast_test_flag(user,IAX_CODEC_NOPREFS)) 05117 pstr = "Disabled"; 05118 else 05119 pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host"; 05120 05121 ast_cli(a->fd, FORMAT2, user->name, auth, user->authmethods, 05122 user->contexts ? user->contexts->context : context, 05123 user->ha ? "Yes" : "No", pstr); 05124 } 05125 05126 if (havepattern) 05127 regfree(®exbuf); 05128 05129 return CLI_SUCCESS; 05130 #undef FORMAT 05131 #undef FORMAT2 05132 }
static char* handle_cli_iax2_test_losspct | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2561 of file chan_iax2.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
02562 { 02563 switch (cmd) { 02564 case CLI_INIT: 02565 e->command = "iax2 test losspct"; 02566 e->usage = 02567 "Usage: iax2 test losspct <percentage>\n" 02568 " For testing, throws away <percentage> percent of incoming packets\n"; 02569 return NULL; 02570 case CLI_GENERATE: 02571 return NULL; 02572 } 02573 if (a->argc != 4) 02574 return CLI_SHOWUSAGE; 02575 02576 test_losspct = atoi(a->argv[3]); 02577 02578 return CLI_SUCCESS; 02579 }
static char* handle_cli_iax2_unregister | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 5331 of file chan_iax2.c.
References ao2_find(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_iax2_unregister(), iax2_peer::expire, expire_registry(), ast_cli_args::fd, find_peer(), ast_cli_args::line, ast_cli_args::n, iax2_peer::name, OBJ_POINTER, peer_ref(), peer_unref(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
05332 { 05333 struct iax2_peer *p; 05334 05335 switch (cmd) { 05336 case CLI_INIT: 05337 e->command = "iax2 unregister"; 05338 e->usage = 05339 "Usage: iax2 unregister <peername>\n" 05340 " Unregister (force expiration) an IAX2 peer from the registry.\n"; 05341 return NULL; 05342 case CLI_GENERATE: 05343 return complete_iax2_unregister(a->line, a->word, a->pos, a->n); 05344 } 05345 05346 if (a->argc != 3) 05347 return CLI_SHOWUSAGE; 05348 05349 p = find_peer(a->argv[2], 1); 05350 if (p) { 05351 if (p->expire > 0) { 05352 struct iax2_peer tmp_peer = { 05353 .name = a->argv[2], 05354 }; 05355 struct iax2_peer *peer; 05356 05357 peer = ao2_find(peers, &tmp_peer, OBJ_POINTER); 05358 if (peer) { 05359 expire_registry(peer_ref(peer)); /* will release its own reference when done */ 05360 peer_unref(peer); /* ref from ao2_find() */ 05361 ast_cli(a->fd, "Peer %s unregistered\n", a->argv[2]); 05362 } else { 05363 ast_cli(a->fd, "Peer %s not found\n", a->argv[2]); 05364 } 05365 } else { 05366 ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]); 05367 } 05368 } else { 05369 ast_cli(a->fd, "Peer unknown: %s. Not unregistered\n", a->argv[2]); 05370 } 05371 return CLI_SUCCESS; 05372 }
static void handle_deferred_full_frames | ( | struct iax2_thread * | thread | ) | [static] |
Handle any deferred full frames for this thread.
Definition at line 7903 of file chan_iax2.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), iax2_pkt_buf::buf, iax2_pkt_buf::entry, iax2_pkt_buf::len, socket_process(), and thread.
07904 { 07905 struct iax2_pkt_buf *pkt_buf; 07906 07907 ast_mutex_lock(&thread->lock); 07908 07909 while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) { 07910 ast_mutex_unlock(&thread->lock); 07911 07912 thread->buf = pkt_buf->buf; 07913 thread->buf_len = pkt_buf->len; 07914 thread->buf_size = pkt_buf->len + 1; 07915 07916 socket_process(thread); 07917 07918 thread->buf = NULL; 07919 ast_free(pkt_buf); 07920 07921 ast_mutex_lock(&thread->lock); 07922 } 07923 07924 ast_mutex_unlock(&thread->lock); 07925 }
static int handle_error | ( | void | ) | [static] |
Definition at line 2228 of file chan_iax2.c.
References ast_inet_ntoa(), ast_log(), errno, LOG_WARNING, and netsocket.
Referenced by send_packet(), socket_read(), and transmit_trunk().
02229 { 02230 /* XXX Ideally we should figure out why an error occurred and then abort those 02231 rather than continuing to try. Unfortunately, the published interface does 02232 not seem to work XXX */ 02233 #if 0 02234 struct sockaddr_in *sin; 02235 int res; 02236 struct msghdr m; 02237 struct sock_extended_err e; 02238 m.msg_name = NULL; 02239 m.msg_namelen = 0; 02240 m.msg_iov = NULL; 02241 m.msg_control = &e; 02242 m.msg_controllen = sizeof(e); 02243 m.msg_flags = 0; 02244 res = recvmsg(netsocket, &m, MSG_ERRQUEUE); 02245 if (res < 0) 02246 ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno)); 02247 else { 02248 if (m.msg_controllen) { 02249 sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e); 02250 if (sin) 02251 ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr)); 02252 else 02253 ast_log(LOG_WARNING, "No address detected??\n"); 02254 } else { 02255 ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno)); 02256 } 02257 } 02258 #endif 02259 return 0; 02260 }
static int iax2_ack_registry | ( | struct iax_ies * | ies, | |
struct sockaddr_in * | sin, | |||
int | callno | |||
) | [static] |
Acknowledgment received for OUR registration.
Definition at line 6869 of file chan_iax2.c.
References iax2_registry::addr, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_verb, EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iax2_sched_replace(), ies, inaddrcmp(), LOG_WARNING, manager_event, iax2_registry::messages, iax2_registry::refresh, REG_STATE_REGISTERED, iax2_registry::regstate, sched, and iax2_registry::us.
Referenced by socket_process().
06870 { 06871 struct iax2_registry *reg; 06872 /* Start pessimistic */ 06873 char peer[256] = ""; 06874 char msgstatus[60]; 06875 int refresh = 60; 06876 char ourip[256] = "<Unspecified>"; 06877 struct sockaddr_in oldus; 06878 struct sockaddr_in us; 06879 int oldmsgs; 06880 06881 memset(&us, 0, sizeof(us)); 06882 if (ies->apparent_addr) 06883 memmove(&us, ies->apparent_addr, sizeof(us)); 06884 if (ies->username) 06885 ast_copy_string(peer, ies->username, sizeof(peer)); 06886 if (ies->refresh) 06887 refresh = ies->refresh; 06888 if (ies->calling_number) { 06889 /* We don't do anything with it really, but maybe we should */ 06890 } 06891 reg = iaxs[callno]->reg; 06892 if (!reg) { 06893 ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer); 06894 return -1; 06895 } 06896 memcpy(&oldus, ®->us, sizeof(oldus)); 06897 oldmsgs = reg->messages; 06898 if (inaddrcmp(®->addr, sin)) { 06899 ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 06900 return -1; 06901 } 06902 memcpy(®->us, &us, sizeof(reg->us)); 06903 if (ies->msgcount >= 0) 06904 reg->messages = ies->msgcount & 0xffff; /* only low 16 bits are used in the transmission of the IE */ 06905 /* always refresh the registration at the interval requested by the server 06906 we are registering to 06907 */ 06908 reg->refresh = refresh; 06909 reg->expire = iax2_sched_replace(reg->expire, sched, 06910 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 06911 if (inaddrcmp(&oldus, ®->us) || (reg->messages != oldmsgs)) { 06912 if (reg->messages > 255) 06913 snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8); 06914 else if (reg->messages > 1) 06915 snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages); 06916 else if (reg->messages > 0) 06917 ast_copy_string(msgstatus, " with 1 new message waiting\n", sizeof(msgstatus)); 06918 else 06919 ast_copy_string(msgstatus, " with no messages waiting\n", sizeof(msgstatus)); 06920 snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 06921 ast_verb(3, "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); 06922 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); 06923 } 06924 reg->regstate = REG_STATE_REGISTERED; 06925 return 0; 06926 }
static void iax2_ami_channelupdate | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Send manager event at call setup to link between Asterisk channel name and IAX2 call identifiers.
Definition at line 988 of file chan_iax2.c.
References chan_iax2_pvt::callno, EVENT_FLAG_SYSTEM, manager_event, ast_channel::name, chan_iax2_pvt::owner, chan_iax2_pvt::peer, and chan_iax2_pvt::peercallno.
Referenced by ast_iax2_new(), and iax2_answer().
00989 { 00990 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 00991 "Channel: %s\r\nChanneltype: IAX2\r\nIAX2-callno-local: %d\r\nIAX2-callno-remote: %d\r\nIAX2-peer: %s\r\n", 00992 pvt->owner ? pvt->owner->name : "", 00993 pvt->callno, pvt->peercallno, pvt->peer ? pvt->peer : ""); 00994 }
static int iax2_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 4148 of file chan_iax2.c.
References AST_CONTROL_ANSWER, ast_debug, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), iax2_ami_channelupdate(), PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
04149 { 04150 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04151 ast_debug(1, "Answering IAX2 call\n"); 04152 ast_mutex_lock(&iaxsl[callno]); 04153 if (iaxs[callno]) 04154 iax2_ami_channelupdate(iaxs[callno]); 04155 ast_mutex_unlock(&iaxsl[callno]); 04156 return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); 04157 }
static int iax2_append_register | ( | const char * | hostname, | |
const char * | username, | |||
const char * | secret, | |||
const char * | porta | |||
) | [static] |
Definition at line 6928 of file chan_iax2.c.
References ast_calloc, ast_copy_string(), ast_dnsmgr_lookup(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, iax2_registry::entry, IAX_DEFAULT_PORTNO, and IAX_DEFAULT_REG_EXPIRE.
Referenced by iax2_register().
06930 { 06931 struct iax2_registry *reg; 06932 06933 if (!(reg = ast_calloc(1, sizeof(*reg)))) 06934 return -1; 06935 06936 if (ast_dnsmgr_lookup(hostname, ®->addr.sin_addr, ®->dnsmgr) < 0) { 06937 ast_free(reg); 06938 return -1; 06939 } 06940 06941 ast_copy_string(reg->username, username, sizeof(reg->username)); 06942 06943 if (secret) 06944 ast_copy_string(reg->secret, secret, sizeof(reg->secret)); 06945 06946 reg->expire = -1; 06947 reg->refresh = IAX_DEFAULT_REG_EXPIRE; 06948 reg->addr.sin_family = AF_INET; 06949 reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); 06950 06951 AST_LIST_LOCK(®istrations); 06952 AST_LIST_INSERT_HEAD(®istrations, reg, entry); 06953 AST_LIST_UNLOCK(®istrations); 06954 06955 return 0; 06956 }
static enum ast_bridge_result iax2_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
int | flags, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc, | |||
int | timeoutms | |||
) | [static] |
Definition at line 3989 of file chan_iax2.c.
References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_mutex_lock(), ast_mutex_unlock(), ast_verb, f, iax2_tech, lock_both(), PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, tv, and unlock_both().
03990 { 03991 struct ast_channel *cs[3]; 03992 struct ast_channel *who, *other; 03993 int to = -1; 03994 int res = -1; 03995 int transferstarted=0; 03996 struct ast_frame *f; 03997 unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt); 03998 unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt); 03999 struct timeval waittimer = {0, 0}, tv; 04000 04001 /* We currently do not support native bridging if a timeoutms value has been provided */ 04002 if (timeoutms > 0) { 04003 return AST_BRIDGE_FAILED; 04004 } 04005 04006 timeoutms = -1; 04007 04008 lock_both(callno0, callno1); 04009 if (!iaxs[callno0] || !iaxs[callno1]) { 04010 unlock_both(callno0, callno1); 04011 return AST_BRIDGE_FAILED; 04012 } 04013 /* Put them in native bridge mode */ 04014 if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) { 04015 iaxs[callno0]->bridgecallno = callno1; 04016 iaxs[callno1]->bridgecallno = callno0; 04017 } 04018 /* If the bridge got retried, don't queue up more packets - the transfer request will be retransmitted as necessary */ 04019 if (iaxs[callno0]->transferring && iaxs[callno1]->transferring) { 04020 transferstarted = 1; 04021 } 04022 unlock_both(callno0, callno1); 04023 04024 /* If not, try to bridge until we can execute a transfer, if we can */ 04025 cs[0] = c0; 04026 cs[1] = c1; 04027 for (/* ever */;;) { 04028 /* Check in case we got masqueraded into */ 04029 if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) { 04030 ast_verb(3, "Can't masquerade, we're different...\n"); 04031 /* Remove from native mode */ 04032 if (c0->tech == &iax2_tech) { 04033 ast_mutex_lock(&iaxsl[callno0]); 04034 iaxs[callno0]->bridgecallno = 0; 04035 ast_mutex_unlock(&iaxsl[callno0]); 04036 } 04037 if (c1->tech == &iax2_tech) { 04038 ast_mutex_lock(&iaxsl[callno1]); 04039 iaxs[callno1]->bridgecallno = 0; 04040 ast_mutex_unlock(&iaxsl[callno1]); 04041 } 04042 return AST_BRIDGE_FAILED_NOWARN; 04043 } 04044 if (c0->nativeformats != c1->nativeformats) { 04045 char buf0[255]; 04046 char buf1[255]; 04047 ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats); 04048 ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats); 04049 ast_verb(3, "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1); 04050 /* Remove from native mode */ 04051 lock_both(callno0, callno1); 04052 if (iaxs[callno0]) 04053 iaxs[callno0]->bridgecallno = 0; 04054 if (iaxs[callno1]) 04055 iaxs[callno1]->bridgecallno = 0; 04056 unlock_both(callno0, callno1); 04057 return AST_BRIDGE_FAILED_NOWARN; 04058 } 04059 /* check if transfered and if we really want native bridging */ 04060 if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) { 04061 /* Try the transfer */ 04062 if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) || 04063 ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA))) 04064 ast_log(LOG_WARNING, "Unable to start the transfer\n"); 04065 transferstarted = 1; 04066 } 04067 if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) { 04068 /* Call has been transferred. We're no longer involved */ 04069 tv = ast_tvnow(); 04070 if (ast_tvzero(waittimer)) { 04071 waittimer = tv; 04072 } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { 04073 c0->_softhangup |= AST_SOFTHANGUP_DEV; 04074 c1->_softhangup |= AST_SOFTHANGUP_DEV; 04075 *fo = NULL; 04076 *rc = c0; 04077 res = AST_BRIDGE_COMPLETE; 04078 break; 04079 } 04080 } 04081 to = 1000; 04082 who = ast_waitfor_n(cs, 2, &to); 04083 if (timeoutms > -1) { 04084 timeoutms -= (1000 - to); 04085 if (timeoutms < 0) 04086 timeoutms = 0; 04087 } 04088 if (!who) { 04089 if (!timeoutms) { 04090 res = AST_BRIDGE_RETRY; 04091 break; 04092 } 04093 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 04094 res = AST_BRIDGE_FAILED; 04095 break; 04096 } 04097 continue; 04098 } 04099 f = ast_read(who); 04100 if (!f) { 04101 *fo = NULL; 04102 *rc = who; 04103 res = AST_BRIDGE_COMPLETE; 04104 break; 04105 } 04106 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS) && (f->subclass != AST_CONTROL_SRCUPDATE)) { 04107 *fo = f; 04108 *rc = who; 04109 res = AST_BRIDGE_COMPLETE; 04110 break; 04111 } 04112 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 04113 if ((f->frametype == AST_FRAME_VOICE) || 04114 (f->frametype == AST_FRAME_TEXT) || 04115 (f->frametype == AST_FRAME_VIDEO) || 04116 (f->frametype == AST_FRAME_IMAGE) || 04117 (f->frametype == AST_FRAME_DTMF) || 04118 (f->frametype == AST_FRAME_CONTROL)) { 04119 /* monitored dtmf take out of the bridge. 04120 * check if we monitor the specific source. 04121 */ 04122 int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1; 04123 if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) { 04124 *rc = who; 04125 *fo = f; 04126 res = AST_BRIDGE_COMPLETE; 04127 /* Remove from native mode */ 04128 break; 04129 } 04130 /* everything else goes to the other side */ 04131 ast_write(other, f); 04132 } 04133 ast_frfree(f); 04134 /* Swap who gets priority */ 04135 cs[2] = cs[0]; 04136 cs[0] = cs[1]; 04137 cs[1] = cs[2]; 04138 } 04139 lock_both(callno0, callno1); 04140 if(iaxs[callno0]) 04141 iaxs[callno0]->bridgecallno = 0; 04142 if(iaxs[callno1]) 04143 iaxs[callno1]->bridgecallno = 0; 04144 unlock_both(callno0, callno1); 04145 return res; 04146 }
static int iax2_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 3642 of file chan_iax2.c.
References ast_channel::_state, ast_channel::adsicpe, ast_channel_datastore_find(), ast_copy_string(), ast_debug, AST_FRAME_IAX, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PRES_NUMBER_NOT_AVAILABLE, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_var_name(), ast_var_value(), auto_congest(), CALLNO_TO_PTR, capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, create_addr(), ast_datastore::data, iax2_datetime(), iax2_sched_add(), iax2_variable_datastore_info, IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_raw(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_OSPTOKEN, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VARIABLE, IAX_IE_VERSION, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPTOKEN_SIZE, IAX_PROTO_VERSION, IAX_SENDANI, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, parse_dial_string(), PTR_TO_CALLNO, sched, secret, send_command(), ast_channel::tech_pvt, and var.
03643 { 03644 struct sockaddr_in sin; 03645 char *l=NULL, *n=NULL, *tmpstr; 03646 struct iax_ie_data ied; 03647 char *defaultrdest = "s"; 03648 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03649 struct parsed_dial_string pds; 03650 struct create_addr_info cai; 03651 struct ast_var_t *var; 03652 struct ast_datastore *variablestore = ast_channel_datastore_find(c, &iax2_variable_datastore_info, NULL); 03653 const char* osp_token_ptr; 03654 unsigned int osp_token_length; 03655 unsigned char osp_block_index; 03656 unsigned int osp_block_length; 03657 unsigned char osp_buffer[256]; 03658 03659 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 03660 ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); 03661 return -1; 03662 } 03663 03664 memset(&cai, 0, sizeof(cai)); 03665 cai.encmethods = iax2_encryption; 03666 03667 memset(&pds, 0, sizeof(pds)); 03668 tmpstr = ast_strdupa(dest); 03669 parse_dial_string(tmpstr, &pds); 03670 03671 if (ast_strlen_zero(pds.peer)) { 03672 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", dest); 03673 return -1; 03674 } 03675 03676 if (!pds.exten) { 03677 pds.exten = defaultrdest; 03678 } 03679 03680 if (create_addr(pds.peer, c, &sin, &cai)) { 03681 ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); 03682 return -1; 03683 } 03684 03685 if (!pds.username && !ast_strlen_zero(cai.username)) 03686 pds.username = cai.username; 03687 if (!pds.password && !ast_strlen_zero(cai.secret)) 03688 pds.password = cai.secret; 03689 if (!pds.key && !ast_strlen_zero(cai.outkey)) 03690 pds.key = cai.outkey; 03691 if (!pds.context && !ast_strlen_zero(cai.peercontext)) 03692 pds.context = cai.peercontext; 03693 03694 /* Keep track of the context for outgoing calls too */ 03695 ast_copy_string(c->context, cai.context, sizeof(c->context)); 03696 03697 if (pds.port) 03698 sin.sin_port = htons(atoi(pds.port)); 03699 03700 l = c->cid.cid_num; 03701 n = c->cid.cid_name; 03702 03703 /* Now build request */ 03704 memset(&ied, 0, sizeof(ied)); 03705 03706 /* On new call, first IE MUST be IAX version of caller */ 03707 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 03708 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); 03709 if (pds.options && strchr(pds.options, 'a')) { 03710 /* Request auto answer */ 03711 iax_ie_append(&ied, IAX_IE_AUTOANSWER); 03712 } 03713 03714 iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); 03715 03716 if (l) { 03717 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); 03718 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03719 } else { 03720 if (n) 03721 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 03722 else 03723 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); 03724 } 03725 03726 iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); 03727 iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); 03728 03729 if (n) 03730 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); 03731 if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) 03732 iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); 03733 03734 if (!ast_strlen_zero(c->language)) 03735 iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); 03736 if (!ast_strlen_zero(c->cid.cid_dnid)) 03737 iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); 03738 if (!ast_strlen_zero(c->cid.cid_rdnis)) 03739 iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis); 03740 03741 if (pds.context) 03742 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); 03743 03744 if (pds.username) 03745 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 03746 03747 if (cai.encmethods) 03748 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); 03749 03750 ast_mutex_lock(&iaxsl[callno]); 03751 03752 if (!ast_strlen_zero(c->context)) 03753 ast_string_field_set(iaxs[callno], context, c->context); 03754 03755 if (pds.username) 03756 ast_string_field_set(iaxs[callno], username, pds.username); 03757 03758 iaxs[callno]->encmethods = cai.encmethods; 03759 03760 iaxs[callno]->adsi = cai.adsi; 03761 03762 ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret); 03763 ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest); 03764 03765 if (pds.key) 03766 ast_string_field_set(iaxs[callno], outkey, pds.key); 03767 if (pds.password) 03768 ast_string_field_set(iaxs[callno], secret, pds.password); 03769 03770 iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); 03771 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); 03772 iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); 03773 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); 03774 03775 if (iaxs[callno]->maxtime) { 03776 /* Initialize pingtime and auto-congest time */ 03777 iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; 03778 iaxs[callno]->initid = iax2_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno)); 03779 } else if (autokill) { 03780 iaxs[callno]->pingtime = autokill / 2; 03781 iaxs[callno]->initid = iax2_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); 03782 } 03783 03784 /* Check if there is an OSP token set by IAXCHANINFO function */ 03785 osp_token_ptr = iaxs[callno]->osptoken; 03786 if (!ast_strlen_zero(osp_token_ptr)) { 03787 if ((osp_token_length = strlen(osp_token_ptr)) <= IAX_MAX_OSPTOKEN_SIZE) { 03788 osp_block_index = 0; 03789 while (osp_token_length > 0) { 03790 osp_block_length = IAX_MAX_OSPBLOCK_SIZE < osp_token_length ? IAX_MAX_OSPBLOCK_SIZE : osp_token_length; 03791 osp_buffer[0] = osp_block_index; 03792 memcpy(osp_buffer + 1, osp_token_ptr, osp_block_length); 03793 iax_ie_append_raw(&ied, IAX_IE_OSPTOKEN, osp_buffer, osp_block_length + 1); 03794 osp_block_index++; 03795 osp_token_ptr += osp_block_length; 03796 osp_token_length -= osp_block_length; 03797 } 03798 } else 03799 ast_log(LOG_WARNING, "OSP token is too long\n"); 03800 } else if (iaxdebug) 03801 ast_debug(1, "OSP token is undefined\n"); 03802 03803 /* send the command using the appropriate socket for this peer */ 03804 iaxs[callno]->sockfd = cai.sockfd; 03805 03806 /* Add remote vars */ 03807 if (variablestore) { 03808 AST_LIST_HEAD(, ast_var_t) *variablelist = variablestore->data; 03809 ast_debug(1, "Found an IAX variable store on this channel\n"); 03810 AST_LIST_LOCK(variablelist); 03811 AST_LIST_TRAVERSE(variablelist, var, entries) { 03812 char tmp[256]; 03813 int i; 03814 ast_debug(1, "Found IAXVAR '%s' with value '%s' (to transmit)\n", ast_var_name(var), ast_var_value(var)); 03815 /* Automatically divide the value up into sized chunks */ 03816 for (i = 0; i < strlen(ast_var_value(var)); i += 255 - (strlen(ast_var_name(var)) + 1)) { 03817 snprintf(tmp, sizeof(tmp), "%s=%s", ast_var_name(var), ast_var_value(var) + i); 03818 iax_ie_append_str(&ied, IAX_IE_VARIABLE, tmp); 03819 } 03820 } 03821 AST_LIST_UNLOCK(variablelist); 03822 } 03823 03824 /* Transmit the string in a "NEW" request */ 03825 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 03826 03827 ast_mutex_unlock(&iaxsl[callno]); 03828 ast_setstate(c, AST_STATE_RINGING); 03829 03830 return 0; 03831 }
static int iax2_canmatch | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid, | |||
const char * | data | |||
) | [static] |
part of the IAX2 dial plan switch interface
Definition at line 11841 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_CANEXIST, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
11842 { 11843 int res = 0; 11844 struct iax2_dpcache *dp = NULL; 11845 #if 0 11846 ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 11847 #endif 11848 if ((priority != 1) && (priority != 2)) 11849 return 0; 11850 11851 AST_LIST_LOCK(&dpcache); 11852 if ((dp = find_cache(chan, data, context, exten, priority))) { 11853 if (dp->flags & CACHE_FLAG_CANEXIST) 11854 res = 1; 11855 } else { 11856 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 11857 } 11858 AST_LIST_UNLOCK(&dpcache); 11859 11860 return res; 11861 }
static unsigned int iax2_datetime | ( | const char * | tz | ) | [static] |
Definition at line 3549 of file chan_iax2.c.
References ast_localtime(), ast_strlen_zero(), ast_tvnow(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, and ast_tm::tm_year.
Referenced by iax2_call(), and update_registry().
03550 { 03551 struct timeval t = ast_tvnow(); 03552 struct ast_tm tm; 03553 unsigned int tmp; 03554 ast_localtime(&t, &tm, ast_strlen_zero(tz) ? NULL : tz); 03555 tmp = (tm.tm_sec >> 1) & 0x1f; /* 5 bits of seconds */ 03556 tmp |= (tm.tm_min & 0x3f) << 5; /* 6 bits of minutes */ 03557 tmp |= (tm.tm_hour & 0x1f) << 11; /* 5 bits of hours */ 03558 tmp |= (tm.tm_mday & 0x1f) << 16; /* 5 bits of day of month */ 03559 tmp |= ((tm.tm_mon + 1) & 0xf) << 21; /* 4 bits of month */ 03560 tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */ 03561 return tmp; 03562 }
static void iax2_destroy | ( | int | callno | ) | [static] |
Definition at line 2334 of file chan_iax2.c.
References ao2_ref(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), ast_tvnow(), chan_iax2_pvt::owner, chan_iax2_pvt::peercallno, remove_by_peercallno(), remove_by_transfercallno(), chan_iax2_pvt::transfercallno, and update_max_trunk().
Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __unload_module(), delete_users(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), peer_destructor(), scheduled_destroy(), and socket_process().
02335 { 02336 struct chan_iax2_pvt *pvt = NULL; 02337 struct ast_channel *owner = NULL; 02338 02339 retry: 02340 pvt = iaxs[callno]; 02341 lastused[callno] = ast_tvnow(); 02342 02343 owner = pvt ? pvt->owner : NULL; 02344 02345 if (owner) { 02346 if (ast_channel_trylock(owner)) { 02347 ast_debug(3, "Avoiding IAX destroy deadlock\n"); 02348 ast_mutex_unlock(&iaxsl[callno]); 02349 usleep(1); 02350 ast_mutex_lock(&iaxsl[callno]); 02351 goto retry; 02352 } 02353 } 02354 02355 if (!owner) { 02356 iaxs[callno] = NULL; 02357 } 02358 02359 if (pvt) { 02360 if (!owner) { 02361 pvt->owner = NULL; 02362 } else { 02363 /* If there's an owner, prod it to give up */ 02364 /* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup() 02365 * because we already hold the owner channel lock. */ 02366 ast_queue_hangup(owner); 02367 } 02368 02369 if (pvt->peercallno) { 02370 remove_by_peercallno(pvt); 02371 } 02372 02373 if (pvt->transfercallno) { 02374 remove_by_transfercallno(pvt); 02375 } 02376 02377 if (!owner) { 02378 ao2_ref(pvt, -1); 02379 pvt = NULL; 02380 } 02381 } 02382 02383 if (owner) { 02384 ast_channel_unlock(owner); 02385 } 02386 02387 if (callno & 0x4000) { 02388 update_max_trunk(); 02389 } 02390 }
static void iax2_destroy_helper | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1399 of file chan_iax2.c.
References ao2_find(), ast_atomic_fetchadd_int(), ast_clear_flag, AST_SCHED_DEL, ast_test_flag, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, iax2_user::name, OBJ_POINTER, chan_iax2_pvt::pingid, sched, user, user_unref(), and chan_iax2_pvt::username.
Referenced by iax2_predestroy(), pvt_destructor(), and stop_stuff().
01400 { 01401 /* Decrement AUTHREQ count if needed */ 01402 if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) { 01403 struct iax2_user *user; 01404 struct iax2_user tmp_user = { 01405 .name = pvt->username, 01406 }; 01407 01408 user = ao2_find(users, &tmp_user, OBJ_POINTER); 01409 if (user) { 01410 ast_atomic_fetchadd_int(&user->curauthreq, -1); 01411 user_unref(user); 01412 } 01413 01414 ast_clear_flag(pvt, IAX_MAXAUTHREQ); 01415 } 01416 /* No more pings or lagrq's */ 01417 AST_SCHED_DEL(sched, pvt->pingid); 01418 AST_SCHED_DEL(sched, pvt->lagid); 01419 AST_SCHED_DEL(sched, pvt->autoid); 01420 AST_SCHED_DEL(sched, pvt->authid); 01421 AST_SCHED_DEL(sched, pvt->initid); 01422 AST_SCHED_DEL(sched, pvt->jbid); 01423 }
static int iax2_devicestate | ( | void * | data | ) | [static] |
Part of the device state notification system ---.
Definition at line 12080 of file chan_iax2.c.
References iax2_peer::addr, ast_debug, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strdupa, ast_strlen_zero(), iax2_peer::defaddr, find_peer(), iax2_peer::historicms, iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, parse_dial_string(), and peer_unref().
12081 { 12082 struct parsed_dial_string pds; 12083 char *tmp = ast_strdupa(data); 12084 struct iax2_peer *p; 12085 int res = AST_DEVICE_INVALID; 12086 12087 memset(&pds, 0, sizeof(pds)); 12088 parse_dial_string(tmp, &pds); 12089 12090 if (ast_strlen_zero(pds.peer)) { 12091 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 12092 return res; 12093 } 12094 12095 ast_debug(3, "Checking device state for device %s\n", pds.peer); 12096 12097 /* SLD: FIXME: second call to find_peer during registration */ 12098 if (!(p = find_peer(pds.peer, 1))) 12099 return res; 12100 12101 res = AST_DEVICE_UNAVAILABLE; 12102 ast_debug(3, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", 12103 pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); 12104 12105 if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && 12106 (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { 12107 /* Peer is registered, or have default IP address 12108 and a valid registration */ 12109 if (p->historicms == 0 || p->historicms <= p->maxms) 12110 /* let the core figure out whether it is in use or not */ 12111 res = AST_DEVICE_UNKNOWN; 12112 } 12113 12114 peer_unref(p); 12115 12116 return res; 12117 }
static int iax2_digit_begin | ( | struct ast_channel * | c, | |
char | digit | |||
) | [static] |
Definition at line 3173 of file chan_iax2.c.
References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03174 { 03175 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); 03176 }
static int iax2_digit_end | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 3178 of file chan_iax2.c.
References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03179 { 03180 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); 03181 }
static int iax2_do_register | ( | struct iax2_registry * | reg | ) | [static] |
Definition at line 9959 of file chan_iax2.c.
References iax2_registry::addr, ast_debug, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno_locked(), iax2_destroy(), iax2_do_register_s(), iax2_sched_replace(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, LOG_WARNING, NEW_FORCE, iax2_registry::refresh, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, sched, send_command(), and iax2_registry::username.
Referenced by __iax2_do_register_s(), load_module(), and reload_config().
09960 { 09961 struct iax_ie_data ied; 09962 if (iaxdebug) 09963 ast_debug(1, "Sending registration request for '%s'\n", reg->username); 09964 09965 if (reg->dnsmgr && 09966 ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { 09967 /* Maybe the IP has changed, force DNS refresh */ 09968 ast_dnsmgr_refresh(reg->dnsmgr); 09969 } 09970 09971 /* 09972 * if IP has Changed, free allocated call to create a new one with new IP 09973 * call has the pointer to IP and must be updated to the new one 09974 */ 09975 if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) { 09976 int callno = reg->callno; 09977 ast_mutex_lock(&iaxsl[callno]); 09978 iax2_destroy(callno); 09979 ast_mutex_unlock(&iaxsl[callno]); 09980 reg->callno = 0; 09981 } 09982 if (!reg->addr.sin_addr.s_addr) { 09983 if (iaxdebug) 09984 ast_debug(1, "Unable to send registration request for '%s' without IP address\n", reg->username); 09985 /* Setup the next registration attempt */ 09986 reg->expire = iax2_sched_replace(reg->expire, sched, 09987 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 09988 return -1; 09989 } 09990 09991 if (!reg->callno) { 09992 ast_debug(3, "Allocate call number\n"); 09993 reg->callno = find_callno_locked(0, 0, ®->addr, NEW_FORCE, defaultsockfd, 0); 09994 if (reg->callno < 1) { 09995 ast_log(LOG_WARNING, "Unable to create call for registration\n"); 09996 return -1; 09997 } else 09998 ast_debug(3, "Registration created on call %d\n", reg->callno); 09999 iaxs[reg->callno]->reg = reg; 10000 ast_mutex_unlock(&iaxsl[reg->callno]); 10001 } 10002 /* Setup the next registration a little early */ 10003 reg->expire = iax2_sched_replace(reg->expire, sched, 10004 (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 10005 /* Send the request */ 10006 memset(&ied, 0, sizeof(ied)); 10007 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 10008 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 10009 send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 10010 reg->regstate = REG_STATE_REGSENT; 10011 return 0; 10012 }
static int iax2_do_register_s | ( | const void * | data | ) | [static] |
Definition at line 6724 of file chan_iax2.c.
References __iax2_do_register_s(), and schedule_action.
Referenced by iax2_ack_registry(), and iax2_do_register().
06725 { 06726 #ifdef SCHED_MULTITHREADED 06727 if (schedule_action(__iax2_do_register_s, data)) 06728 #endif 06729 __iax2_do_register_s(data); 06730 return 0; 06731 }
static void iax2_dprequest | ( | struct iax2_dpcache * | dp, | |
int | callno | |||
) | [static] |
Definition at line 7449 of file chan_iax2.c.
References AST_FRAME_IAX, auto_hangup(), CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, iax2_sched_replace(), IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, sched, and send_command().
Referenced by find_cache(), and socket_process().
07450 { 07451 struct iax_ie_data ied; 07452 /* Auto-hangup with 30 seconds of inactivity */ 07453 iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 07454 sched, 30000, auto_hangup, (void *)(long)callno); 07455 memset(&ied, 0, sizeof(ied)); 07456 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten); 07457 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); 07458 dp->flags |= CACHE_FLAG_TRANSMITTED; 07459 }
static void * iax2_dup_variable_datastore | ( | void * | ) | [static] |
Definition at line 1003 of file chan_iax2.c.
References ast_calloc, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_var_assign(), ast_var_name(), ast_var_value(), ast_var_t::entries, and LOG_ERROR.
01004 { 01005 AST_LIST_HEAD(, ast_var_t) *oldlist = old, *newlist; 01006 struct ast_var_t *oldvar, *newvar; 01007 01008 newlist = ast_calloc(sizeof(*newlist), 1); 01009 if (!newlist) { 01010 ast_log(LOG_ERROR, "Unable to duplicate iax2 variables\n"); 01011 return NULL; 01012 } 01013 01014 AST_LIST_HEAD_INIT(newlist); 01015 AST_LIST_LOCK(oldlist); 01016 AST_LIST_TRAVERSE(oldlist, oldvar, entries) { 01017 newvar = ast_var_assign(ast_var_name(oldvar), ast_var_value(oldvar)); 01018 if (newvar) 01019 AST_LIST_INSERT_TAIL(newlist, newvar, entries); 01020 else 01021 ast_log(LOG_ERROR, "Unable to duplicate iax2 variable '%s'\n", ast_var_name(oldvar)); 01022 } 01023 AST_LIST_UNLOCK(oldlist); 01024 return newlist; 01025 }
static int iax2_exec | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid, | |||
const char * | data | |||
) | [static] |
Execute IAX2 dialplan switch.
Definition at line 11887 of file chan_iax2.c.
References ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_verb, CACHE_FLAG_EXISTS, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_exec(), and pbx_findapp().
11888 { 11889 char odata[256]; 11890 char req[256]; 11891 char *ncontext; 11892 struct iax2_dpcache *dp = NULL; 11893 struct ast_app *dial = NULL; 11894 #if 0 11895 ast_log(LOG_NOTICE, "iax2_exec: con: %s, exten: %s, pri: %d, cid: %s, data: %s, newstack: %d\n", context, exten, priority, callerid ? callerid : "<unknown>", data, newstack); 11896 #endif 11897 if (priority == 2) { 11898 /* Indicate status, can be overridden in dialplan */ 11899 const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS"); 11900 if (dialstatus) { 11901 dial = pbx_findapp(dialstatus); 11902 if (dial) 11903 pbx_exec(chan, dial, ""); 11904 } 11905 return -1; 11906 } else if (priority != 1) 11907 return -1; 11908 11909 AST_LIST_LOCK(&dpcache); 11910 if ((dp = find_cache(chan, data, context, exten, priority))) { 11911 if (dp->flags & CACHE_FLAG_EXISTS) { 11912 ast_copy_string(odata, data, sizeof(odata)); 11913 ncontext = strchr(odata, '/'); 11914 if (ncontext) { 11915 *ncontext = '\0'; 11916 ncontext++; 11917 snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext); 11918 } else { 11919 snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten); 11920 } 11921 ast_verb(3, "Executing Dial('%s')\n", req); 11922 } else { 11923 AST_LIST_UNLOCK(&dpcache); 11924 ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data); 11925 return -1; 11926 } 11927 } 11928 AST_LIST_UNLOCK(&dpcache); 11929 11930 if ((dial = pbx_findapp("Dial"))) 11931 return pbx_exec(chan, dial, req); 11932 else 11933 ast_log(LOG_WARNING, "No dial application registered\n"); 11934 11935 return -1; 11936 }
static int iax2_exists | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid, | |||
const char * | data | |||
) | [static] |
Part of the IAX2 switch interface.
Definition at line 11818 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_EXISTS, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
11819 { 11820 int res = 0; 11821 struct iax2_dpcache *dp = NULL; 11822 #if 0 11823 ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 11824 #endif 11825 if ((priority != 1) && (priority != 2)) 11826 return 0; 11827 11828 AST_LIST_LOCK(&dpcache); 11829 if ((dp = find_cache(chan, data, context, exten, priority))) { 11830 if (dp->flags & CACHE_FLAG_EXISTS) 11831 res = 1; 11832 } else { 11833 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 11834 } 11835 AST_LIST_UNLOCK(&dpcache); 11836 11837 return res; 11838 }
static int iax2_fixup | ( | struct ast_channel * | oldchannel, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 3200 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, PTR_TO_CALLNO, and ast_channel::tech_pvt.
03201 { 03202 unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt); 03203 ast_mutex_lock(&iaxsl[callno]); 03204 if (iaxs[callno]) 03205 iaxs[callno]->owner = newchan; 03206 else 03207 ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n"); 03208 ast_mutex_unlock(&iaxsl[callno]); 03209 return 0; 03210 }
static void iax2_frame_free | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 1425 of file chan_iax2.c.
References AST_SCHED_DEL, iax_frame_free(), iax_frame::retrans, and sched.
Referenced by __attempt_transmit(), __do_deliver(), __get_from_jb(), complete_transfer(), pvt_destructor(), and schedule_delivery().
01426 { 01427 AST_SCHED_DEL(sched, fr->retrans); 01428 iax_frame_free(fr); 01429 }
static void iax2_free_variable_datastore | ( | void * | ) | [static] |
Definition at line 1027 of file chan_iax2.c.
References ast_free, AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and ast_var_t::entries.
01028 { 01029 AST_LIST_HEAD(, ast_var_t) *oldlist = old; 01030 struct ast_var_t *oldvar; 01031 01032 AST_LIST_LOCK(oldlist); 01033 while ((oldvar = AST_LIST_REMOVE_HEAD(oldlist, entries))) { 01034 ast_free(oldvar); 01035 } 01036 AST_LIST_UNLOCK(oldlist); 01037 AST_LIST_HEAD_DESTROY(oldlist); 01038 ast_free(oldlist); 01039 }
static int iax2_getpeername | ( | struct sockaddr_in | sin, | |
char * | host, | |||
int | len | |||
) | [static] |
Definition at line 1369 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_copy_string(), iax2_peer::name, peer_unref(), and realtime_peer().
Referenced by __find_callno().
01370 { 01371 struct iax2_peer *peer = NULL; 01372 int res = 0; 01373 struct ao2_iterator i; 01374 01375 i = ao2_iterator_init(peers, 0); 01376 while ((peer = ao2_iterator_next(&i))) { 01377 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 01378 (peer->addr.sin_port == sin.sin_port)) { 01379 ast_copy_string(host, peer->name, len); 01380 peer_unref(peer); 01381 res = 1; 01382 break; 01383 } 01384 peer_unref(peer); 01385 } 01386 01387 if (!peer) { 01388 peer = realtime_peer(NULL, &sin); 01389 if (peer) { 01390 ast_copy_string(host, peer->name, len); 01391 peer_unref(peer); 01392 res = 1; 01393 } 01394 } 01395 01396 return res; 01397 }
static int iax2_getpeertrunk | ( | struct sockaddr_in | sin | ) | [static] |
Definition at line 4216 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_TRUNK, and peer_unref().
Referenced by check_access().
04217 { 04218 struct iax2_peer *peer; 04219 int res = 0; 04220 struct ao2_iterator i; 04221 04222 i = ao2_iterator_init(peers, 0); 04223 while ((peer = ao2_iterator_next(&i))) { 04224 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 04225 (peer->addr.sin_port == sin.sin_port)) { 04226 res = ast_test_flag(peer, IAX_TRUNK); 04227 peer_unref(peer); 04228 break; 04229 } 04230 peer_unref(peer); 04231 } 04232 04233 return res; 04234 }
static int iax2_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3833 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_test_flag, ast_verb, CALLNO_TO_PTR, ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, LOG_ERROR, LOG_WARNING, ast_channel::name, PTR_TO_CALLNO, sched, scheduled_destroy(), send_command_final(), and ast_channel::tech_pvt.
03834 { 03835 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03836 struct iax_ie_data ied; 03837 int alreadygone; 03838 memset(&ied, 0, sizeof(ied)); 03839 ast_mutex_lock(&iaxsl[callno]); 03840 if (callno && iaxs[callno]) { 03841 ast_debug(1, "We're hanging up %s now...\n", c->name); 03842 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE); 03843 /* Send the hangup unless we have had a transmission error or are already gone */ 03844 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); 03845 if (!iaxs[callno]->error && !alreadygone) { 03846 if (send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1)) { 03847 ast_log(LOG_WARNING, "No final packet could be sent for callno %d\n", callno); 03848 } 03849 if (!iaxs[callno]) { 03850 ast_mutex_unlock(&iaxsl[callno]); 03851 return 0; 03852 } 03853 } 03854 /* Explicitly predestroy it */ 03855 iax2_predestroy(callno); 03856 /* If we were already gone to begin with, destroy us now */ 03857 if (iaxs[callno] && alreadygone) { 03858 ast_debug(1, "Really destroying %s now...\n", c->name); 03859 iax2_destroy(callno); 03860 } else if (iaxs[callno]) { 03861 if (ast_sched_add(sched, 10000, scheduled_destroy, CALLNO_TO_PTR(callno)) < 0) { 03862 ast_log(LOG_ERROR, "Unable to schedule iax2 callno %d destruction?!! Destroying immediately.\n", callno); 03863 iax2_destroy(callno); 03864 } 03865 } 03866 } else if (c->tech_pvt) { 03867 /* If this call no longer exists, but the channel still 03868 * references it we need to set the channel's tech_pvt to null 03869 * to avoid ast_channel_free() trying to free it. 03870 */ 03871 c->tech_pvt = NULL; 03872 } 03873 ast_mutex_unlock(&iaxsl[callno]); 03874 ast_verb(3, "Hungup '%s'\n", c->name); 03875 return 0; 03876 }
static int iax2_indicate | ( | struct ast_channel * | c, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 4159 of file chan_iax2.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_CONTROL, ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::mohinterpret, PTR_TO_CALLNO, send_command(), ast_channel::tech_pvt, and wait_for_peercallno().
04160 { 04161 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04162 struct chan_iax2_pvt *pvt; 04163 int res = 0; 04164 04165 if (iaxdebug) 04166 ast_debug(1, "Indicating condition %d\n", condition); 04167 04168 ast_mutex_lock(&iaxsl[callno]); 04169 pvt = iaxs[callno]; 04170 04171 if (wait_for_peercallno(pvt)) { 04172 res = -1; 04173 goto done; 04174 } 04175 04176 switch (condition) { 04177 case AST_CONTROL_HOLD: 04178 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 04179 ast_moh_start(c, data, pvt->mohinterpret); 04180 goto done; 04181 } 04182 break; 04183 case AST_CONTROL_UNHOLD: 04184 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 04185 ast_moh_stop(c); 04186 goto done; 04187 } 04188 } 04189 04190 res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); 04191 04192 done: 04193 ast_mutex_unlock(&iaxsl[callno]); 04194 04195 return res; 04196 }
static int iax2_matchmore | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | exten, | |||
int | priority, | |||
const char * | callerid, | |||
const char * | data | |||
) | [static] |
Part of the IAX2 Switch interface.
Definition at line 11864 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), CACHE_FLAG_MATCHMORE, chan, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
11865 { 11866 int res = 0; 11867 struct iax2_dpcache *dp = NULL; 11868 #if 0 11869 ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 11870 #endif 11871 if ((priority != 1) && (priority != 2)) 11872 return 0; 11873 11874 AST_LIST_LOCK(&dpcache); 11875 if ((dp = find_cache(chan, data, context, exten, priority))) { 11876 if (dp->flags & CACHE_FLAG_MATCHMORE) 11877 res = 1; 11878 } else { 11879 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 11880 } 11881 AST_LIST_UNLOCK(&dpcache); 11882 11883 return res; 11884 }
static int iax2_poke_noanswer | ( | const void * | data | ) | [static] |
Definition at line 10162 of file chan_iax2.c.
References __iax2_poke_noanswer(), peer_unref(), iax2_peer::pokeexpire, and schedule_action.
Referenced by iax2_poke_peer().
10163 { 10164 struct iax2_peer *peer = (struct iax2_peer *)data; 10165 peer->pokeexpire = -1; 10166 #ifdef SCHED_MULTITHREADED 10167 if (schedule_action(__iax2_poke_noanswer, data)) 10168 #endif 10169 __iax2_poke_noanswer(data); 10170 peer_unref(peer); 10171 return 0; 10172 }
static int iax2_poke_peer | ( | struct iax2_peer * | peer, | |
int | heldcall | |||
) | [static] |
Definition at line 10183 of file chan_iax2.c.
References iax2_peer::addr, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), iax2_peer::callno, DEFAULT_MAXMS, iax2_peer::dnsmgr, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), iax2_sched_add(), IAX_COMMAND_POKE, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, iax2_peer::name, NEW_FORCE, peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, sched, send_command(), and iax2_peer::sockfd.
Referenced by __iax2_poke_peer_s(), iax2_poke_peer_cb(), poke_all_peers(), reg_source_db(), and update_registry().
10184 { 10185 int callno; 10186 if (!peer->maxms || (!peer->addr.sin_addr.s_addr && !peer->dnsmgr)) { 10187 /* IF we have no IP without dnsmgr, or this isn't to be monitored, return 10188 immediately after clearing things out */ 10189 peer->lastms = 0; 10190 peer->historicms = 0; 10191 peer->pokeexpire = -1; 10192 peer->callno = 0; 10193 return 0; 10194 } 10195 10196 /* The peer could change the callno inside iax2_destroy, since we do deadlock avoidance */ 10197 if ((callno = peer->callno) > 0) { 10198 ast_log(LOG_NOTICE, "Still have a callno...\n"); 10199 ast_mutex_lock(&iaxsl[callno]); 10200 iax2_destroy(callno); 10201 ast_mutex_unlock(&iaxsl[callno]); 10202 } 10203 if (heldcall) 10204 ast_mutex_unlock(&iaxsl[heldcall]); 10205 callno = peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0); 10206 if (heldcall) 10207 ast_mutex_lock(&iaxsl[heldcall]); 10208 if (peer->callno < 1) { 10209 ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); 10210 return -1; 10211 } 10212 10213 /* Speed up retransmission times for this qualify call */ 10214 iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1; 10215 iaxs[peer->callno]->peerpoke = peer; 10216 10217 if (peer->pokeexpire > -1) { 10218 if (!ast_sched_del(sched, peer->pokeexpire)) { 10219 peer->pokeexpire = -1; 10220 peer_unref(peer); 10221 } 10222 } 10223 10224 /* Queue up a new task to handle no reply */ 10225 /* If the host is already unreachable then use the unreachable interval instead */ 10226 if (peer->lastms < 0) 10227 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer_ref(peer)); 10228 else 10229 peer->pokeexpire = iax2_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer_ref(peer)); 10230 10231 if (peer->pokeexpire == -1) 10232 peer_unref(peer); 10233 10234 /* And send the poke */ 10235 ast_mutex_lock(&iaxsl[callno]); 10236 if (iaxs[callno]) { 10237 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1); 10238 } 10239 ast_mutex_unlock(&iaxsl[callno]); 10240 10241 return 0; 10242 }
static int iax2_poke_peer_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 10174 of file chan_iax2.c.
References iax2_poke_peer().
Referenced by load_module().
10175 { 10176 struct iax2_peer *peer = obj; 10177 10178 iax2_poke_peer(peer, 0); 10179 10180 return 0; 10181 }
static int iax2_poke_peer_s | ( | const void * | data | ) | [static] |
Definition at line 7489 of file chan_iax2.c.
References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.
Referenced by __iax2_poke_noanswer(), and socket_process().
07490 { 07491 struct iax2_peer *peer = (struct iax2_peer *)data; 07492 peer->pokeexpire = -1; 07493 #ifdef SCHED_MULTITHREADED 07494 if (schedule_action(__iax2_poke_peer_s, data)) 07495 #endif 07496 __iax2_poke_peer_s(data); 07497 return 0; 07498 }
static int iax2_predestroy | ( | int | callno | ) | [static] |
Definition at line 2311 of file chan_iax2.c.
References ast_module_unref(), ast_set_flag, ast_test_flag, iax2_destroy_helper(), iax2_queue_hangup(), IAX_ALREADYGONE, chan_iax2_pvt::owner, and ast_channel::tech_pvt.
Referenced by iax2_hangup(), and send_command_final().
02312 { 02313 struct ast_channel *c = NULL; 02314 struct chan_iax2_pvt *pvt = iaxs[callno]; 02315 02316 if (!pvt) 02317 return -1; 02318 02319 if (!ast_test_flag(pvt, IAX_ALREADYGONE)) { 02320 iax2_destroy_helper(pvt); 02321 ast_set_flag(pvt, IAX_ALREADYGONE); 02322 } 02323 02324 if ((c = pvt->owner)) { 02325 c->tech_pvt = NULL; 02326 iax2_queue_hangup(callno); 02327 pvt->owner = NULL; 02328 ast_module_unref(ast_module_info->self); 02329 } 02330 02331 return 0; 02332 }
static void * iax2_process_thread | ( | void * | data | ) | [static] |
Definition at line 9834 of file chan_iax2.c.
References ast_atomic_fetchadd_int(), ast_cond_timedwait(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_tvadd(), ast_tvnow(), iax2_process_thread_cleanup(), IAX_THREAD_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), and thread.
Referenced by find_idle_thread(), and start_network_thread().
09835 { 09836 struct iax2_thread *thread = data; 09837 struct timeval tv; 09838 struct timespec ts; 09839 int put_into_idle = 0; 09840 09841 ast_atomic_fetchadd_int(&iaxactivethreadcount,1); 09842 pthread_cleanup_push(iax2_process_thread_cleanup, data); 09843 for(;;) { 09844 /* Wait for something to signal us to be awake */ 09845 ast_mutex_lock(&thread->lock); 09846 09847 /* Flag that we're ready to accept signals */ 09848 thread->ready_for_signal = 1; 09849 09850 /* Put into idle list if applicable */ 09851 if (put_into_idle) 09852 insert_idle_thread(thread); 09853 09854 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) { 09855 struct iax2_thread *t = NULL; 09856 /* Wait to be signalled or time out */ 09857 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 09858 ts.tv_sec = tv.tv_sec; 09859 ts.tv_nsec = tv.tv_usec * 1000; 09860 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) { 09861 /* This thread was never put back into the available dynamic 09862 * thread list, so just go away. */ 09863 if (!put_into_idle) { 09864 ast_mutex_unlock(&thread->lock); 09865 break; 09866 } 09867 AST_LIST_LOCK(&dynamic_list); 09868 /* Account for the case where this thread is acquired *right* after a timeout */ 09869 if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list))) 09870 ast_atomic_fetchadd_int(&iaxdynamicthreadcount, -1); 09871 AST_LIST_UNLOCK(&dynamic_list); 09872 if (t) { 09873 /* This dynamic thread timed out waiting for a task and was 09874 * not acquired immediately after the timeout, 09875 * so it's time to go away. */ 09876 ast_mutex_unlock(&thread->lock); 09877 break; 09878 } 09879 /* Someone grabbed our thread *right* after we timed out. 09880 * Wait for them to set us up with something to do and signal 09881 * us to continue. */ 09882 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 09883 ts.tv_sec = tv.tv_sec; 09884 ts.tv_nsec = tv.tv_usec * 1000; 09885 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) 09886 { 09887 ast_mutex_unlock(&thread->lock); 09888 break; 09889 } 09890 } 09891 } else { 09892 ast_cond_wait(&thread->cond, &thread->lock); 09893 } 09894 09895 /* Go back into our respective list */ 09896 put_into_idle = 1; 09897 09898 ast_mutex_unlock(&thread->lock); 09899 09900 if (thread->iostate == IAX_IOSTATE_IDLE) 09901 continue; 09902 09903 /* Add ourselves to the active list now */ 09904 AST_LIST_LOCK(&active_list); 09905 AST_LIST_INSERT_HEAD(&active_list, thread, list); 09906 AST_LIST_UNLOCK(&active_list); 09907 09908 /* See what we need to do */ 09909 switch(thread->iostate) { 09910 case IAX_IOSTATE_READY: 09911 thread->actions++; 09912 thread->iostate = IAX_IOSTATE_PROCESSING; 09913 socket_process(thread); 09914 handle_deferred_full_frames(thread); 09915 break; 09916 case IAX_IOSTATE_SCHEDREADY: 09917 thread->actions++; 09918 thread->iostate = IAX_IOSTATE_PROCESSING; 09919 #ifdef SCHED_MULTITHREADED 09920 thread->schedfunc(thread->scheddata); 09921 #endif 09922 default: 09923 break; 09924 } 09925 time(&thread->checktime); 09926 thread->iostate = IAX_IOSTATE_IDLE; 09927 #ifdef DEBUG_SCHED_MULTITHREAD 09928 thread->curfunc[0]='\0'; 09929 #endif 09930 09931 /* Now... remove ourselves from the active list, and return to the idle list */ 09932 AST_LIST_LOCK(&active_list); 09933 AST_LIST_REMOVE(&active_list, thread, list); 09934 AST_LIST_UNLOCK(&active_list); 09935 09936 /* Make sure another frame didn't sneak in there after we thought we were done. */ 09937 handle_deferred_full_frames(thread); 09938 } 09939 09940 /*!\note For some reason, idle threads are exiting without being removed 09941 * from an idle list, which is causing memory corruption. Forcibly remove 09942 * it from the list, if it's there. 09943 */ 09944 AST_LIST_LOCK(&idle_list); 09945 AST_LIST_REMOVE(&idle_list, thread, list); 09946 AST_LIST_UNLOCK(&idle_list); 09947 09948 AST_LIST_LOCK(&dynamic_list); 09949 AST_LIST_REMOVE(&dynamic_list, thread, list); 09950 AST_LIST_UNLOCK(&dynamic_list); 09951 09952 /* I am exiting here on my own volition, I need to clean up my own data structures 09953 * Assume that I am no longer in any of the lists (idle, active, or dynamic) 09954 */ 09955 pthread_cleanup_pop(1); 09956 return NULL; 09957 }
static void iax2_process_thread_cleanup | ( | void * | data | ) | [static] |
Definition at line 9825 of file chan_iax2.c.
References ast_atomic_dec_and_test(), ast_cond_destroy(), ast_free, ast_mutex_destroy(), iaxactivethreadcount, and thread.
Referenced by iax2_process_thread().
09826 { 09827 struct iax2_thread *thread = data; 09828 ast_mutex_destroy(&thread->lock); 09829 ast_cond_destroy(&thread->cond); 09830 ast_free(thread); 09831 ast_atomic_dec_and_test(&iaxactivethreadcount); 09832 }
static int iax2_provision | ( | struct sockaddr_in * | end, | |
int | sockfd, | |||
char * | dest, | |||
const char * | template, | |||
int | force | |||
) | [static] |
Definition at line 10014 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_mutex_unlock(), ast_set_flag, auto_hangup(), iax_ie_data::buf, create_addr(), find_callno_locked(), iax2_sched_replace(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), NEW_FORCE, iax_ie_data::pos, sched, and send_command().
Referenced by check_provisioning(), handle_cli_iax2_provision(), and iax2_prov_app().
10015 { 10016 /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning 10017 is found for template */ 10018 struct iax_ie_data provdata; 10019 struct iax_ie_data ied; 10020 unsigned int sig; 10021 struct sockaddr_in sin; 10022 int callno; 10023 struct create_addr_info cai; 10024 10025 memset(&cai, 0, sizeof(cai)); 10026 10027 ast_debug(1, "Provisioning '%s' from template '%s'\n", dest, template); 10028 10029 if (iax_provision_build(&provdata, &sig, template, force)) { 10030 ast_debug(1, "No provisioning found for template '%s'\n", template); 10031 return 0; 10032 } 10033 10034 if (end) { 10035 memcpy(&sin, end, sizeof(sin)); 10036 cai.sockfd = sockfd; 10037 } else if (create_addr(dest, NULL, &sin, &cai)) 10038 return -1; 10039 10040 /* Build the rest of the message */ 10041 memset(&ied, 0, sizeof(ied)); 10042 iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); 10043 10044 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 10045 if (!callno) 10046 return -1; 10047 10048 if (iaxs[callno]) { 10049 /* Schedule autodestruct in case they don't ever give us anything back */ 10050 iaxs[callno]->autoid = iax2_sched_replace(iaxs[callno]->autoid, 10051 sched, 15000, auto_hangup, (void *)(long)callno); 10052 ast_set_flag(iaxs[callno], IAX_PROVISION); 10053 /* Got a call number now, so go ahead and send the provisioning information */ 10054 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); 10055 } 10056 ast_mutex_unlock(&iaxsl[callno]); 10057 10058 return 1; 10059 }
static int iax2_queue_control_data | ( | int | callno, | |
enum ast_control_frame_type | control, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Queue a control frame on the ast_channel owner.
This function queues a control frame on the owner of the IAX2 pvt struct that is active for the given call number.
Definition at line 1936 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_control_data(), DEADLOCK_AVOIDANCE, and chan_iax2_pvt::owner.
Referenced by socket_process().
01938 { 01939 for (;;) { 01940 if (iaxs[callno] && iaxs[callno]->owner) { 01941 if (ast_channel_trylock(iaxs[callno]->owner)) { 01942 /* Avoid deadlock by pausing and trying again */ 01943 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01944 } else { 01945 ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); 01946 ast_channel_unlock(iaxs[callno]->owner); 01947 break; 01948 } 01949 } else 01950 break; 01951 } 01952 return 0; 01953 }
static int iax2_queue_frame | ( | int | callno, | |
struct ast_frame * | f | |||
) | [static] |
Queue a frame to a call's owning asterisk channel.
Definition at line 1874 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, and chan_iax2_pvt::owner.
Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), __get_from_jb(), and socket_process().
01875 { 01876 for (;;) { 01877 if (iaxs[callno] && iaxs[callno]->owner) { 01878 if (ast_channel_trylock(iaxs[callno]->owner)) { 01879 /* Avoid deadlock by pausing and trying again */ 01880 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01881 } else { 01882 ast_queue_frame(iaxs[callno]->owner, f); 01883 ast_channel_unlock(iaxs[callno]->owner); 01884 break; 01885 } 01886 } else 01887 break; 01888 } 01889 return 0; 01890 }
static int iax2_queue_hangup | ( | int | callno | ) | [static] |
Queue a hangup frame on the ast_channel owner.
This function queues a hangup frame on the owner of the IAX2 pvt struct that is active for the given call number.
Definition at line 1905 of file chan_iax2.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, and chan_iax2_pvt::owner.
Referenced by iax2_predestroy().
01906 { 01907 for (;;) { 01908 if (iaxs[callno] && iaxs[callno]->owner) { 01909 if (ast_channel_trylock(iaxs[callno]->owner)) { 01910 /* Avoid deadlock by pausing and trying again */ 01911 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 01912 } else { 01913 ast_queue_hangup(iaxs[callno]->owner); 01914 ast_channel_unlock(iaxs[callno]->owner); 01915 break; 01916 } 01917 } else 01918 break; 01919 } 01920 return 0; 01921 }
static struct ast_frame * iax2_read | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3942 of file chan_iax2.c.
References ast_log(), ast_null_frame, and LOG_NOTICE.
03943 { 03944 ast_log(LOG_NOTICE, "I should never be called!\n"); 03945 return &ast_null_frame; 03946 }
static int iax2_register | ( | const char * | value, | |
int | lineno | |||
) | [static] |
Definition at line 6958 of file chan_iax2.c.
References ast_copy_string(), ast_log(), copy(), hostname, iax2_append_register(), LOG_WARNING, secret, and strsep().
Referenced by set_config().
06959 { 06960 char copy[256]; 06961 char *username, *hostname, *secret; 06962 char *porta; 06963 char *stringp=NULL; 06964 06965 if (!value) 06966 return -1; 06967 06968 ast_copy_string(copy, value, sizeof(copy)); 06969 stringp = copy; 06970 username = strsep(&stringp, "@"); 06971 hostname = strsep(&stringp, "@"); 06972 06973 if (!hostname) { 06974 ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno); 06975 return -1; 06976 } 06977 06978 stringp = username; 06979 username = strsep(&stringp, ":"); 06980 secret = strsep(&stringp, ":"); 06981 stringp = hostname; 06982 hostname = strsep(&stringp, ":"); 06983 porta = strsep(&stringp, ":"); 06984 06985 if (porta && !atoi(porta)) { 06986 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 06987 return -1; 06988 } 06989 06990 return iax2_append_register(hostname, username, secret, porta); 06991 }
static struct ast_channel * iax2_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 10254 of file chan_iax2.c.
References ast_best_codec(), AST_CAUSE_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_flags, ast_getformatname(), ast_hangup(), ast_iax2_new(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_translator_best_choice(), create_addr(), find_callno_locked(), globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, LOG_WARNING, make_trunk(), ast_channel::name, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), ast_channel::readformat, and ast_channel::writeformat.
10255 { 10256 int callno; 10257 int res; 10258 int fmt, native; 10259 struct sockaddr_in sin; 10260 struct ast_channel *c; 10261 struct parsed_dial_string pds; 10262 struct create_addr_info cai; 10263 char *tmpstr; 10264 10265 memset(&pds, 0, sizeof(pds)); 10266 tmpstr = ast_strdupa(data); 10267 parse_dial_string(tmpstr, &pds); 10268 10269 if (ast_strlen_zero(pds.peer)) { 10270 ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", (char *) data); 10271 return NULL; 10272 } 10273 10274 memset(&cai, 0, sizeof(cai)); 10275 cai.capability = iax2_capability; 10276 10277 ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 10278 10279 /* Populate our address from the given */ 10280 if (create_addr(pds.peer, NULL, &sin, &cai)) { 10281 *cause = AST_CAUSE_UNREGISTERED; 10282 return NULL; 10283 } 10284 10285 if (pds.port) 10286 sin.sin_port = htons(atoi(pds.port)); 10287 10288 callno = find_callno_locked(0, 0, &sin, NEW_FORCE, cai.sockfd, 0); 10289 if (callno < 1) { 10290 ast_log(LOG_WARNING, "Unable to create call\n"); 10291 *cause = AST_CAUSE_CONGESTION; 10292 return NULL; 10293 } 10294 10295 /* If this is a trunk, update it now */ 10296 ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 10297 if (ast_test_flag(&cai, IAX_TRUNK)) { 10298 int new_callno; 10299 if ((new_callno = make_trunk(callno, 1)) != -1) 10300 callno = new_callno; 10301 } 10302 iaxs[callno]->maxtime = cai.maxtime; 10303 if (cai.found) 10304 ast_string_field_set(iaxs[callno], host, pds.peer); 10305 10306 c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability); 10307 10308 ast_mutex_unlock(&iaxsl[callno]); 10309 10310 if (c) { 10311 /* Choose a format we can live with */ 10312 if (c->nativeformats & format) 10313 c->nativeformats &= format; 10314 else { 10315 native = c->nativeformats; 10316 fmt = format; 10317 res = ast_translator_best_choice(&fmt, &native); 10318 if (res < 0) { 10319 ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", 10320 ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); 10321 ast_hangup(c); 10322 return NULL; 10323 } 10324 c->nativeformats = native; 10325 } 10326 c->readformat = ast_best_codec(c->nativeformats); 10327 c->writeformat = c->readformat; 10328 } 10329 10330 return c; 10331 }
static int iax2_sched_add | ( | struct sched_context * | con, | |
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) | [static] |
Definition at line 1155 of file chan_iax2.c.
References ast_sched_add(), sched_lock, and signal_condition().
Referenced by __attempt_transmit(), __find_callno(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), iax2_call(), iax2_poke_peer(), make_trunk(), network_thread(), reg_source_db(), socket_process(), and update_registry().
01156 { 01157 int res; 01158 01159 res = ast_sched_add(con, when, callback, data); 01160 signal_condition(&sched_lock, &sched_cond); 01161 01162 return res; 01163 }
static int iax2_sched_replace | ( | int | id, | |
struct sched_context * | con, | |||
int | when, | |||
ast_sched_cb | callback, | |||
const void * | data | |||
) | [static] |
Definition at line 1147 of file chan_iax2.c.
References AST_SCHED_REPLACE, sched_lock, and signal_condition().
Referenced by auth_fail(), iax2_ack_registry(), iax2_do_register(), iax2_dprequest(), iax2_provision(), and update_jbsched().
01148 { 01149 AST_SCHED_REPLACE(id, con, when, callback, data); 01150 signal_condition(&sched_lock, &sched_cond); 01151 01152 return id; 01153 }
static int iax2_send | ( | struct chan_iax2_pvt * | pvt, | |
struct ast_frame * | f, | |||
unsigned int | ts, | |||
int | seqno, | |||
int | now, | |||
int | transfer, | |||
int | final | |||
) | [static] |
Definition at line 4864 of file chan_iax2.c.
References iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, ast_frame::datalen, iax_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, iax_frame::ecx, iax_frame::encmethods, encrypt_frame(), f, iax_frame::final, chan_iax2_pvt::first_iax_message, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::last_iax_message, chan_iax2_pvt::lastsent, chan_iax2_pvt::lastvsent, LOG_WARNING, MARK_IAX_SUBCLASS_TX, MAX_RETRY_TIME, MIN_RETRY_TIME, iax_frame::mydcx, ast_iax2_full_hdr::oseqno, chan_iax2_pvt::oseqno, iax_frame::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, iax_frame::retrytime, ast_iax2_full_hdr::scallno, iax_frame::semirand, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, iax_frame::transfer, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, ast_iax2_mini_hdr::ts, ast_iax2_video_hdr::ts, ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_full_hdr::type, and ast_iax2_video_hdr::zeros.
Referenced by __send_command(), iax2_write(), and socket_process().
04865 { 04866 /* Queue a packet for delivery on a given private structure. Use "ts" for 04867 timestamp, or calculate if ts is 0. Send immediately without retransmission 04868 or delayed, with retransmission */ 04869 struct ast_iax2_full_hdr *fh; 04870 struct ast_iax2_mini_hdr *mh; 04871 struct ast_iax2_video_hdr *vh; 04872 struct { 04873 struct iax_frame fr2; 04874 unsigned char buffer[4096]; 04875 } frb; 04876 struct iax_frame *fr; 04877 int res; 04878 int sendmini=0; 04879 unsigned int lastsent; 04880 unsigned int fts; 04881 04882 frb.fr2.afdatalen = sizeof(frb.buffer); 04883 04884 if (!pvt) { 04885 ast_log(LOG_WARNING, "No private structure for packet?\n"); 04886 return -1; 04887 } 04888 04889 lastsent = pvt->lastsent; 04890 04891 /* Calculate actual timestamp */ 04892 fts = calc_timestamp(pvt, ts, f); 04893 04894 /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out 04895 * (the endpoint should detect the lost packet itself). But, we want to do this here, so that we 04896 * increment the "predicted timestamps" for voice, if we're predicting */ 04897 if(f->frametype == AST_FRAME_VOICE && f->datalen == 0) 04898 return 0; 04899 04900 04901 if ((ast_test_flag(pvt, IAX_TRUNK) || 04902 (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) || 04903 ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L)))) 04904 /* High two bytes are the same on timestamp, or sending on a trunk */ && 04905 (f->frametype == AST_FRAME_VOICE) 04906 /* is a voice frame */ && 04907 (f->subclass == pvt->svoiceformat) 04908 /* is the same type */ ) { 04909 /* Force immediate rather than delayed transmission */ 04910 now = 1; 04911 /* Mark that mini-style frame is appropriate */ 04912 sendmini = 1; 04913 } 04914 if ( f->frametype == AST_FRAME_VIDEO ) { 04915 /* 04916 * If the lower 15 bits of the timestamp roll over, or if 04917 * the video format changed then send a full frame. 04918 * Otherwise send a mini video frame 04919 */ 04920 if (((fts & 0xFFFF8000L) == (pvt->lastvsent & 0xFFFF8000L)) && 04921 ((f->subclass & ~0x1) == pvt->svideoformat) 04922 ) { 04923 now = 1; 04924 sendmini = 1; 04925 } else { 04926 now = 0; 04927 sendmini = 0; 04928 } 04929 pvt->lastvsent = fts; 04930 } 04931 if (f->frametype == AST_FRAME_IAX) { 04932 /* 0x8000 marks this message as TX:, this bit will be stripped later */ 04933 pvt->last_iax_message = f->subclass | MARK_IAX_SUBCLASS_TX; 04934 if (!pvt->first_iax_message) { 04935 pvt->first_iax_message = pvt->last_iax_message; 04936 } 04937 } 04938 /* Allocate an iax_frame */ 04939 if (now) { 04940 fr = &frb.fr2; 04941 } else 04942 fr = iax_frame_new(DIRECTION_OUTGRESS, ast_test_flag(pvt, IAX_ENCRYPTED) ? f->datalen + 32 : f->datalen, (f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO)); 04943 if (!fr) { 04944 ast_log(LOG_WARNING, "Out of memory\n"); 04945 return -1; 04946 } 04947 /* Copy our prospective frame into our immediate or retransmitted wrapper */ 04948 iax_frame_wrap(fr, f); 04949 04950 fr->ts = fts; 04951 fr->callno = pvt->callno; 04952 fr->transfer = transfer; 04953 fr->final = final; 04954 fr->encmethods = 0; 04955 if (!sendmini) { 04956 /* We need a full frame */ 04957 if (seqno > -1) 04958 fr->oseqno = seqno; 04959 else 04960 fr->oseqno = pvt->oseqno++; 04961 fr->iseqno = pvt->iseqno; 04962 fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr)); 04963 fh->scallno = htons(fr->callno | IAX_FLAG_FULL); 04964 fh->ts = htonl(fr->ts); 04965 fh->oseqno = fr->oseqno; 04966 if (transfer) { 04967 fh->iseqno = 0; 04968 } else 04969 fh->iseqno = fr->iseqno; 04970 /* Keep track of the last thing we've acknowledged */ 04971 if (!transfer) 04972 pvt->aseqno = fr->iseqno; 04973 fh->type = fr->af.frametype & 0xFF; 04974 if (fr->af.frametype == AST_FRAME_VIDEO) 04975 fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6); 04976 else 04977 fh->csub = compress_subclass(fr->af.subclass); 04978 if (transfer) { 04979 fr->dcallno = pvt->transfercallno; 04980 } else 04981 fr->dcallno = pvt->peercallno; 04982 fh->dcallno = htons(fr->dcallno); 04983 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); 04984 fr->data = fh; 04985 fr->retries = 0; 04986 /* Retry after 2x the ping time has passed */ 04987 fr->retrytime = pvt->pingtime * 2; 04988 if (fr->retrytime < MIN_RETRY_TIME) 04989 fr->retrytime = MIN_RETRY_TIME; 04990 if (fr->retrytime > MAX_RETRY_TIME) 04991 fr->retrytime = MAX_RETRY_TIME; 04992 /* Acks' don't get retried */ 04993 if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) 04994 fr->retries = -1; 04995 else if (f->frametype == AST_FRAME_VOICE) 04996 pvt->svoiceformat = f->subclass; 04997 else if (f->frametype == AST_FRAME_VIDEO) 04998 pvt->svideoformat = f->subclass & ~0x1; 04999 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 05000 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 05001 if (iaxdebug) { 05002 if (fr->transfer) 05003 iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 05004 else 05005 iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 05006 } 05007 encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen); 05008 fr->encmethods = pvt->encmethods; 05009 fr->ecx = pvt->ecx; 05010 fr->mydcx = pvt->mydcx; 05011 memcpy(fr->semirand, pvt->semirand, sizeof(fr->semirand)); 05012 } else 05013 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 05014 } 05015 05016 if (now) { 05017 res = send_packet(fr); 05018 } else 05019 res = iax2_transmit(fr); 05020 } else { 05021 if (ast_test_flag(pvt, IAX_TRUNK)) { 05022 iax2_trunk_queue(pvt, fr); 05023 res = 0; 05024 } else if (fr->af.frametype == AST_FRAME_VIDEO) { 05025 /* Video frame have no sequence number */ 05026 fr->oseqno = -1; 05027 fr->iseqno = -1; 05028 vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr)); 05029 vh->zeros = 0; 05030 vh->callno = htons(0x8000 | fr->callno); 05031 vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); 05032 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); 05033 fr->data = vh; 05034 fr->retries = -1; 05035 res = send_packet(fr); 05036 } else { 05037 /* Mini-frames have no sequence number */ 05038 fr->oseqno = -1; 05039 fr->iseqno = -1; 05040 /* Mini frame will do */ 05041 mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr)); 05042 mh->callno = htons(fr->callno); 05043 mh->ts = htons(fr->ts & 0xFFFF); 05044 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); 05045 fr->data = mh; 05046 fr->retries = -1; 05047 if (pvt->transferring == TRANSFER_MEDIAPASS) 05048 fr->transfer = 1; 05049 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 05050 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 05051 encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen); 05052 } else 05053 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 05054 } 05055 res = send_packet(fr); 05056 } 05057 } 05058 return res; 05059 }
static int iax2_sendhtml | ( | struct ast_channel * | c, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3195 of file chan_iax2.c.
References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03196 { 03197 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1); 03198 }
static int iax2_sendimage | ( | struct ast_channel * | c, | |
struct ast_frame * | img | |||
) | [static] |
Definition at line 3190 of file chan_iax2.c.
References AST_FRAME_IMAGE, ast_frame::data, ast_frame::datalen, PTR_TO_CALLNO, send_command_locked(), ast_frame::subclass, and ast_channel::tech_pvt.
03191 { 03192 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1); 03193 }
static int iax2_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 3183 of file chan_iax2.c.
References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03184 { 03185 03186 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT, 03187 0, 0, (unsigned char *)text, strlen(text) + 1, -1); 03188 }
static int iax2_setoption | ( | struct ast_channel * | c, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3900 of file chan_iax2.c.
References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_free, ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, errno, PTR_TO_CALLNO, send_command_locked(), ast_channel::tech_pvt, and wait_for_peercallno().
03901 { 03902 struct ast_option_header *h; 03903 int res; 03904 03905 switch (option) { 03906 case AST_OPTION_TXGAIN: 03907 case AST_OPTION_RXGAIN: 03908 /* these two cannot be sent, because they require a result */ 03909 errno = ENOSYS; 03910 return -1; 03911 default: 03912 { 03913 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03914 struct chan_iax2_pvt *pvt; 03915 03916 ast_mutex_lock(&iaxsl[callno]); 03917 pvt = iaxs[callno]; 03918 03919 if (wait_for_peercallno(pvt)) { 03920 ast_mutex_unlock(&iaxsl[callno]); 03921 return -1; 03922 } 03923 03924 ast_mutex_unlock(&iaxsl[callno]); 03925 03926 if (!(h = ast_malloc(datalen + sizeof(*h)))) { 03927 return -1; 03928 } 03929 03930 h->flag = AST_OPTION_FLAG_REQUEST; 03931 h->option = htons(option); 03932 memcpy(h->data, data, datalen); 03933 res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL, 03934 AST_CONTROL_OPTION, 0, (unsigned char *) h, 03935 datalen + sizeof(*h), -1); 03936 ast_free(h); 03937 return res; 03938 } 03939 } 03940 }
static int iax2_start_transfer | ( | unsigned short | callno0, | |
unsigned short | callno1, | |||
int | mediaonly | |||
) | [static] |
Definition at line 3948 of file chan_iax2.c.
References AST_FRAME_IAX, ast_random(), IAX_COMMAND_TXREQ, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), IAX_IE_CALLNO, IAX_IE_TRANSFERID, send_command(), TRANSFER_BEGIN, and TRANSFER_MBEGIN.
03949 { 03950 int res; 03951 struct iax_ie_data ied0; 03952 struct iax_ie_data ied1; 03953 unsigned int transferid = (unsigned int)ast_random(); 03954 memset(&ied0, 0, sizeof(ied0)); 03955 iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr); 03956 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno); 03957 iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); 03958 03959 memset(&ied1, 0, sizeof(ied1)); 03960 iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr); 03961 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno); 03962 iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); 03963 03964 res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); 03965 if (res) 03966 return -1; 03967 res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); 03968 if (res) 03969 return -1; 03970 iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03971 iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03972 return 0; 03973 }
static int iax2_transfer | ( | struct ast_channel * | c, | |
const char * | dest | |||
) | [static] |
Definition at line 4198 of file chan_iax2.c.
References ast_copy_string(), ast_debug, AST_FRAME_IAX, chan_iax2_pvt::callno, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, ast_channel::name, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
04199 { 04200 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04201 struct iax_ie_data ied = { "", }; 04202 char tmp[256], *context; 04203 ast_copy_string(tmp, dest, sizeof(tmp)); 04204 context = strchr(tmp, '@'); 04205 if (context) { 04206 *context = '\0'; 04207 context++; 04208 } 04209 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp); 04210 if (context) 04211 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); 04212 ast_debug(1, "Transferring '%s' to '%s'\n", c->name, dest); 04213 return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); 04214 }
static int iax2_transmit | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 3155 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, iax2_trunk_peer::list, sched_lock, iax_frame::sentyet, and signal_condition().
Referenced by iax2_send().
03156 { 03157 /* Lock the queue and place this packet at the end */ 03158 /* By setting this to 0, the network thread will send it for us, and 03159 queue retransmission if necessary */ 03160 fr->sentyet = 0; 03161 AST_LIST_LOCK(&frame_queue); 03162 AST_LIST_INSERT_TAIL(&frame_queue, fr, list); 03163 AST_LIST_UNLOCK(&frame_queue); 03164 /* Wake up the network and scheduler thread */ 03165 if (netthreadid != AST_PTHREADT_NULL) 03166 pthread_kill(netthreadid, SIGURG); 03167 signal_condition(&sched_lock, &sched_cond); 03168 return 0; 03169 }
static int iax2_trunk_expired | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [inline, static] |
Definition at line 7543 of file chan_iax2.c.
References iax2_trunk_peer::trunkact.
Referenced by timing_read().
07544 { 07545 /* Drop when trunk is about 5 seconds idle */ 07546 if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 07547 return 1; 07548 return 0; 07549 }
static int iax2_trunk_queue | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_frame * | fr | |||
) | [static] |
Definition at line 4603 of file chan_iax2.c.
References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_tvnow(), ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, DEFAULT_TRUNKDATA, f, find_tpeer(), globalflags, IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, ast_iax2_meta_trunk_mini::mini, send_trunk(), chan_iax2_pvt::sockfd, iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdataalloc, iax2_trunk_peer::trunkdatalen, iax_frame::ts, and ast_iax2_mini_hdr::ts.
Referenced by iax2_send().
04604 { 04605 struct ast_frame *f; 04606 struct iax2_trunk_peer *tpeer; 04607 void *tmp, *ptr; 04608 struct timeval now; 04609 int res; 04610 struct ast_iax2_meta_trunk_entry *met; 04611 struct ast_iax2_meta_trunk_mini *mtm; 04612 04613 f = &fr->af; 04614 tpeer = find_tpeer(&pvt->addr, pvt->sockfd); 04615 if (tpeer) { 04616 if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) { 04617 /* Need to reallocate space */ 04618 if (tpeer->trunkdataalloc < trunkmaxsize) { 04619 if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) { 04620 ast_mutex_unlock(&tpeer->lock); 04621 return -1; 04622 } 04623 04624 tpeer->trunkdataalloc += DEFAULT_TRUNKDATA; 04625 tpeer->trunkdata = tmp; 04626 ast_debug(1, "Expanded trunk '%s:%d' to %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), tpeer->trunkdataalloc); 04627 } else { 04628 ast_log(LOG_WARNING, "Maximum trunk data space exceeded to %s:%d\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 04629 ast_mutex_unlock(&tpeer->lock); 04630 return -1; 04631 } 04632 } 04633 04634 /* Append to meta frame */ 04635 ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen; 04636 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) { 04637 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 04638 mtm->len = htons(f->datalen); 04639 mtm->mini.callno = htons(pvt->callno); 04640 mtm->mini.ts = htons(0xffff & fr->ts); 04641 ptr += sizeof(struct ast_iax2_meta_trunk_mini); 04642 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini); 04643 } else { 04644 met = (struct ast_iax2_meta_trunk_entry *)ptr; 04645 /* Store call number and length in meta header */ 04646 met->callno = htons(pvt->callno); 04647 met->len = htons(f->datalen); 04648 /* Advance pointers/decrease length past trunk entry header */ 04649 ptr += sizeof(struct ast_iax2_meta_trunk_entry); 04650 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry); 04651 } 04652 /* Copy actual trunk data */ 04653 memcpy(ptr, f->data, f->datalen); 04654 tpeer->trunkdatalen += f->datalen; 04655 04656 tpeer->calls++; 04657 04658 /* track the largest mtu we actually have sent */ 04659 if (tpeer->trunkdatalen + f->datalen + 4 > trunk_maxmtu) 04660 trunk_maxmtu = tpeer->trunkdatalen + f->datalen + 4 ; 04661 04662 /* if we have enough for a full MTU, ship it now without waiting */ 04663 if (global_max_trunk_mtu > 0 && tpeer->trunkdatalen + f->datalen + 4 >= global_max_trunk_mtu) { 04664 now = ast_tvnow(); 04665 res = send_trunk(tpeer, &now); 04666 trunk_untimed ++; 04667 } 04668 04669 ast_mutex_unlock(&tpeer->lock); 04670 } 04671 return 0; 04672 }
static int iax2_vnak | ( | int | callno | ) | [static] |
Definition at line 7461 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_VNAK, and send_command_immediate().
Referenced by socket_process(), and socket_process_meta().
07462 { 07463 return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno); 07464 }
static int iax2_write | ( | struct ast_channel * | c, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 5907 of file chan_iax2.c.
References ast_debug, AST_FRAME_NULL, AST_FRAME_VOICE, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, iax2_registry::callno, errno, f, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, PTR_TO_CALLNO, and ast_channel::tech_pvt.
05908 { 05909 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 05910 int res = -1; 05911 ast_mutex_lock(&iaxsl[callno]); 05912 if (iaxs[callno]) { 05913 /* If there's an outstanding error, return failure now */ 05914 if (!iaxs[callno]->error) { 05915 if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) 05916 res = 0; 05917 /* Don't waste bandwidth sending null frames */ 05918 else if (f->frametype == AST_FRAME_NULL) 05919 res = 0; 05920 else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH)) 05921 res = 0; 05922 else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 05923 res = 0; 05924 else 05925 /* Simple, just queue for transmission */ 05926 res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0); 05927 } else { 05928 ast_debug(1, "Write error: %s\n", strerror(errno)); 05929 } 05930 } 05931 /* If it's already gone, just return */ 05932 ast_mutex_unlock(&iaxsl[callno]); 05933 return res; 05934 }
static int iax_check_version | ( | char * | dev | ) | [static] |
Definition at line 2103 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_iax2_firmware_header::devname, iax_firmware::fwh, iax2_trunk_peer::list, and ast_iax2_firmware_header::version.
Referenced by update_registry().
02104 { 02105 int res = 0; 02106 struct iax_firmware *cur = NULL; 02107 02108 if (ast_strlen_zero(dev)) 02109 return 0; 02110 02111 AST_LIST_LOCK(&firmwares); 02112 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02113 if (!strcmp(dev, (char *)cur->fwh->devname)) { 02114 res = ntohs(cur->fwh->version); 02115 break; 02116 } 02117 } 02118 AST_LIST_UNLOCK(&firmwares); 02119 02120 return res; 02121 }
static void iax_debug_output | ( | const char * | data | ) | [static] |
Definition at line 797 of file chan_iax2.c.
References ast_verbose().
Referenced by load_module().
00798 { 00799 if (iaxdebug) 00800 ast_verbose("%s", data); 00801 }
static void iax_error_output | ( | const char * | data | ) | [static] |
Definition at line 803 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00804 { 00805 ast_log(LOG_WARNING, "%s", data); 00806 }
static int iax_firmware_append | ( | struct iax_ie_data * | ied, | |
const unsigned char * | dev, | |||
unsigned int | desc | |||
) | [static] |
Definition at line 2123 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, iax_firmware::fwh, iax_ie_append(), iax_ie_append_int(), iax_ie_append_raw(), IAX_IE_FWBLOCKDATA, IAX_IE_FWBLOCKDESC, and iax2_trunk_peer::list.
Referenced by socket_process().
02124 { 02125 int res = -1; 02126 unsigned int bs = desc & 0xff; 02127 unsigned int start = (desc >> 8) & 0xffffff; 02128 unsigned int bytes; 02129 struct iax_firmware *cur; 02130 02131 if (ast_strlen_zero((char *)dev) || !bs) 02132 return -1; 02133 02134 start *= bs; 02135 02136 AST_LIST_LOCK(&firmwares); 02137 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02138 if (strcmp((char *)dev, (char *)cur->fwh->devname)) 02139 continue; 02140 iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc); 02141 if (start < ntohl(cur->fwh->datalen)) { 02142 bytes = ntohl(cur->fwh->datalen) - start; 02143 if (bytes > bs) 02144 bytes = bs; 02145 iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes); 02146 } else { 02147 bytes = 0; 02148 iax_ie_append(ied, IAX_IE_FWBLOCKDATA); 02149 } 02150 if (bytes == bs) 02151 res = 0; 02152 else 02153 res = 1; 02154 break; 02155 } 02156 AST_LIST_UNLOCK(&firmwares); 02157 02158 return res; 02159 }
static int iax_park | ( | struct ast_channel * | chan1, | |
struct ast_channel * | chan2 | |||
) | [static] |
Definition at line 7720 of file chan_iax2.c.
References ast_channel::accountcode, ast_channel::amaflags, ast_calloc, ast_channel_alloc, ast_channel_masquerade(), ast_copy_string(), ast_do_masquerade(), ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached_background, AST_STATE_DOWN, ast_channel::context, ast_channel::exten, iax_park_thread(), LOG_WARNING, ast_channel::name, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by socket_process().
07721 { 07722 struct iax_dual *d; 07723 struct ast_channel *chan1m, *chan2m; 07724 pthread_t th; 07725 chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 07726 chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name); 07727 if (chan2m && chan1m) { 07728 /* Make formats okay */ 07729 chan1m->readformat = chan1->readformat; 07730 chan1m->writeformat = chan1->writeformat; 07731 ast_channel_masquerade(chan1m, chan1); 07732 /* Setup the extensions and such */ 07733 ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context)); 07734 ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten)); 07735 chan1m->priority = chan1->priority; 07736 07737 /* We make a clone of the peer channel too, so we can play 07738 back the announcement */ 07739 /* Make formats okay */ 07740 chan2m->readformat = chan2->readformat; 07741 chan2m->writeformat = chan2->writeformat; 07742 ast_channel_masquerade(chan2m, chan2); 07743 /* Setup the extensions and such */ 07744 ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context)); 07745 ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten)); 07746 chan2m->priority = chan2->priority; 07747 if (ast_do_masquerade(chan2m)) { 07748 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 07749 ast_hangup(chan2m); 07750 return -1; 07751 } 07752 } else { 07753 if (chan1m) 07754 ast_hangup(chan1m); 07755 if (chan2m) 07756 ast_hangup(chan2m); 07757 return -1; 07758 } 07759 if ((d = ast_calloc(1, sizeof(*d)))) { 07760 d->chan1 = chan1m; 07761 d->chan2 = chan2m; 07762 if (!ast_pthread_create_detached_background(&th, NULL, iax_park_thread, d)) { 07763 return 0; 07764 } 07765 ast_free(d); 07766 } 07767 return -1; 07768 }
static void* iax_park_thread | ( | void * | stuff | ) | [static] |
Definition at line 7700 of file chan_iax2.c.
References ast_free, ast_frfree, ast_hangup(), ast_log(), ast_park_call(), ast_read(), iax_dual::chan1, iax_dual::chan2, ext, f, and LOG_NOTICE.
Referenced by iax_park().
07701 { 07702 struct ast_channel *chan1, *chan2; 07703 struct iax_dual *d; 07704 struct ast_frame *f; 07705 int ext; 07706 int res; 07707 d = stuff; 07708 chan1 = d->chan1; 07709 chan2 = d->chan2; 07710 ast_free(d); 07711 f = ast_read(chan1); 07712 if (f) 07713 ast_frfree(f); 07714 res = ast_park_call(chan1, chan2, 0, &ext); 07715 ast_hangup(chan2); 07716 ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext); 07717 return NULL; 07718 }
Definition at line 1522 of file chan_iax2.c.
References iax_frame::af, iax_frame::afdatalen, iax_frame::cacheable, ast_frame::datalen, DIRECTION_INGRESS, iax_frame_new(), and iax_frame_wrap().
Referenced by socket_process(), and socket_process_meta().
01523 { 01524 struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable); 01525 if (new) { 01526 size_t afdatalen = new->afdatalen; 01527 memcpy(new, fr, sizeof(*new)); 01528 iax_frame_wrap(new, &fr->af); 01529 new->afdatalen = afdatalen; 01530 new->data = NULL; 01531 new->datalen = 0; 01532 new->direction = DIRECTION_INGRESS; 01533 new->retrans = -1; 01534 } 01535 return new; 01536 }
static void insert_idle_thread | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 1045 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, IAX_THREAD_TYPE_DYNAMIC, iax2_trunk_peer::list, and thread.
Referenced by iax2_process_thread().
01046 { 01047 if (thread->type == IAX_THREAD_TYPE_DYNAMIC) { 01048 AST_LIST_LOCK(&dynamic_list); 01049 AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); 01050 AST_LIST_UNLOCK(&dynamic_list); 01051 } else { 01052 AST_LIST_LOCK(&idle_list); 01053 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 01054 AST_LIST_UNLOCK(&idle_list); 01055 } 01056 01057 return; 01058 }
static void jb_debug_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 832 of file chan_iax2.c.
References ast_verbose().
Referenced by handle_cli_iax2_set_debug_jb(), and handle_cli_iax2_set_debug_jb_deprecated().
00833 { 00834 va_list args; 00835 char buf[1024]; 00836 00837 va_start(args, fmt); 00838 vsnprintf(buf, sizeof(buf), fmt, args); 00839 va_end(args); 00840 00841 ast_verbose("%s", buf); 00842 }
static void jb_error_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 808 of file chan_iax2.c.
References ast_log(), and LOG_ERROR.
Referenced by handle_cli_iax2_set_debug_jb(), handle_cli_iax2_set_debug_jb_deprecated(), and load_module().
00809 { 00810 va_list args; 00811 char buf[1024]; 00812 00813 va_start(args, fmt); 00814 vsnprintf(buf, sizeof(buf), fmt, args); 00815 va_end(args); 00816 00817 ast_log(LOG_ERROR, "%s", buf); 00818 }
static void jb_warning_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 820 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by handle_cli_iax2_set_debug_jb(), handle_cli_iax2_set_debug_jb_deprecated(), and load_module().
00821 { 00822 va_list args; 00823 char buf[1024]; 00824 00825 va_start(args, fmt); 00826 vsnprintf(buf, sizeof(buf), fmt, args); 00827 va_end(args); 00828 00829 ast_log(LOG_WARNING, "%s", buf); 00830 }
static int load_module | ( | void | ) | [static] |
Load IAX2 module, load configuraiton ---.
Definition at line 12398 of file chan_iax2.c.
References __unload_module(), ao2_callback(), ao2_container_alloc(), ao2_ref(), ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_register_application, ast_register_switch(), ast_verb, cli_iax2, config, iax2_registry::entry, errno, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, iax2_do_register(), iax2_poke_peer_cb(), iax2_prov_app(), iax2_switch, iax2_tech, iax_debug_output(), iax_error_output(), IAX_MAX_CALLS, iax_peercallno_pvts, iax_provision_reload(), iax_set_error(), iax_set_output(), iax_transfercallno_pvts, iaxpeer_function, iaxvar_function, io, io_context_create(), io_context_destroy(), jb_error_output(), jb_setoutput(), jb_warning_output(), LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), MAX_PEER_BUCKETS, MAX_USER_BUCKETS, netsock, outsock, papp, pdescrip, peer_cmp_cb(), peer_hash_cb(), peer_set_sock_cb(), psyn, pvt_cmp_cb(), pvt_hash_cb(), reload_firmware(), sched, sched_context_create(), sched_context_destroy(), set_config(), start_network_thread(), transfercallno_pvt_cmp_cb(), transfercallno_pvt_hash_cb(), user_cmp_cb(), and user_hash_cb().
12399 { 12400 char *config = "iax.conf"; 12401 int x = 0; 12402 struct iax2_registry *reg = NULL; 12403 12404 peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb); 12405 if (!peers) 12406 return AST_MODULE_LOAD_FAILURE; 12407 users = ao2_container_alloc(MAX_USER_BUCKETS, user_hash_cb, user_cmp_cb); 12408 if (!users) { 12409 ao2_ref(peers, -1); 12410 return AST_MODULE_LOAD_FAILURE; 12411 } 12412 iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb); 12413 if (!iax_peercallno_pvts) { 12414 ao2_ref(peers, -1); 12415 ao2_ref(users, -1); 12416 return AST_MODULE_LOAD_FAILURE; 12417 } 12418 iax_transfercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, transfercallno_pvt_hash_cb, transfercallno_pvt_cmp_cb); 12419 if (!iax_transfercallno_pvts) { 12420 ao2_ref(peers, -1); 12421 ao2_ref(users, -1); 12422 ao2_ref(iax_peercallno_pvts, -1); 12423 return AST_MODULE_LOAD_FAILURE; 12424 } 12425 ast_custom_function_register(&iaxpeer_function); 12426 ast_custom_function_register(&iaxvar_function); 12427 12428 iax_set_output(iax_debug_output); 12429 iax_set_error(iax_error_output); 12430 jb_setoutput(jb_error_output, jb_warning_output, NULL); 12431 12432 #ifdef HAVE_DAHDI 12433 #ifdef DAHDI_TIMERACK 12434 timingfd = open("/dev/dahdi/timer", O_RDWR); 12435 if (timingfd < 0) 12436 #endif 12437 timingfd = open("/dev/dahdi/pseudo", O_RDWR); 12438 if (timingfd < 0) 12439 ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno)); 12440 #endif 12441 12442 memset(iaxs, 0, sizeof(iaxs)); 12443 12444 for (x = 0; x < ARRAY_LEN(iaxsl); x++) { 12445 ast_mutex_init(&iaxsl[x]); 12446 } 12447 12448 ast_cond_init(&sched_cond, NULL); 12449 12450 if (!(sched = sched_context_create())) { 12451 ast_log(LOG_ERROR, "Failed to create scheduler context\n"); 12452 return AST_MODULE_LOAD_FAILURE; 12453 } 12454 12455 if (!(io = io_context_create())) { 12456 ast_log(LOG_ERROR, "Failed to create I/O context\n"); 12457 sched_context_destroy(sched); 12458 return AST_MODULE_LOAD_FAILURE; 12459 } 12460 12461 if (!(netsock = ast_netsock_list_alloc())) { 12462 ast_log(LOG_ERROR, "Failed to create netsock list\n"); 12463 io_context_destroy(io); 12464 sched_context_destroy(sched); 12465 return AST_MODULE_LOAD_FAILURE; 12466 } 12467 ast_netsock_init(netsock); 12468 12469 outsock = ast_netsock_list_alloc(); 12470 if (!outsock) { 12471 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 12472 io_context_destroy(io); 12473 sched_context_destroy(sched); 12474 return AST_MODULE_LOAD_FAILURE; 12475 } 12476 ast_netsock_init(outsock); 12477 12478 ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 12479 12480 ast_register_application(papp, iax2_prov_app, psyn, pdescrip); 12481 12482 ast_manager_register( "IAXpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peers, "List IAX Peers" ); 12483 ast_manager_register( "IAXpeerlist", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_peer_list, "List IAX Peers" ); 12484 ast_manager_register( "IAXnetstats", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_iax2_show_netstats, "Show IAX Netstats" ); 12485 12486 if(set_config(config, 0) == -1) 12487 return AST_MODULE_LOAD_DECLINE; 12488 12489 if (ast_channel_register(&iax2_tech)) { 12490 ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2"); 12491 __unload_module(); 12492 return AST_MODULE_LOAD_FAILURE; 12493 } 12494 12495 if (ast_register_switch(&iax2_switch)) 12496 ast_log(LOG_ERROR, "Unable to register IAX switch\n"); 12497 12498 if (start_network_thread()) { 12499 ast_log(LOG_ERROR, "Unable to start network thread\n"); 12500 __unload_module(); 12501 return AST_MODULE_LOAD_FAILURE; 12502 } else 12503 ast_verb(2, "IAX Ready and Listening\n"); 12504 12505 AST_LIST_LOCK(®istrations); 12506 AST_LIST_TRAVERSE(®istrations, reg, entry) 12507 iax2_do_register(reg); 12508 AST_LIST_UNLOCK(®istrations); 12509 12510 ao2_callback(peers, 0, peer_set_sock_cb, NULL); 12511 ao2_callback(peers, 0, iax2_poke_peer_cb, NULL); 12512 12513 12514 reload_firmware(0); 12515 iax_provision_reload(0); 12516 12517 return AST_MODULE_LOAD_SUCCESS; 12518 }
static void lock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3975 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), and DEADLOCK_AVOIDANCE.
Referenced by iax2_bridge().
03976 { 03977 ast_mutex_lock(&iaxsl[callno0]); 03978 while (ast_mutex_trylock(&iaxsl[callno1])) { 03979 DEADLOCK_AVOIDANCE(&iaxsl[callno0]); 03980 } 03981 }
static void log_jitterstats | ( | unsigned short | callno | ) | [static] |
Definition at line 7843 of file chan_iax2.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, jb_info::current, EVENT_FLAG_REPORTING, jb_info::frames_dropped, jb_info::frames_in, jb_info::frames_lost, jb_info::frames_ooo, IAX_USEJITTERBUF, ast_channel::jb, jb_getinfo(), jb_info::jitter, jb_info::losspct, manager_event, and jb_info::min.
Referenced by socket_process().
07844 { 07845 int localjitter = -1, localdelay = 0, locallost = -1, locallosspct = -1, localdropped = 0, localooo = -1, localpackets = -1; 07846 jb_info jbinfo; 07847 07848 ast_mutex_lock(&iaxsl[callno]); 07849 if (iaxs[callno] && iaxs[callno]->owner && iaxs[callno]->owner->name) { 07850 if(ast_test_flag(iaxs[callno], IAX_USEJITTERBUF)) { 07851 jb_getinfo(iaxs[callno]->jb, &jbinfo); 07852 localjitter = jbinfo.jitter; 07853 localdelay = jbinfo.current - jbinfo.min; 07854 locallost = jbinfo.frames_lost; 07855 locallosspct = jbinfo.losspct/1000; 07856 localdropped = jbinfo.frames_dropped; 07857 localooo = jbinfo.frames_ooo; 07858 localpackets = jbinfo.frames_in; 07859 } 07860 ast_debug(3, "JB STATS:%s ping=%d ljitterms=%d ljbdelayms=%d ltotlost=%d lrecentlosspct=%d ldropped=%d looo=%d lrecvd=%d rjitterms=%d rjbdelayms=%d rtotlost=%d rrecentlosspct=%d rdropped=%d rooo=%d rrecvd=%d\n", 07861 iaxs[callno]->owner->name, 07862 iaxs[callno]->pingtime, 07863 localjitter, 07864 localdelay, 07865 locallost, 07866 locallosspct, 07867 localdropped, 07868 localooo, 07869 localpackets, 07870 iaxs[callno]->remote_rr.jitter, 07871 iaxs[callno]->remote_rr.delay, 07872 iaxs[callno]->remote_rr.losscnt, 07873 iaxs[callno]->remote_rr.losspct/1000, 07874 iaxs[callno]->remote_rr.dropped, 07875 iaxs[callno]->remote_rr.ooo, 07876 iaxs[callno]->remote_rr.packets); 07877 manager_event(EVENT_FLAG_REPORTING, "JitterBufStats", "Owner: %s\r\nPing: %d\r\nLocalJitter: %d\r\nLocalJBDelay: %d\r\nLocalTotalLost: %d\r\nLocalLossPercent: %d\r\nLocalDropped: %d\r\nLocalooo: %d\r\nLocalReceived: %d\r\nRemoteJitter: %d\r\nRemoteJBDelay: %d\r\nRemoteTotalLost: %d\r\nRemoteLossPercent: %d\r\nRemoteDropped: %d\r\nRemoteooo: %d\r\nRemoteReceived: %d\r\n", 07878 iaxs[callno]->owner->name, 07879 iaxs[callno]->pingtime, 07880 localjitter, 07881 localdelay, 07882 locallost, 07883 locallosspct, 07884 localdropped, 07885 localooo, 07886 localpackets, 07887 iaxs[callno]->remote_rr.jitter, 07888 iaxs[callno]->remote_rr.delay, 07889 iaxs[callno]->remote_rr.losscnt, 07890 iaxs[callno]->remote_rr.losspct/1000, 07891 iaxs[callno]->remote_rr.dropped, 07892 iaxs[callno]->remote_rr.ooo, 07893 iaxs[callno]->remote_rr.packets); 07894 } 07895 ast_mutex_unlock(&iaxsl[callno]); 07896 }
static int make_trunk | ( | unsigned short | callno, | |
int | locked | |||
) | [static] |
Definition at line 1593 of file chan_iax2.c.
References ARRAY_LEN, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, ast_tvnow(), iax2_sched_add(), LOG_WARNING, MIN_REUSE_TIME, sched, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().
Referenced by iax2_request(), and socket_process().
01594 { 01595 int x; 01596 int res= 0; 01597 struct timeval now = ast_tvnow(); 01598 if (iaxs[callno]->oseqno) { 01599 ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n"); 01600 return -1; 01601 } 01602 if (callno & TRUNK_CALL_START) { 01603 ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno); 01604 return -1; 01605 } 01606 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01607 ast_mutex_lock(&iaxsl[x]); 01608 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01609 /*! 01610 * \note We delete these before switching the slot, because if 01611 * they fire in the meantime, they will generate a warning. 01612 */ 01613 AST_SCHED_DEL(sched, iaxs[callno]->pingid); 01614 AST_SCHED_DEL(sched, iaxs[callno]->lagid); 01615 iaxs[x] = iaxs[callno]; 01616 iaxs[x]->callno = x; 01617 iaxs[callno] = NULL; 01618 /* Update the two timers that should have been started */ 01619 iaxs[x]->pingid = iax2_sched_add(sched, 01620 ping_time * 1000, send_ping, (void *)(long)x); 01621 iaxs[x]->lagid = iax2_sched_add(sched, 01622 lagrq_time * 1000, send_lagrq, (void *)(long)x); 01623 if (locked) 01624 ast_mutex_unlock(&iaxsl[callno]); 01625 res = x; 01626 if (!locked) 01627 ast_mutex_unlock(&iaxsl[x]); 01628 break; 01629 } 01630 ast_mutex_unlock(&iaxsl[x]); 01631 } 01632 if (x >= ARRAY_LEN(iaxs) - 1) { 01633 ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n"); 01634 return -1; 01635 } 01636 ast_debug(1, "Made call %d into trunk call %d\n", callno, x); 01637 /* We move this call from a non-trunked to a trunked call */ 01638 update_max_trunk(); 01639 update_max_nontrunk(); 01640 return res; 01641 }
static int manager_iax2_show_netstats | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 5423 of file chan_iax2.c.
References ast_cli_netstats(), astman_append(), RESULT_SUCCESS, and s.
Referenced by load_module().
05424 { 05425 ast_cli_netstats(s, -1, 0); 05426 astman_append(s, "\r\n"); 05427 return RESULT_SUCCESS; 05428 }
static int manager_iax2_show_peer_list | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
callback to display iax peers in manager format
Definition at line 5475 of file chan_iax2.c.
References iax2_peer::addr, ao2_iterator_init(), ao2_iterator_next(), ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), IAX_DYNAMIC, iax2_peer::mask, iax2_peer::name, peer_status(), peer_unref(), RESULT_SUCCESS, s, status, and iax2_peer::username.
Referenced by load_module().
05476 { 05477 struct iax2_peer *peer = NULL; 05478 int peer_count = 0; 05479 char nm[20]; 05480 char status[20]; 05481 const char *id = astman_get_header(m,"ActionID"); 05482 char idtext[256] = ""; 05483 struct ao2_iterator i; 05484 05485 if (!ast_strlen_zero(id)) 05486 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05487 05488 astman_append(s, "Response: Success\r\n%sMessage: IAX Peer status list will follow\r\n\r\n", idtext); 05489 05490 05491 i = ao2_iterator_init(peers, 0); 05492 for (peer = ao2_iterator_next(&i); peer; peer_unref(peer), peer = ao2_iterator_next(&i)) { 05493 05494 astman_append(s, "Event: PeerEntry\r\n%sChanneltype: IAX\r\n", idtext); 05495 if (!ast_strlen_zero(peer->username)) { 05496 astman_append(s, "ObjectName: %s\r\nObjectUsername: %s\r\n", peer->name, peer->username); 05497 } else { 05498 astman_append(s, "ObjectName: %s\r\n", peer->name); 05499 } 05500 astman_append(s, "ChanObjectType: peer\r\n"); 05501 astman_append(s, "IPaddress: %s\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-"); 05502 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 05503 astman_append(s, "Mask: %s\r\n", nm); 05504 astman_append(s, "Port: %d\r\n", ntohs(peer->addr.sin_port)); 05505 astman_append(s, "Dynamic: %s\r\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No"); 05506 peer_status(peer, status, sizeof(status)); 05507 astman_append(s, "Status: %s\r\n\r\n", status); 05508 peer_count++; 05509 } 05510 05511 astman_append(s, "Event: PeerlistComplete\r\n%sListItems: %d\r\n\r\n", idtext, peer_count); 05512 return RESULT_SUCCESS; 05513 }
static int manager_iax2_show_peers | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
callback to display iax peers in manager
Definition at line 5462 of file chan_iax2.c.
References __iax2_show_peers(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), and s.
Referenced by load_module().
05463 { 05464 char *a[] = { "iax2", "show", "users" }; 05465 const char *id = astman_get_header(m,"ActionID"); 05466 char idtext[256] = ""; 05467 05468 if (!ast_strlen_zero(id)) 05469 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 05470 astman_send_ack(s, m, "Peer status list will follow"); 05471 return __iax2_show_peers(1, -1, s, 3, a ); 05472 }
static int match | ( | struct sockaddr_in * | sin, | |
unsigned short | callno, | |||
unsigned short | dcallno, | |||
const struct chan_iax2_pvt * | cur, | |||
int | check_dcallno | |||
) | [static] |
Definition at line 1542 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::callno, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, chan_iax2_pvt::transfercallno, and chan_iax2_pvt::transferring.
Referenced by __find_callno(), ao2_callback(), ast_parse_device_state(), check_blacklist(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), lua_find_extension(), pbx_find_extension(), pvt_cmp_cb(), realtime_switch_common(), and transfercallno_pvt_cmp_cb().
01543 { 01544 if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && 01545 (cur->addr.sin_port == sin->sin_port)) { 01546 /* This is the main host */ 01547 if ( (cur->peercallno == 0 || cur->peercallno == callno) && 01548 (check_dcallno ? dcallno == cur->callno : 1) ) { 01549 /* That's us. Be sure we keep track of the peer call number */ 01550 return 1; 01551 } 01552 } 01553 if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && 01554 (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { 01555 /* We're transferring */ 01556 if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno)) 01557 return 1; 01558 } 01559 return 0; 01560 }
static void memcpy_decrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
ast_aes_decrypt_key * | dcx | |||
) | [static] |
Definition at line 4702 of file chan_iax2.c.
References ast_aes_decrypt, ast_log(), and LOG_WARNING.
Referenced by decode_frame().
04703 { 04704 #if 0 04705 /* Debug with "fake encryption" */ 04706 int x; 04707 if (len % 16) 04708 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04709 for (x=0;x<len;x++) 04710 dst[x] = src[x] ^ 0xff; 04711 #else 04712 unsigned char lastblock[16] = { 0 }; 04713 int x; 04714 while(len > 0) { 04715 ast_aes_decrypt(src, dst, dcx); 04716 for (x=0;x<16;x++) 04717 dst[x] ^= lastblock[x]; 04718 memcpy(lastblock, src, sizeof(lastblock)); 04719 dst += 16; 04720 src += 16; 04721 len -= 16; 04722 } 04723 #endif 04724 }
static void memcpy_encrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
ast_aes_encrypt_key * | ecx | |||
) | [static] |
Definition at line 4726 of file chan_iax2.c.
References ast_aes_encrypt, ast_log(), and LOG_WARNING.
Referenced by encrypt_frame().
04727 { 04728 #if 0 04729 /* Debug with "fake encryption" */ 04730 int x; 04731 if (len % 16) 04732 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 04733 for (x=0;x<len;x++) 04734 dst[x] = src[x] ^ 0xff; 04735 #else 04736 unsigned char curblock[16] = { 0 }; 04737 int x; 04738 while(len > 0) { 04739 for (x=0;x<16;x++) 04740 curblock[x] ^= src[x]; 04741 ast_aes_encrypt(curblock, dst, ecx); 04742 memcpy(curblock, dst, sizeof(curblock)); 04743 dst += 16; 04744 src += 16; 04745 len -= 16; 04746 } 04747 #endif 04748 }
static void merge_encryption | ( | struct chan_iax2_pvt * | p, | |
unsigned int | enc | |||
) | [static] |
Definition at line 6242 of file chan_iax2.c.
References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.
Referenced by authenticate_reply(), and socket_process().
06243 { 06244 /* Select exactly one common encryption if there are any */ 06245 p->encmethods &= enc; 06246 if (p->encmethods) { 06247 if (p->encmethods & IAX_ENCRYPT_AES128) 06248 p->encmethods = IAX_ENCRYPT_AES128; 06249 else 06250 p->encmethods = 0; 06251 } 06252 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 979 of file chan_iax2.c.
00980 { 00981 /* The MWI subscriptions exist just so the core knows we care about those 00982 * mailboxes. However, we just grab the events out of the cache when it 00983 * is time to send MWI, since it is only sent with a REGACK. */ 00984 }
static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 10362 of file chan_iax2.c.
References ast_debug, ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_mutex_trylock(), ast_mutex_unlock(), attempt_transmit(), f, iax2_sched_add(), iax_frame_free(), io, iax_frame::list, sched, send_packet(), and timing_read().
Referenced by start_network_thread().
10363 { 10364 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 10365 from the network, and queue them for delivery to the channels */ 10366 int res, count, wakeup; 10367 struct iax_frame *f; 10368 10369 if (timingfd > -1) 10370 ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL); 10371 10372 for(;;) { 10373 pthread_testcancel(); 10374 10375 /* Go through the queue, sending messages which have not yet been 10376 sent, and scheduling retransmissions if appropriate */ 10377 AST_LIST_LOCK(&frame_queue); 10378 count = 0; 10379 wakeup = -1; 10380 AST_LIST_TRAVERSE_SAFE_BEGIN(&frame_queue, f, list) { 10381 if (f->sentyet) 10382 continue; 10383 10384 /* Try to lock the pvt, if we can't... don't fret - defer it till later */ 10385 if (ast_mutex_trylock(&iaxsl[f->callno])) { 10386 wakeup = 1; 10387 continue; 10388 } 10389 10390 f->sentyet = 1; 10391 10392 if (iaxs[f->callno]) { 10393 send_packet(f); 10394 count++; 10395 } 10396 10397 ast_mutex_unlock(&iaxsl[f->callno]); 10398 10399 if (f->retries < 0) { 10400 /* This is not supposed to be retransmitted */ 10401 AST_LIST_REMOVE_CURRENT(list); 10402 /* Free the iax frame */ 10403 iax_frame_free(f); 10404 } else { 10405 /* We need reliable delivery. Schedule a retransmission */ 10406 f->retries++; 10407 f->retrans = iax2_sched_add(sched, f->retrytime, attempt_transmit, f); 10408 } 10409 } 10410 AST_LIST_TRAVERSE_SAFE_END; 10411 AST_LIST_UNLOCK(&frame_queue); 10412 10413 pthread_testcancel(); 10414 if (count >= 20) 10415 ast_debug(1, "chan_iax2: Sent %d queued outbound frames all at once\n", count); 10416 10417 /* Now do the IO, and run scheduled tasks */ 10418 res = ast_io_wait(io, wakeup); 10419 if (res >= 0) { 10420 if (res >= 20) 10421 ast_debug(1, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res); 10422 } 10423 } 10424 return NULL; 10425 }
static struct chan_iax2_pvt* new_iax | ( | struct sockaddr_in * | sin, | |
const char * | host | |||
) | [static] |
Definition at line 1484 of file chan_iax2.c.
References ao2_alloc(), ao2_ref(), AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, ast_string_field_set, exten, jb_new(), jb_setconf(), jb_conf::max_contig_interp, jb_conf::max_jitterbuf, prefs, pvt_destructor(), jb_conf::resync_threshold, and jb_conf::target_extra.
Referenced by __find_callno().
01485 { 01486 struct chan_iax2_pvt *tmp; 01487 jb_conf jbconf; 01488 01489 if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) { 01490 return NULL; 01491 } 01492 01493 if (ast_string_field_init(tmp, 32)) { 01494 ao2_ref(tmp, -1); 01495 tmp = NULL; 01496 return NULL; 01497 } 01498 01499 tmp->prefs = prefs; 01500 tmp->pingid = -1; 01501 tmp->lagid = -1; 01502 tmp->autoid = -1; 01503 tmp->authid = -1; 01504 tmp->initid = -1; 01505 01506 ast_string_field_set(tmp,exten, "s"); 01507 ast_string_field_set(tmp,host, host); 01508 01509 tmp->jb = jb_new(); 01510 tmp->jbid = -1; 01511 jbconf.max_jitterbuf = maxjitterbuffer; 01512 jbconf.resync_threshold = resyncthreshold; 01513 jbconf.max_contig_interp = maxjitterinterps; 01514 jbconf.target_extra = jittertargetextra; 01515 jb_setconf(tmp->jb,&jbconf); 01516 01517 AST_LIST_HEAD_INIT_NOLOCK(&tmp->dpentries); 01518 01519 return tmp; 01520 }
static void parse_dial_string | ( | char * | data, | |
struct parsed_dial_string * | pds | |||
) | [static] |
Parses an IAX dial string into its component parts.
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 3602 of file chan_iax2.c.
References ast_strip_quoted(), ast_strlen_zero(), parsed_dial_string::context, parsed_dial_string::exten, parsed_dial_string::key, parsed_dial_string::options, parsed_dial_string::password, parsed_dial_string::peer, parsed_dial_string::port, strsep(), and parsed_dial_string::username.
Referenced by cache_get_callno_locked(), iax2_call(), iax2_devicestate(), and iax2_request().
03603 { 03604 if (ast_strlen_zero(data)) 03605 return; 03606 03607 pds->peer = strsep(&data, "/"); 03608 pds->exten = strsep(&data, "/"); 03609 pds->options = data; 03610 03611 if (pds->exten) { 03612 data = pds->exten; 03613 pds->exten = strsep(&data, "@"); 03614 pds->context = data; 03615 } 03616 03617 if (strchr(pds->peer, '@')) { 03618 data = pds->peer; 03619 pds->username = strsep(&data, "@"); 03620 pds->peer = data; 03621 } 03622 03623 if (pds->username) { 03624 data = pds->username; 03625 pds->username = strsep(&data, ":"); 03626 pds->password = data; 03627 } 03628 03629 data = pds->peer; 03630 pds->peer = strsep(&data, ":"); 03631 pds->port = data; 03632 03633 /* check for a key name wrapped in [] in the secret position, if found, 03634 move it to the key field instead 03635 */ 03636 if (pds->password && (pds->password[0] == '[')) { 03637 pds->key = ast_strip_quoted(pds->password, "[", "]"); 03638 pds->password = NULL; 03639 } 03640 }
static int peer_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1290 of file chan_iax2.c.
References CMP_MATCH, and iax2_peer::name.
Referenced by load_module().
01291 { 01292 struct iax2_peer *peer = obj, *peer2 = arg; 01293 01294 return !strcmp(peer->name, peer2->name) ? CMP_MATCH : 0; 01295 }
static int peer_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11059 of file chan_iax2.c.
References ast_set_flag, and IAX_DELME.
Referenced by delete_users().
11060 { 11061 struct iax2_peer *peer = obj; 11062 11063 ast_set_flag(peer, IAX_DELME); 11064 11065 return 0; 11066 }
static void peer_destructor | ( | void * | obj | ) | [static] |
Definition at line 10578 of file chan_iax2.c.
References ast_dnsmgr_release(), ast_event_unsubscribe(), ast_free_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_string_field_free_memory, iax2_peer::callno, iax2_peer::dnsmgr, iax2_peer::ha, iax2_destroy(), iax2_peer::mwi_event_sub, and register_peer_exten().
Referenced by build_peer().
10579 { 10580 struct iax2_peer *peer = obj; 10581 int callno = peer->callno; 10582 10583 ast_free_ha(peer->ha); 10584 10585 if (callno > 0) { 10586 ast_mutex_lock(&iaxsl[callno]); 10587 iax2_destroy(callno); 10588 ast_mutex_unlock(&iaxsl[callno]); 10589 } 10590 10591 register_peer_exten(peer, 0); 10592 10593 if (peer->dnsmgr) 10594 ast_dnsmgr_release(peer->dnsmgr); 10595 10596 if (peer->mwi_event_sub) 10597 ast_event_unsubscribe(peer->mwi_event_sub); 10598 10599 ast_string_field_free_memory(peer); 10600 }
static int peer_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1280 of file chan_iax2.c.
References ast_str_hash(), and iax2_peer::name.
Referenced by load_module().
01281 { 01282 const struct iax2_peer *peer = obj; 01283 01284 return ast_str_hash(peer->name); 01285 }
Definition at line 1337 of file chan_iax2.c.
References ao2_ref().
Referenced by __iax2_poke_noanswer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_unregister(), iax2_poke_peer(), reg_source_db(), socket_process(), and update_registry().
01338 { 01339 ao2_ref(peer, +1); 01340 return peer; 01341 }
static int peer_set_sock_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 12352 of file chan_iax2.c.
References iax2_peer::sockfd.
Referenced by load_module().
12353 { 12354 struct iax2_peer *peer = obj; 12355 12356 if (peer->sockfd < 0) 12357 peer->sockfd = defaultsockfd; 12358 12359 return 0; 12360 }
static int peer_set_srcaddr | ( | struct iax2_peer * | peer, | |
const char * | srcaddr | |||
) | [static] |
Parse the "sourceaddress" value, lookup in netsock list and set peer's sockfd. Defaults to defaultsockfd if not found.
Definition at line 10506 of file chan_iax2.c.
References ast_debug, ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, io, LOG_WARNING, iax2_peer::name, netsock, outsock, socket_read(), iax2_peer::sockfd, and strsep().
Referenced by build_peer().
10507 { 10508 struct sockaddr_in sin; 10509 int nonlocal = 1; 10510 int port = IAX_DEFAULT_PORTNO; 10511 int sockfd = defaultsockfd; 10512 char *tmp; 10513 char *addr; 10514 char *portstr; 10515 10516 if (!(tmp = ast_strdupa(srcaddr))) 10517 return -1; 10518 10519 addr = strsep(&tmp, ":"); 10520 portstr = tmp; 10521 10522 if (portstr) { 10523 port = atoi(portstr); 10524 if (port < 1) 10525 port = IAX_DEFAULT_PORTNO; 10526 } 10527 10528 if (!ast_get_ip(&sin, addr)) { 10529 struct ast_netsock *sock; 10530 int res; 10531 10532 sin.sin_port = 0; 10533 sin.sin_family = AF_INET; 10534 res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin)); 10535 if (res == 0) { 10536 /* ip address valid. */ 10537 sin.sin_port = htons(port); 10538 if (!(sock = ast_netsock_find(netsock, &sin))) 10539 sock = ast_netsock_find(outsock, &sin); 10540 if (sock) { 10541 sockfd = ast_netsock_sockfd(sock); 10542 nonlocal = 0; 10543 } else { 10544 unsigned int orig_saddr = sin.sin_addr.s_addr; 10545 /* INADDR_ANY matches anyway! */ 10546 sin.sin_addr.s_addr = INADDR_ANY; 10547 if (ast_netsock_find(netsock, &sin)) { 10548 sin.sin_addr.s_addr = orig_saddr; 10549 sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, cos, socket_read, NULL); 10550 if (sock) { 10551 sockfd = ast_netsock_sockfd(sock); 10552 ast_netsock_unref(sock); 10553 nonlocal = 0; 10554 } else { 10555 nonlocal = 2; 10556 } 10557 } 10558 } 10559 } 10560 } 10561 10562 peer->sockfd = sockfd; 10563 10564 if (nonlocal == 1) { 10565 ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", 10566 srcaddr, peer->name); 10567 return -1; 10568 } else if (nonlocal == 2) { 10569 ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n", 10570 srcaddr, peer->name); 10571 return -1; 10572 } else { 10573 ast_debug(1, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); 10574 return 0; 10575 } 10576 }
static int peer_status | ( | struct iax2_peer * | peer, | |
char * | status, | |||
int | statuslen | |||
) | [static] |
peer_status: Report Peer status in character string
Definition at line 2652 of file chan_iax2.c.
References ast_copy_string(), iax2_peer::lastms, and iax2_peer::maxms.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), function_iaxpeer(), function_sippeer(), handle_cli_iax2_show_peer(), and manager_iax2_show_peer_list().
02653 { 02654 int res = 0; 02655 if (peer->maxms) { 02656 if (peer->lastms < 0) { 02657 ast_copy_string(status, "UNREACHABLE", statuslen); 02658 } else if (peer->lastms > peer->maxms) { 02659 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 02660 res = 1; 02661 } else if (peer->lastms) { 02662 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 02663 res = 1; 02664 } else { 02665 ast_copy_string(status, "UNKNOWN", statuslen); 02666 } 02667 } else { 02668 ast_copy_string(status, "Unmonitored", statuslen); 02669 res = -1; 02670 } 02671 return res; 02672 }
Definition at line 1343 of file chan_iax2.c.
References ao2_ref().
Referenced by __expire_registry(), __iax2_poke_noanswer(), __iax2_poke_peer_s(), __iax2_show_peers(), authenticate_reply(), build_peer(), complete_iax2_show_peer(), complete_iax2_unregister(), create_addr(), function_iaxpeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), iax2_devicestate(), iax2_getpeername(), iax2_getpeertrunk(), iax2_poke_noanswer(), iax2_poke_peer(), manager_iax2_show_peer_list(), poke_all_peers(), prune_peers(), reg_source_db(), registry_authrequest(), set_config(), socket_process(), unlink_peer(), and update_registry().
01344 { 01345 ao2_ref(peer, -1); 01346 return NULL; 01347 }
static void poke_all_peers | ( | void | ) | [static] |
Definition at line 11556 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), iax2_poke_peer(), and peer_unref().
Referenced by reload_config().
11557 { 11558 struct ao2_iterator i; 11559 struct iax2_peer *peer; 11560 11561 i = ao2_iterator_init(peers, 0); 11562 while ((peer = ao2_iterator_next(&i))) { 11563 iax2_poke_peer(peer, 0); 11564 peer_unref(peer); 11565 } 11566 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 11119 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ast_test_flag, IAX_DELME, IAX_RTCACHEFRIENDS, peer_unref(), and unlink_peer().
11120 { 11121 struct iax2_peer *peer; 11122 struct ao2_iterator i; 11123 11124 i = ao2_iterator_init(peers, 0); 11125 while ((peer = ao2_iterator_next(&i))) { 11126 if (ast_test_flag(peer, IAX_DELME) || ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 11127 unlink_peer(peer); 11128 } 11129 peer_unref(peer); 11130 } 11131 }
static void prune_users | ( | void | ) | [static] |
Definition at line 11104 of file chan_iax2.c.
References ao2_iterator_init(), ao2_iterator_next(), ao2_unlink(), ast_test_flag, IAX_DELME, IAX_RTCACHEFRIENDS, user, and user_unref().
Referenced by handle_cli_iax2_prune_realtime(), and reload_config().
11105 { 11106 struct iax2_user *user; 11107 struct ao2_iterator i; 11108 11109 i = ao2_iterator_init(users, 0); 11110 while ((user = ao2_iterator_next(&i))) { 11111 if (ast_test_flag(user, IAX_DELME) || ast_test_flag(user, IAX_RTCACHEFRIENDS)) { 11112 ao2_unlink(users, user); 11113 } 11114 user_unref(user); 11115 } 11116 }
static int pvt_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 12369 of file chan_iax2.c.
References CMP_MATCH, chan_iax2_pvt::frames_received, and match().
12370 { 12371 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 12372 12373 /* The frames_received field is used to hold whether we're matching 12374 * against a full frame or not ... */ 12375 12376 return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt, 12377 pvt2->frames_received) ? CMP_MATCH : 0; 12378 }
static void pvt_destructor | ( | void * | obj | ) | [static] |
Definition at line 1445 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_set_flag, ast_string_field_free_memory, ast_variables_destroy(), iax2_registry::callno, chan_iax2_pvt::callno, iax_frame::callno, jb_frame::data, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, iax2_trunk_peer::list, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, and chan_iax2_pvt::vars.
01446 { 01447 struct chan_iax2_pvt *pvt = obj; 01448 struct iax_frame *cur = NULL; 01449 01450 iax2_destroy_helper(pvt); 01451 01452 /* Already gone */ 01453 ast_set_flag(pvt, IAX_ALREADYGONE); 01454 01455 AST_LIST_LOCK(&frame_queue); 01456 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 01457 /* Cancel any pending transmissions */ 01458 if (cur->callno == pvt->callno) { 01459 cur->retries = -1; 01460 } 01461 } 01462 AST_LIST_UNLOCK(&frame_queue); 01463 01464 if (pvt->reg) { 01465 pvt->reg->callno = 0; 01466 } 01467 01468 if (!pvt->owner) { 01469 jb_frame frame; 01470 if (pvt->vars) { 01471 ast_variables_destroy(pvt->vars); 01472 pvt->vars = NULL; 01473 } 01474 01475 while (jb_getall(pvt->jb, &frame) == JB_OK) { 01476 iax2_frame_free(frame.data); 01477 } 01478 01479 jb_destroy(pvt->jb); 01480 ast_string_field_free_memory(pvt); 01481 } 01482 }
static int pvt_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 12362 of file chan_iax2.c.
References chan_iax2_pvt::peercallno.
12363 { 12364 const struct chan_iax2_pvt *pvt = obj; 12365 12366 return pvt->peercallno; 12367 }
static int raw_hangup | ( | struct sockaddr_in * | sin, | |
unsigned short | src, | |||
unsigned short | dst, | |||
int | sockfd | |||
) | [static] |
Definition at line 6222 of file chan_iax2.c.
References ast_debug, AST_FRAME_IAX, ast_inet_ntoa(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_showframe(), ast_iax2_full_hdr::iseqno, option_debug, ast_iax2_full_hdr::oseqno, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.
Referenced by socket_process().
06223 { 06224 struct ast_iax2_full_hdr fh; 06225 fh.scallno = htons(src | IAX_FLAG_FULL); 06226 fh.dcallno = htons(dst); 06227 fh.ts = 0; 06228 fh.oseqno = 0; 06229 fh.iseqno = 0; 06230 fh.type = AST_FRAME_IAX; 06231 fh.csub = compress_subclass(IAX_COMMAND_INVAL); 06232 if (iaxdebug) 06233 iax_showframe(NULL, &fh, 0, sin, 0); 06234 #if 0 06235 if (option_debug) 06236 #endif 06237 ast_debug(1, "Raw Hangup %s:%d, src=%d, dst=%d\n", 06238 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst); 06239 return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin)); 06240 }
static struct iax2_peer * realtime_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 3216 of file chan_iax2.c.
References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.
03217 { 03218 struct ast_variable *var = NULL; 03219 struct ast_variable *tmp; 03220 struct iax2_peer *peer=NULL; 03221 time_t regseconds = 0, nowtime; 03222 int dynamic=0; 03223 03224 if (peername) { 03225 var = ast_load_realtime("iaxpeers", "name", peername, "host", "dynamic", NULL); 03226 if (!var && sin) 03227 var = ast_load_realtime("iaxpeers", "name", peername, "host", ast_inet_ntoa(sin->sin_addr), NULL); 03228 } else if (sin) { 03229 char porta[25]; 03230 sprintf(porta, "%d", ntohs(sin->sin_port)); 03231 var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 03232 if (var) { 03233 /* We'll need the peer name in order to build the structure! */ 03234 for (tmp = var; tmp; tmp = tmp->next) { 03235 if (!strcasecmp(tmp->name, "name")) 03236 peername = tmp->value; 03237 } 03238 } 03239 } 03240 if (!var && peername) { /* Last ditch effort */ 03241 var = ast_load_realtime("iaxpeers", "name", peername, NULL); 03242 /*!\note 03243 * If this one loaded something, then we need to ensure that the host 03244 * field matched. The only reason why we can't have this as a criteria 03245 * is because we only have the IP address and the host field might be 03246 * set as a name (and the reverse PTR might not match). 03247 */ 03248 if (var && sin) { 03249 for (tmp = var; tmp; tmp = tmp->next) { 03250 if (!strcasecmp(tmp->name, "host")) { 03251 struct ast_hostent ahp; 03252 struct hostent *hp; 03253 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 03254 /* No match */ 03255 ast_variables_destroy(var); 03256 var = NULL; 03257 } 03258 break; 03259 } 03260 } 03261 } 03262 } 03263 if (!var) 03264 return NULL; 03265 03266 peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); 03267 03268 if (!peer) { 03269 ast_variables_destroy(var); 03270 return NULL; 03271 } 03272 03273 for (tmp = var; tmp; tmp = tmp->next) { 03274 /* Make sure it's not a user only... */ 03275 if (!strcasecmp(tmp->name, "type")) { 03276 if (strcasecmp(tmp->value, "friend") && 03277 strcasecmp(tmp->value, "peer")) { 03278 /* Whoops, we weren't supposed to exist! */ 03279 peer = peer_unref(peer); 03280 break; 03281 } 03282 } else if (!strcasecmp(tmp->name, "regseconds")) { 03283 ast_get_time_t(tmp->value, ®seconds, 0, NULL); 03284 } else if (!strcasecmp(tmp->name, "ipaddr")) { 03285 inet_aton(tmp->value, &(peer->addr.sin_addr)); 03286 } else if (!strcasecmp(tmp->name, "port")) { 03287 peer->addr.sin_port = htons(atoi(tmp->value)); 03288 } else if (!strcasecmp(tmp->name, "host")) { 03289 if (!strcasecmp(tmp->value, "dynamic")) 03290 dynamic = 1; 03291 } 03292 } 03293 03294 ast_variables_destroy(var); 03295 03296 if (!peer) 03297 return NULL; 03298 03299 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 03300 ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS); 03301 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) { 03302 if (peer->expire > -1) { 03303 if (!ast_sched_del(sched, peer->expire)) { 03304 peer->expire = -1; 03305 peer_unref(peer); 03306 } 03307 } 03308 peer->expire = iax2_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer_ref(peer)); 03309 if (peer->expire == -1) 03310 peer_unref(peer); 03311 } 03312 ao2_link(peers, peer); 03313 if (ast_test_flag(peer, IAX_DYNAMIC)) 03314 reg_source_db(peer); 03315 } else { 03316 ast_set_flag(peer, IAX_TEMPONLY); 03317 } 03318 03319 if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) { 03320 time(&nowtime); 03321 if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) { 03322 memset(&peer->addr, 0, sizeof(peer->addr)); 03323 realtime_update_peer(peer->name, &peer->addr, 0); 03324 ast_debug(1, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n", 03325 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 03326 } 03327 else { 03328 ast_debug(1, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n", 03329 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 03330 } 03331 } 03332 03333 return peer; 03334 }
static void realtime_update_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin, | |||
time_t | regtime | |||
) | [static] |
Definition at line 3407 of file chan_iax2.c.
References ast_inet_ntoa(), and ast_update_realtime().
Referenced by __expire_registry(), update_peer(), and update_registry().
03408 { 03409 char port[10]; 03410 char regseconds[20]; 03411 03412 snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); 03413 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 03414 ast_update_realtime("iaxpeers", "name", peername, 03415 "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 03416 "regseconds", regseconds, NULL); 03417 }
static struct iax2_user* realtime_user | ( | const char * | username, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 3336 of file chan_iax2.c.
References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ast_variable::name, ast_variable::next, ast_variable::value, and var.
03337 { 03338 struct ast_variable *var; 03339 struct ast_variable *tmp; 03340 struct iax2_user *user=NULL; 03341 03342 var = ast_load_realtime("iaxusers", "name", username, "host", "dynamic", NULL); 03343 if (!var) 03344 var = ast_load_realtime("iaxusers", "name", username, "host", ast_inet_ntoa(sin->sin_addr), NULL); 03345 if (!var && sin) { 03346 char porta[6]; 03347 snprintf(porta, sizeof(porta), "%d", ntohs(sin->sin_port)); 03348 var = ast_load_realtime("iaxusers", "name", username, "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 03349 if (!var) 03350 var = ast_load_realtime("iaxusers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 03351 } 03352 if (!var) { /* Last ditch effort */ 03353 var = ast_load_realtime("iaxusers", "name", username, NULL); 03354 /*!\note 03355 * If this one loaded something, then we need to ensure that the host 03356 * field matched. The only reason why we can't have this as a criteria 03357 * is because we only have the IP address and the host field might be 03358 * set as a name (and the reverse PTR might not match). 03359 */ 03360 if (var) { 03361 for (tmp = var; tmp; tmp = tmp->next) { 03362 if (!strcasecmp(tmp->name, "host")) { 03363 struct ast_hostent ahp; 03364 struct hostent *hp; 03365 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 03366 /* No match */ 03367 ast_variables_destroy(var); 03368 var = NULL; 03369 } 03370 break; 03371 } 03372 } 03373 } 03374 } 03375 if (!var) 03376 return NULL; 03377 03378 tmp = var; 03379 while(tmp) { 03380 /* Make sure it's not a peer only... */ 03381 if (!strcasecmp(tmp->name, "type")) { 03382 if (strcasecmp(tmp->value, "friend") && 03383 strcasecmp(tmp->value, "user")) { 03384 return NULL; 03385 } 03386 } 03387 tmp = tmp->next; 03388 } 03389 03390 user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); 03391 03392 ast_variables_destroy(var); 03393 03394 if (!user) 03395 return NULL; 03396 03397 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 03398 ast_set_flag(user, IAX_RTCACHEFRIENDS); 03399 ao2_link(users, user); 03400 } else { 03401 ast_set_flag(user, IAX_TEMPONLY); 03402 } 03403 03404 return user; 03405 }
static void reg_source_db | ( | struct iax2_peer * | p | ) | [static] |
Definition at line 7073 of file chan_iax2.c.
References iax2_peer::addr, ast_db_get(), ast_device_state_changed(), ast_inet_ntoa(), ast_sched_del(), ast_test_flag, ast_verb, iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), IAX_TEMPONLY, inet_aton(), iax2_peer::name, peer_ref(), peer_unref(), register_peer_exten(), and sched.
Referenced by build_peer(), set_config(), and temp_peer().
07074 { 07075 char data[80]; 07076 struct in_addr in; 07077 char *c, *d; 07078 if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { 07079 c = strchr(data, ':'); 07080 if (c) { 07081 *c = '\0'; 07082 c++; 07083 if (inet_aton(data, &in)) { 07084 d = strchr(c, ':'); 07085 if (d) { 07086 *d = '\0'; 07087 d++; 07088 ast_verb(3, "Seeding '%s' at %s:%d for %d\n", p->name, 07089 ast_inet_ntoa(in), atoi(c), atoi(d)); 07090 iax2_poke_peer(p, 0); 07091 p->expiry = atoi(d); 07092 memset(&p->addr, 0, sizeof(p->addr)); 07093 p->addr.sin_family = AF_INET; 07094 p->addr.sin_addr = in; 07095 p->addr.sin_port = htons(atoi(c)); 07096 if (p->expire > -1) { 07097 if (!ast_sched_del(sched, p->expire)) { 07098 p->expire = -1; 07099 peer_unref(p); 07100 } 07101 } 07102 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 07103 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 07104 if (p->expire == -1) 07105 peer_unref(p); 07106 if (iax2_regfunk) 07107 iax2_regfunk(p->name, 1); 07108 register_peer_exten(p, 1); 07109 } 07110 07111 } 07112 } 07113 } 07114 }
static void register_peer_exten | ( | struct iax2_peer * | peer, | |
int | onoff | |||
) | [static] |
Definition at line 6994 of file chan_iax2.c.
References ast_add_extension(), ast_context_remove_extension(), ast_copy_string(), ast_exists_extension(), ast_free_ptr, ast_strdup, ast_strlen_zero(), ext, iax2_peer::name, iax2_peer::regexten, S_OR, and strsep().
Referenced by __expire_registry(), expire_register(), handle_response_peerpoke(), parse_register_contact(), peer_destructor(), reg_source_db(), sip_destroy_peer(), sip_poke_noanswer(), and update_registry().
06995 { 06996 char multi[256]; 06997 char *stringp, *ext; 06998 if (!ast_strlen_zero(regcontext)) { 06999 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 07000 stringp = multi; 07001 while((ext = strsep(&stringp, "&"))) { 07002 if (onoff) { 07003 if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL)) 07004 ast_add_extension(regcontext, 1, ext, 1, NULL, NULL, 07005 "Noop", ast_strdup(peer->name), ast_free_ptr, "IAX2"); 07006 } else 07007 ast_context_remove_extension(regcontext, ext, 1, NULL); 07008 } 07009 } 07010 }
static int register_verify | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Verify inbound registration.
Definition at line 6391 of file chan_iax2.c.
References ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_copy_string(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, ies, iax2_peer::inkeys, LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), iax2_peer::name, iax2_peer::secret, secret, and strsep().
Referenced by handle_request_register(), and socket_process().
06392 { 06393 char requeststr[256] = ""; 06394 char peer[256] = ""; 06395 char md5secret[256] = ""; 06396 char rsasecret[256] = ""; 06397 char secret[256] = ""; 06398 struct iax2_peer *p = NULL; 06399 struct ast_key *key; 06400 char *keyn; 06401 int x; 06402 int expire = 0; 06403 int res = -1; 06404 06405 ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06406 /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */ 06407 if (ies->username) 06408 ast_copy_string(peer, ies->username, sizeof(peer)); 06409 if (ies->password) 06410 ast_copy_string(secret, ies->password, sizeof(secret)); 06411 if (ies->md5_result) 06412 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 06413 if (ies->rsa_result) 06414 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 06415 if (ies->refresh) 06416 expire = ies->refresh; 06417 06418 if (ast_strlen_zero(peer)) { 06419 ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr)); 06420 return -1; 06421 } 06422 06423 /* SLD: first call to lookup peer during registration */ 06424 ast_mutex_unlock(&iaxsl[callno]); 06425 p = find_peer(peer, 1); 06426 ast_mutex_lock(&iaxsl[callno]); 06427 if (!p || !iaxs[callno]) { 06428 if (iaxs[callno]) { 06429 int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT)); 06430 /* Anything, as long as it's non-blank */ 06431 ast_string_field_set(iaxs[callno], secret, "badsecret"); 06432 /* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless 06433 * 1. A challenge already exists indicating a AUTHREQ was already sent out. 06434 * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it. 06435 * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened 06436 * to be plaintext, indicating it is an authmethod used by other peers on the system. 06437 * 06438 * If none of these cases exist, res will be returned as 0 without authentication indicating 06439 * an AUTHREQ needs to be sent out. */ 06440 06441 if (ast_strlen_zero(iaxs[callno]->challenge) && 06442 !(!ast_strlen_zero(secret) && plaintext)) { 06443 /* by setting res to 0, an REGAUTH will be sent */ 06444 res = 0; 06445 } 06446 } 06447 if (authdebug && !p) 06448 ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 06449 goto return_unref; 06450 } 06451 06452 if (!ast_test_flag(p, IAX_DYNAMIC)) { 06453 if (authdebug) 06454 ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 06455 goto return_unref; 06456 } 06457 06458 if (!ast_apply_ha(p->ha, sin)) { 06459 if (authdebug) 06460 ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 06461 goto return_unref; 06462 } 06463 ast_string_field_set(iaxs[callno], secret, p->secret); 06464 ast_string_field_set(iaxs[callno], inkeys, p->inkeys); 06465 /* Check secret against what we have on file */ 06466 if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) { 06467 if (!ast_strlen_zero(p->inkeys)) { 06468 char tmpkeys[256]; 06469 char *stringp=NULL; 06470 ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys)); 06471 stringp=tmpkeys; 06472 keyn = strsep(&stringp, ":"); 06473 while(keyn) { 06474 key = ast_key_get(keyn, AST_KEY_PUBLIC); 06475 if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) { 06476 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06477 break; 06478 } else if (!key) 06479 ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn); 06480 keyn = strsep(&stringp, ":"); 06481 } 06482 if (!keyn) { 06483 if (authdebug) 06484 ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys); 06485 goto return_unref; 06486 } 06487 } else { 06488 if (authdebug) 06489 ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer); 06490 goto return_unref; 06491 } 06492 } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { 06493 struct MD5Context md5; 06494 unsigned char digest[16]; 06495 char *tmppw, *stringp; 06496 06497 tmppw = ast_strdupa(p->secret); 06498 stringp = tmppw; 06499 while((tmppw = strsep(&stringp, ";"))) { 06500 MD5Init(&md5); 06501 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 06502 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 06503 MD5Final(digest, &md5); 06504 for (x=0;x<16;x++) 06505 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 06506 if (!strcasecmp(requeststr, md5secret)) 06507 break; 06508 } 06509 if (tmppw) { 06510 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06511 } else { 06512 if (authdebug) 06513 ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret); 06514 goto return_unref; 06515 } 06516 } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) { 06517 /* They've provided a plain text password and we support that */ 06518 if (strcmp(secret, p->secret)) { 06519 if (authdebug) 06520 ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 06521 goto return_unref; 06522 } else 06523 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 06524 } else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) { 06525 /* if challenge has been sent, but no challenge response if given, reject. */ 06526 goto return_unref; 06527 } 06528 ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ 06529 06530 /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */ 06531 res = 0; 06532 06533 return_unref: 06534 if (iaxs[callno]) { 06535 ast_string_field_set(iaxs[callno], peer, peer); 06536 06537 /* Choose lowest expiry number */ 06538 if (expire && (expire < iaxs[callno]->expiry)) { 06539 iaxs[callno]->expiry = expire; 06540 } 06541 } 06542 06543 if (p) { 06544 peer_unref(p); 06545 } 06546 return res; 06547 }
static int registry_authrequest | ( | int | callno | ) | [static] |
Definition at line 7270 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_strdupa, ast_string_field_set, iax2_peer::authmethods, find_peer(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_COMMAND_REGAUTH, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CHALLENGE, IAX_IE_USERNAME, peer_unref(), and send_command().
Referenced by socket_process().
07271 { 07272 struct iax_ie_data ied; 07273 struct iax2_peer *p; 07274 char challenge[10]; 07275 const char *peer_name; 07276 int sentauthmethod; 07277 07278 peer_name = ast_strdupa(iaxs[callno]->peer); 07279 07280 /* SLD: third call to find_peer in registration */ 07281 ast_mutex_unlock(&iaxsl[callno]); 07282 if ((p = find_peer(peer_name, 1))) { 07283 last_authmethod = p->authmethods; 07284 } 07285 07286 ast_mutex_lock(&iaxsl[callno]); 07287 if (!iaxs[callno]) 07288 goto return_unref; 07289 07290 memset(&ied, 0, sizeof(ied)); 07291 /* The selection of which delayed reject is sent may leak information, 07292 * if it sets a static response. For example, if a host is known to only 07293 * use MD5 authentication, then an RSA response would indicate that the 07294 * peer does not exist, and vice-versa. 07295 * Therefore, we use whatever the last peer used (which may vary over the 07296 * course of a server, which should leak minimal information). */ 07297 sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT); 07298 if (!p) { 07299 iaxs[callno]->authmethods = sentauthmethod; 07300 } 07301 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod); 07302 if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) { 07303 /* Build the challenge */ 07304 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 07305 ast_string_field_set(iaxs[callno], challenge, challenge); 07306 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge); 07307 } 07308 iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name); 07309 07310 return_unref: 07311 if (p) { 07312 peer_unref(p); 07313 } 07314 07315 return iaxs[callno] ? send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1) : -1; 07316 }
static int registry_rerequest | ( | struct iax_ies * | ies, | |
int | callno, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 7318 of file chan_iax2.c.
References iax2_registry::addr, ast_copy_string(), AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, ies, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax2_registry::refresh, REG_STATE_AUTHSENT, iax2_registry::regstate, iax2_registry::secret, send_command(), and iax2_registry::username.
Referenced by socket_process().
07319 { 07320 struct iax2_registry *reg; 07321 /* Start pessimistic */ 07322 struct iax_ie_data ied; 07323 char peer[256] = ""; 07324 char challenge[256] = ""; 07325 int res; 07326 int authmethods = 0; 07327 if (ies->authmethods) 07328 authmethods = ies->authmethods; 07329 if (ies->username) 07330 ast_copy_string(peer, ies->username, sizeof(peer)); 07331 if (ies->challenge) 07332 ast_copy_string(challenge, ies->challenge, sizeof(challenge)); 07333 memset(&ied, 0, sizeof(ied)); 07334 reg = iaxs[callno]->reg; 07335 if (reg) { 07336 if (inaddrcmp(®->addr, sin)) { 07337 ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 07338 return -1; 07339 } 07340 if (ast_strlen_zero(reg->secret)) { 07341 ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); 07342 reg->regstate = REG_STATE_NOAUTH; 07343 return -1; 07344 } 07345 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 07346 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 07347 if (reg->secret[0] == '[') { 07348 char tmpkey[256]; 07349 ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); 07350 tmpkey[strlen(tmpkey) - 1] = '\0'; 07351 res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL); 07352 } else 07353 res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL); 07354 if (!res) { 07355 reg->regstate = REG_STATE_AUTHSENT; 07356 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 07357 } else 07358 return -1; 07359 ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); 07360 } else 07361 ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); 07362 return -1; 07363 }
static char* regstate2str | ( | int | regstate | ) | [static] |
Definition at line 5516 of file chan_iax2.c.
References REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED.
Referenced by handle_cli_iax2_show_registry(), handle_response_register(), manager_show_registry(), sip_reg_timeout(), and sip_show_registry().
05517 { 05518 switch(regstate) { 05519 case REG_STATE_UNREGISTERED: 05520 return "Unregistered"; 05521 case REG_STATE_REGSENT: 05522 return "Request Sent"; 05523 case REG_STATE_AUTHSENT: 05524 return "Auth. Sent"; 05525 case REG_STATE_REGISTERED: 05526 return "Registered"; 05527 case REG_STATE_REJECTED: 05528 return "Rejected"; 05529 case REG_STATE_TIMEOUT: 05530 return "Timeout"; 05531 case REG_STATE_NOAUTH: 05532 return "No Authentication"; 05533 default: 05534 return "Unknown"; 05535 } 05536 }
static int reload | ( | void | ) | [static] |
Definition at line 11611 of file chan_iax2.c.
References reload_config().
11612 { 11613 return reload_config(); 11614 }
static int reload_config | ( | void | ) | [static] |
Definition at line 11567 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, iax2_registry::entry, iax2_do_register(), iax_provision_reload(), poke_all_peers(), prune_peers(), prune_users(), reload_firmware(), and set_config().
11568 { 11569 char *config = "iax.conf"; 11570 struct iax2_registry *reg; 11571 11572 if (set_config(config, 1) > 0) { 11573 prune_peers(); 11574 prune_users(); 11575 trunk_timed = trunk_untimed = 0; 11576 trunk_nmaxmtu = trunk_maxmtu = 0; 11577 11578 AST_LIST_LOCK(®istrations); 11579 AST_LIST_TRAVERSE(®istrations, reg, entry) 11580 iax2_do_register(reg); 11581 AST_LIST_UNLOCK(®istrations); 11582 11583 /* Qualify hosts, too */ 11584 poke_all_peers(); 11585 } 11586 11587 reload_firmware(0); 11588 iax_provision_reload(1); 11589 11590 return 0; 11591 }
static void reload_firmware | ( | int | unload | ) | [static] |
Definition at line 2162 of file chan_iax2.c.
References ast_config_AST_DATA_DIR, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verb, iax_firmware::dead, destroy_firmware(), dir, errno, iax2_trunk_peer::list, LOG_WARNING, and try_firmware().
Referenced by __unload_module(), load_module(), and reload_config().
02163 { 02164 struct iax_firmware *cur = NULL; 02165 DIR *fwd; 02166 struct dirent *de; 02167 char dir[256], fn[256]; 02168 02169 AST_LIST_LOCK(&firmwares); 02170 02171 /* Mark all as dead */ 02172 AST_LIST_TRAVERSE(&firmwares, cur, list) 02173 cur->dead = 1; 02174 02175 /* Now that we have marked them dead... load new ones */ 02176 if (!unload) { 02177 snprintf(dir, sizeof(dir), "%s/firmware/iax", ast_config_AST_DATA_DIR); 02178 fwd = opendir(dir); 02179 if (fwd) { 02180 while((de = readdir(fwd))) { 02181 if (de->d_name[0] != '.') { 02182 snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name); 02183 if (!try_firmware(fn)) { 02184 ast_verb(2, "Loaded firmware '%s'\n", de->d_name); 02185 } 02186 } 02187 } 02188 closedir(fwd); 02189 } else 02190 ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno)); 02191 } 02192 02193 /* Clean up leftovers */ 02194 AST_LIST_TRAVERSE_SAFE_BEGIN(&firmwares, cur, list) { 02195 if (!cur->dead) 02196 continue; 02197 AST_LIST_REMOVE_CURRENT(list); 02198 destroy_firmware(cur); 02199 } 02200 AST_LIST_TRAVERSE_SAFE_END; 02201 02202 AST_LIST_UNLOCK(&firmwares); 02203 }
static void remove_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1672 of file chan_iax2.c.
References ao2_unlink(), ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by complete_transfer(), iax2_destroy(), and socket_process().
01673 { 01674 if (!pvt->peercallno) { 01675 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01676 return; 01677 } 01678 01679 ao2_unlink(iax_peercallno_pvts, pvt); 01680 }
static void remove_by_transfercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1653 of file chan_iax2.c.
References ao2_unlink(), ast_log(), iax_transfercallno_pvts, LOG_ERROR, and chan_iax2_pvt::transfercallno.
Referenced by complete_transfer(), and iax2_destroy().
01654 { 01655 if (!pvt->transfercallno) { 01656 ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n"); 01657 return; 01658 } 01659 01660 ao2_unlink(iax_transfercallno_pvts, pvt); 01661 }
Definition at line 7813 of file chan_iax2.c.
References ast_string_field_set, iax_frame::callno, IAX_MAX_OSPBLOCK_NUM, IAX_MAX_OSPBLOCK_SIZE, IAX_MAX_OSPBUFF_SIZE, and ies.
Referenced by socket_process().
07814 { 07815 int i; 07816 unsigned int length, offset = 0; 07817 char full_osptoken[IAX_MAX_OSPBUFF_SIZE]; 07818 07819 for (i = 0; i < IAX_MAX_OSPBLOCK_NUM; i++) { 07820 length = ies->ospblocklength[i]; 07821 if (length != 0) { 07822 if (length > IAX_MAX_OSPBLOCK_SIZE) { 07823 /* OSP token block length wrong, clear buffer */ 07824 offset = 0; 07825 break; 07826 } else { 07827 memcpy(full_osptoken + offset, ies->osptokenblock[i], length); 07828 offset += length; 07829 } 07830 } else { 07831 break; 07832 } 07833 } 07834 *(full_osptoken + offset) = '\0'; 07835 if (strlen(full_osptoken) != offset) { 07836 /* OSP token length wrong, clear buffer */ 07837 *full_osptoken = '\0'; 07838 } 07839 07840 ast_string_field_set(iaxs[fr->callno], osptoken, full_osptoken); 07841 }
Definition at line 7802 of file chan_iax2.c.
References iax_frame::callno, and ies.
Referenced by socket_process().
07803 { 07804 iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter; 07805 iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24; 07806 iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff; 07807 iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts; 07808 iaxs[fr->callno]->remote_rr.delay = ies->rr_delay; 07809 iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped; 07810 iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; 07811 }
static void* sched_thread | ( | void * | ignore | ) | [static] |
Definition at line 10333 of file chan_iax2.c.
References ast_cond_timedwait(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), ast_tvnow(), sched, and sched_lock.
10334 { 10335 int count; 10336 int res; 10337 struct timeval tv; 10338 struct timespec ts; 10339 10340 for (;;) { 10341 res = ast_sched_wait(sched); 10342 if ((res > 1000) || (res < 0)) 10343 res = 1000; 10344 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); 10345 ts.tv_sec = tv.tv_sec; 10346 ts.tv_nsec = tv.tv_usec * 1000; 10347 10348 pthread_testcancel(); 10349 ast_mutex_lock(&sched_lock); 10350 ast_cond_timedwait(&sched_cond, &sched_lock, &ts); 10351 ast_mutex_unlock(&sched_lock); 10352 pthread_testcancel(); 10353 10354 count = ast_sched_runq(sched); 10355 if (count >= 20) 10356 ast_debug(1, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); 10357 } 10358 10359 return NULL; 10360 }
static int schedule_delivery | ( | struct iax_frame * | fr, | |
int | updatehistory, | |||
int | fromtrunk, | |||
unsigned int * | tsout | |||
) | [static] |
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it.
Definition at line 3071 of file chan_iax2.c.
References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), ast_debug, AST_FRAME_CNG, AST_FRAME_VOICE, ast_samp2tv(), AST_SCHED_DEL, ast_test_flag, ast_tv(), ast_tvadd(), ast_tvzero(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, ast_channel_tech::properties, sched, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().
Referenced by socket_process(), and socket_process_meta().
03072 { 03073 int type, len; 03074 int ret; 03075 int needfree = 0; 03076 struct ast_channel *owner = NULL; 03077 struct ast_channel *bridge = NULL; 03078 03079 /* Attempt to recover wrapped timestamps */ 03080 unwrap_timestamp(fr); 03081 03082 /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */ 03083 if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) 03084 fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000)); 03085 else { 03086 #if 0 03087 ast_debug(1, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n"); 03088 #endif 03089 fr->af.delivery = ast_tv(0,0); 03090 } 03091 03092 type = JB_TYPE_CONTROL; 03093 len = 0; 03094 03095 if(fr->af.frametype == AST_FRAME_VOICE) { 03096 type = JB_TYPE_VOICE; 03097 len = ast_codec_get_samples(&fr->af) / 8; 03098 } else if(fr->af.frametype == AST_FRAME_CNG) { 03099 type = JB_TYPE_SILENCE; 03100 } 03101 03102 if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) { 03103 if (tsout) 03104 *tsout = fr->ts; 03105 __do_deliver(fr); 03106 return -1; 03107 } 03108 03109 if ((owner = iaxs[fr->callno]->owner)) 03110 bridge = ast_bridged_channel(owner); 03111 03112 /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to 03113 * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */ 03114 if ( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (bridge->tech->properties & AST_CHAN_TP_WANTSJITTER) ) { 03115 jb_frame frame; 03116 03117 /* deliver any frames in the jb */ 03118 while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { 03119 __do_deliver(frame.data); 03120 /* __do_deliver() can make the call disappear */ 03121 if (!iaxs[fr->callno]) 03122 return -1; 03123 } 03124 03125 jb_reset(iaxs[fr->callno]->jb); 03126 03127 AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid); 03128 03129 /* deliver this frame now */ 03130 if (tsout) 03131 *tsout = fr->ts; 03132 __do_deliver(fr); 03133 return -1; 03134 } 03135 03136 /* insert into jitterbuffer */ 03137 /* TODO: Perhaps we could act immediately if it's not droppable and late */ 03138 ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts, 03139 calc_rxstamp(iaxs[fr->callno],fr->ts)); 03140 if (ret == JB_DROP) { 03141 needfree++; 03142 } else if (ret == JB_SCHED) { 03143 update_jbsched(iaxs[fr->callno]); 03144 } 03145 if (tsout) 03146 *tsout = fr->ts; 03147 if (needfree) { 03148 /* Free our iax frame */ 03149 iax2_frame_free(fr); 03150 return -1; 03151 } 03152 return 0; 03153 }
static int scheduled_destroy | ( | const void * | vid | ) | [static] |
Definition at line 1431 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_destroy(), LOG_DEBUG, option_debug, and PTR_TO_CALLNO.
Referenced by iax2_hangup().
01432 { 01433 short callno = PTR_TO_CALLNO(vid); 01434 ast_mutex_lock(&iaxsl[callno]); 01435 if (iaxs[callno]) { 01436 if (option_debug) { 01437 ast_log(LOG_DEBUG, "Really destroying %d now...\n", callno); 01438 } 01439 iax2_destroy(callno); 01440 } 01441 ast_mutex_unlock(&iaxsl[callno]); 01442 return 0; 01443 }
static int send_apathetic_reply | ( | unsigned short | callno, | |
unsigned short | dcallno, | |||
struct sockaddr_in * | sin, | |||
int | command, | |||
int | ts, | |||
unsigned char | seqno | |||
) | [static] |
Definition at line 3575 of file chan_iax2.c.
References AST_FRAME_IAX, compress_subclass(), and f.
Referenced by socket_process().
03576 { 03577 struct ast_iax2_full_hdr f = { .scallno = htons(0x8000 | callno), .dcallno = htons(dcallno), 03578 .ts = htonl(ts), .iseqno = seqno, .oseqno = 0, .type = AST_FRAME_IAX, 03579 .csub = compress_subclass(command) }; 03580 03581 return sendto(defaultsockfd, &f, sizeof(f), 0, (struct sockaddr *)sin, sizeof(*sin)); 03582 }
static int send_command | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5950 of file chan_iax2.c.
References __send_command().
Referenced by __attempt_transmit(), __send_lagrq(), __send_ping(), authenticate_reply(), authenticate_request(), cache_get_callno_locked(), dp_lookup(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_indicate(), iax2_poke_peer(), iax2_provision(), iax2_start_transfer(), registry_authrequest(), registry_rerequest(), send_command_locked(), and socket_process().
05951 { 05952 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); 05953 }
static int send_command_final | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno | |||
) | [static] |
Definition at line 5969 of file chan_iax2.c.
References __send_command(), chan_iax2_pvt::callno, and iax2_predestroy().
Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_hangup(), socket_process(), and update_registry().
05970 { 05971 int call_num = i->callno; 05972 /* It is assumed that the callno has already been locked */ 05973 iax2_predestroy(i->callno); 05974 if (!iaxs[call_num]) 05975 return -1; 05976 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1); 05977 }
static int send_command_immediate | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5979 of file chan_iax2.c.
References __send_command().
Referenced by iax2_vnak(), and socket_process().
05980 { 05981 return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0); 05982 }
static int send_command_locked | ( | unsigned short | callno, | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5955 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), and send_command().
Referenced by iax2_answer(), iax2_digit_begin(), iax2_digit_end(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), and iax2_transfer().
05956 { 05957 int res; 05958 ast_mutex_lock(&iaxsl[callno]); 05959 res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno); 05960 ast_mutex_unlock(&iaxsl[callno]); 05961 return res; 05962 }
static int send_command_transfer | ( | struct chan_iax2_pvt * | , | |
char | , | |||
int | , | |||
unsigned | int, | |||
const unsigned char * | , | |||
int | ||||
) | [static] |
Definition at line 5984 of file chan_iax2.c.
References __send_command().
Referenced by socket_process(), and try_transfer().
05985 { 05986 return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0); 05987 }
static int send_lagrq | ( | const void * | data | ) | [static] |
Definition at line 1233 of file chan_iax2.c.
References __send_lagrq(), and schedule_action.
Referenced by __find_callno(), __send_lagrq(), and make_trunk().
01234 { 01235 #ifdef SCHED_MULTITHREADED 01236 if (schedule_action(__send_lagrq, data)) 01237 #endif 01238 __send_lagrq(data); 01239 01240 return 0; 01241 }
static int send_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2275 of file chan_iax2.c.
References ast_debug, ast_inet_ntoa(), errno, f, handle_error(), iax_showframe(), and iax2_trunk_peer::sockfd.
Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().
02276 { 02277 int res; 02278 int callno = f->callno; 02279 02280 /* Don't send if there was an error, but return error instead */ 02281 if (!callno || !iaxs[callno] || iaxs[callno]->error) 02282 return -1; 02283 02284 /* Called with iaxsl held */ 02285 if (iaxdebug) 02286 ast_debug(3, "Sending %d on %d/%d to %s:%d\n", f->ts, callno, iaxs[callno]->peercallno, ast_inet_ntoa(iaxs[callno]->addr.sin_addr), ntohs(iaxs[callno]->addr.sin_port)); 02287 if (f->transfer) { 02288 if (iaxdebug) 02289 iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02290 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, 02291 sizeof(iaxs[callno]->transfer)); 02292 } else { 02293 if (iaxdebug) 02294 iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr)); 02295 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, 02296 sizeof(iaxs[callno]->addr)); 02297 } 02298 if (res < 0) { 02299 if (iaxdebug) 02300 ast_debug(1, "Received error: %s\n", strerror(errno)); 02301 handle_error(); 02302 } else 02303 res = 0; 02304 return res; 02305 }
static int send_ping | ( | const void * | data | ) | [static] |
Definition at line 1188 of file chan_iax2.c.
References __send_ping(), and schedule_action.
Referenced by __find_callno(), __send_ping(), do_monitor(), init_phone_step2(), and make_trunk().
01189 { 01190 #ifdef SCHED_MULTITHREADED 01191 if (schedule_action(__send_ping, data)) 01192 #endif 01193 __send_ping(data); 01194 01195 return 0; 01196 }
static int send_trunk | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [static] |
Definition at line 7500 of file chan_iax2.c.
References iax2_trunk_peer::addr, iax_frame::afdata, ast_debug, ast_inet_ntoa(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, globalflags, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_hdr::metacmd, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.
Referenced by iax2_trunk_queue(), and timing_read().
07501 { 07502 int res = 0; 07503 struct iax_frame *fr; 07504 struct ast_iax2_meta_hdr *meta; 07505 struct ast_iax2_meta_trunk_hdr *mth; 07506 int calls = 0; 07507 07508 /* Point to frame */ 07509 fr = (struct iax_frame *)tpeer->trunkdata; 07510 /* Point to meta data */ 07511 meta = (struct ast_iax2_meta_hdr *)fr->afdata; 07512 mth = (struct ast_iax2_meta_trunk_hdr *)meta->data; 07513 if (tpeer->trunkdatalen) { 07514 /* We're actually sending a frame, so fill the meta trunk header and meta header */ 07515 meta->zeros = 0; 07516 meta->metacmd = IAX_META_TRUNK; 07517 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) 07518 meta->cmddata = IAX_META_TRUNK_MINI; 07519 else 07520 meta->cmddata = IAX_META_TRUNK_SUPERMINI; 07521 mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now)); 07522 /* And the rest of the ast_iax2 header */ 07523 fr->direction = DIRECTION_OUTGRESS; 07524 fr->retrans = -1; 07525 fr->transfer = 0; 07526 /* Any appropriate call will do */ 07527 fr->data = fr->afdata; 07528 fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr); 07529 res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd); 07530 calls = tpeer->calls; 07531 #if 0 07532 ast_debug(1, "Trunking %d call chunks in %d bytes to %s:%d, ts=%d\n", calls, fr->datalen, ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), ntohl(mth->ts)); 07533 #endif 07534 /* Reset transmit trunk side data */ 07535 tpeer->trunkdatalen = 0; 07536 tpeer->calls = 0; 07537 } 07538 if (res < 0) 07539 return res; 07540 return calls; 07541 }
static int set_config | ( | char * | config_file, | |
int | reload | |||
) | [static] |
Load configuration.
Definition at line 11165 of file chan_iax2.c.
References ao2_link(), ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_context_find_or_create(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_netsock_bind(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_netsock_sockfd(), ast_netsock_unref(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_str2cos(), ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, build_peer(), build_user(), capability, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MAXMS, errno, format, gen, get_encrypt_methods(), globalflags, iax2_register(), IAX_ALLOWFWDOWNLOAD, IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_RTUPDATE, IAX_TRANSFERMEDIA, IAX_TRUNKTIMESTAMPS, IAX_USEJITTERBUF, iaxmaxthreadcount, iaxthreadcount, io, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, MAX_TRUNK_MTU, MAX_TRUNKDATA, ast_variable::name, netsock, ast_variable::next, outsock, peer_unref(), prefs, reg_source_db(), secret, set_config_destroy(), set_timing(), socket_read(), user, user_unref(), and ast_variable::value.
Referenced by load_module(), reload(), and reload_config().
11166 { 11167 struct ast_config *cfg, *ucfg; 11168 int capability=iax2_capability; 11169 struct ast_variable *v; 11170 char *cat; 11171 const char *utype; 11172 const char *tosval; 11173 int format; 11174 int portno = IAX_DEFAULT_PORTNO; 11175 int x; 11176 int mtuv; 11177 struct iax2_user *user; 11178 struct iax2_peer *peer; 11179 struct ast_netsock *ns; 11180 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 11181 #if 0 11182 static unsigned short int last_port=0; 11183 #endif 11184 11185 cfg = ast_config_load(config_file, config_flags); 11186 11187 if (!cfg) { 11188 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 11189 return -1; 11190 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 11191 ucfg = ast_config_load("users.conf", config_flags); 11192 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 11193 return 0; 11194 /* Otherwise we need to reread both files */ 11195 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 11196 cfg = ast_config_load(config_file, config_flags); 11197 } else { /* iax.conf changed, gotta reread users.conf, too */ 11198 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 11199 ucfg = ast_config_load("users.conf", config_flags); 11200 } 11201 11202 if (reload) { 11203 set_config_destroy(); 11204 } 11205 11206 /* Reset global codec prefs */ 11207 memset(&prefs, 0 , sizeof(struct ast_codec_pref)); 11208 11209 /* Reset Global Flags */ 11210 memset(&globalflags, 0, sizeof(globalflags)); 11211 ast_set_flag(&globalflags, IAX_RTUPDATE); 11212 11213 #ifdef SO_NO_CHECK 11214 nochecksums = 0; 11215 #endif 11216 11217 min_reg_expire = IAX_DEFAULT_REG_EXPIRE; 11218 max_reg_expire = IAX_DEFAULT_REG_EXPIRE; 11219 global_max_trunk_mtu = MAX_TRUNK_MTU; 11220 11221 maxauthreq = 3; 11222 11223 srvlookup = 0; 11224 11225 v = ast_variable_browse(cfg, "general"); 11226 11227 /* Seed initial tos value */ 11228 tosval = ast_variable_retrieve(cfg, "general", "tos"); 11229 if (tosval) { 11230 if (ast_str2tos(tosval, &tos)) 11231 ast_log(LOG_WARNING, "Invalid tos value, refer to QoS documentation\n"); 11232 } 11233 /* Seed initial cos value */ 11234 tosval = ast_variable_retrieve(cfg, "general", "cos"); 11235 if (tosval) { 11236 if (ast_str2cos(tosval, &cos)) 11237 ast_log(LOG_WARNING, "Invalid cos value, refer to QoS documentation\n"); 11238 } 11239 while(v) { 11240 if (!strcasecmp(v->name, "bindport")){ 11241 if (reload) 11242 ast_log(LOG_NOTICE, "Ignoring bindport on reload\n"); 11243 else 11244 portno = atoi(v->value); 11245 } else if (!strcasecmp(v->name, "pingtime")) 11246 ping_time = atoi(v->value); 11247 else if (!strcasecmp(v->name, "iaxthreadcount")) { 11248 if (reload) { 11249 if (atoi(v->value) != iaxthreadcount) 11250 ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n"); 11251 } else { 11252 iaxthreadcount = atoi(v->value); 11253 if (iaxthreadcount < 1) { 11254 ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n"); 11255 iaxthreadcount = 1; 11256 } else if (iaxthreadcount > 256) { 11257 ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n"); 11258 iaxthreadcount = 256; 11259 } 11260 } 11261 } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) { 11262 if (reload) { 11263 AST_LIST_LOCK(&dynamic_list); 11264 iaxmaxthreadcount = atoi(v->value); 11265 AST_LIST_UNLOCK(&dynamic_list); 11266 } else { 11267 iaxmaxthreadcount = atoi(v->value); 11268 if (iaxmaxthreadcount < 0) { 11269 ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n"); 11270 iaxmaxthreadcount = 0; 11271 } else if (iaxmaxthreadcount > 256) { 11272 ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n"); 11273 iaxmaxthreadcount = 256; 11274 } 11275 } 11276 } else if (!strcasecmp(v->name, "nochecksums")) { 11277 #ifdef SO_NO_CHECK 11278 if (ast_true(v->value)) 11279 nochecksums = 1; 11280 else 11281 nochecksums = 0; 11282 #else 11283 if (ast_true(v->value)) 11284 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 11285 #endif 11286 } 11287 else if (!strcasecmp(v->name, "maxjitterbuffer")) 11288 maxjitterbuffer = atoi(v->value); 11289 else if (!strcasecmp(v->name, "resyncthreshold")) 11290 resyncthreshold = atoi(v->value); 11291 else if (!strcasecmp(v->name, "maxjitterinterps")) 11292 maxjitterinterps = atoi(v->value); 11293 else if (!strcasecmp(v->name, "jittertargetextra")) 11294 jittertargetextra = atoi(v->value); 11295 else if (!strcasecmp(v->name, "lagrqtime")) 11296 lagrq_time = atoi(v->value); 11297 else if (!strcasecmp(v->name, "maxregexpire")) 11298 max_reg_expire = atoi(v->value); 11299 else if (!strcasecmp(v->name, "minregexpire")) 11300 min_reg_expire = atoi(v->value); 11301 else if (!strcasecmp(v->name, "bindaddr")) { 11302 if (reload) { 11303 ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n"); 11304 } else { 11305 if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, cos, socket_read, NULL))) { 11306 ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno); 11307 } else { 11308 if (strchr(v->value, ':')) 11309 ast_verb(2, "Binding IAX2 to '%s'\n", v->value); 11310 else 11311 ast_verb(2, "Binding IAX2 to '%s:%d'\n", v->value, portno); 11312 if (defaultsockfd < 0) 11313 defaultsockfd = ast_netsock_sockfd(ns); 11314 ast_netsock_unref(ns); 11315 } 11316 } 11317 } else if (!strcasecmp(v->name, "authdebug")) 11318 authdebug = ast_true(v->value); 11319 else if (!strcasecmp(v->name, "encryption")) 11320 iax2_encryption = get_encrypt_methods(v->value); 11321 else if (!strcasecmp(v->name, "transfer")) { 11322 if (!strcasecmp(v->value, "mediaonly")) { 11323 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 11324 } else if (ast_true(v->value)) { 11325 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 11326 } else 11327 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 11328 } else if (!strcasecmp(v->name, "codecpriority")) { 11329 if(!strcasecmp(v->value, "caller")) 11330 ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST); 11331 else if(!strcasecmp(v->value, "disabled")) 11332 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 11333 else if(!strcasecmp(v->value, "reqonly")) { 11334 ast_set_flag((&globalflags), IAX_CODEC_NOCAP); 11335 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 11336 } 11337 } else if (!strcasecmp(v->name, "jitterbuffer")) 11338 ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 11339 else if (!strcasecmp(v->name, "forcejitterbuffer")) 11340 ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF); 11341 else if (!strcasecmp(v->name, "delayreject")) 11342 delayreject = ast_true(v->value); 11343 else if (!strcasecmp(v->name, "allowfwdownload")) 11344 ast_set2_flag((&globalflags), ast_true(v->value), IAX_ALLOWFWDOWNLOAD); 11345 else if (!strcasecmp(v->name, "rtcachefriends")) 11346 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS); 11347 else if (!strcasecmp(v->name, "rtignoreregexpire")) 11348 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE); 11349 else if (!strcasecmp(v->name, "rtupdate")) 11350 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE); 11351 else if (!strcasecmp(v->name, "trunktimestamps")) 11352 ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS); 11353 else if (!strcasecmp(v->name, "rtautoclear")) { 11354 int i = atoi(v->value); 11355 if(i > 0) 11356 global_rtautoclear = i; 11357 else 11358 i = 0; 11359 ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR); 11360 } else if (!strcasecmp(v->name, "trunkfreq")) { 11361 trunkfreq = atoi(v->value); 11362 if (trunkfreq < 10) 11363 trunkfreq = 10; 11364 } else if (!strcasecmp(v->name, "trunkmtu")) { 11365 mtuv = atoi(v->value); 11366 if (mtuv == 0 ) 11367 global_max_trunk_mtu = 0; 11368 else if (mtuv >= 172 && mtuv < 4000) 11369 global_max_trunk_mtu = mtuv; 11370 else 11371 ast_log(LOG_NOTICE, "trunkmtu value out of bounds (%d) at line %d\n", 11372 mtuv, v->lineno); 11373 } else if (!strcasecmp(v->name, "trunkmaxsize")) { 11374 trunkmaxsize = atoi(v->value); 11375 if (trunkmaxsize == 0) 11376 trunkmaxsize = MAX_TRUNKDATA; 11377 } else if (!strcasecmp(v->name, "autokill")) { 11378 if (sscanf(v->value, "%d", &x) == 1) { 11379 if (x >= 0) 11380 autokill = x; 11381 else 11382 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 11383 } else if (ast_true(v->value)) { 11384 autokill = DEFAULT_MAXMS; 11385 } else { 11386 autokill = 0; 11387 } 11388 } else if (!strcasecmp(v->name, "bandwidth")) { 11389 if (!strcasecmp(v->value, "low")) { 11390 capability = IAX_CAPABILITY_LOWBANDWIDTH; 11391 } else if (!strcasecmp(v->value, "medium")) { 11392 capability = IAX_CAPABILITY_MEDBANDWIDTH; 11393 } else if (!strcasecmp(v->value, "high")) { 11394 capability = IAX_CAPABILITY_FULLBANDWIDTH; 11395 } else 11396 ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); 11397 } else if (!strcasecmp(v->name, "allow")) { 11398 ast_parse_allow_disallow(&prefs, &capability, v->value, 1); 11399 } else if (!strcasecmp(v->name, "disallow")) { 11400 ast_parse_allow_disallow(&prefs, &capability, v->value, 0); 11401 } else if (!strcasecmp(v->name, "register")) { 11402 iax2_register(v->value, v->lineno); 11403 } else if (!strcasecmp(v->name, "iaxcompat")) { 11404 iaxcompat = ast_true(v->value); 11405 } else if (!strcasecmp(v->name, "regcontext")) { 11406 ast_copy_string(regcontext, v->value, sizeof(regcontext)); 11407 /* Create context if it doesn't exist already */ 11408 ast_context_find_or_create(NULL, NULL, regcontext, "IAX2"); 11409 } else if (!strcasecmp(v->name, "tos")) { 11410 if (ast_str2tos(v->value, &tos)) 11411 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 11412 } else if (!strcasecmp(v->name, "cos")) { 11413 if (ast_str2cos(v->value, &cos)) 11414 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 11415 } else if (!strcasecmp(v->name, "accountcode")) { 11416 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 11417 } else if (!strcasecmp(v->name, "mohinterpret")) { 11418 ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); 11419 } else if (!strcasecmp(v->name, "mohsuggest")) { 11420 ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest)); 11421 } else if (!strcasecmp(v->name, "amaflags")) { 11422 format = ast_cdr_amaflags2int(v->value); 11423 if (format < 0) { 11424 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 11425 } else { 11426 amaflags = format; 11427 } 11428 } else if (!strcasecmp(v->name, "language")) { 11429 ast_copy_string(language, v->value, sizeof(language)); 11430 } else if (!strcasecmp(v->name, "maxauthreq")) { 11431 maxauthreq = atoi(v->value); 11432 if (maxauthreq < 0) 11433 maxauthreq = 0; 11434 } else if (!strcasecmp(v->name, "adsi")) { 11435 adsi = ast_true(v->value); 11436 } else if (!strcasecmp(v->name, "srvlookup")) { 11437 srvlookup = ast_true(v->value); 11438 } /*else if (strcasecmp(v->name,"type")) */ 11439 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 11440 v = v->next; 11441 } 11442 11443 if (defaultsockfd < 0) { 11444 if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, cos, socket_read, NULL))) { 11445 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 11446 } else { 11447 ast_verb(2, "Binding IAX2 to default address 0.0.0.0:%d\n", portno); 11448 defaultsockfd = ast_netsock_sockfd(ns); 11449 ast_netsock_unref(ns); 11450 } 11451 } 11452 if (reload) { 11453 ast_netsock_release(outsock); 11454 outsock = ast_netsock_list_alloc(); 11455 if (!outsock) { 11456 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 11457 return -1; 11458 } 11459 ast_netsock_init(outsock); 11460 } 11461 11462 if (min_reg_expire > max_reg_expire) { 11463 ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n", 11464 min_reg_expire, max_reg_expire, max_reg_expire); 11465 min_reg_expire = max_reg_expire; 11466 } 11467 iax2_capability = capability; 11468 11469 if (ucfg) { 11470 struct ast_variable *gen; 11471 int genhasiax; 11472 int genregisteriax; 11473 const char *hasiax, *registeriax; 11474 11475 genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); 11476 genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); 11477 gen = ast_variable_browse(ucfg, "general"); 11478 cat = ast_category_browse(ucfg, NULL); 11479 while (cat) { 11480 if (strcasecmp(cat, "general")) { 11481 hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); 11482 registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); 11483 if (ast_true(hasiax) || (!hasiax && genhasiax)) { 11484 /* Start with general parameters, then specific parameters, user and peer */ 11485 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 11486 if (user) { 11487 ao2_link(users, user); 11488 user = user_unref(user); 11489 } 11490 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 11491 if (peer) { 11492 if (ast_test_flag(peer, IAX_DYNAMIC)) 11493 reg_source_db(peer); 11494 ao2_link(peers, peer); 11495 peer = peer_unref(peer); 11496 } 11497 } 11498 if (ast_true(registeriax) || (!registeriax && genregisteriax)) { 11499 char tmp[256]; 11500 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 11501 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 11502 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 11503 if (!host) 11504 host = ast_variable_retrieve(ucfg, "general", "host"); 11505 if (!username) 11506 username = ast_variable_retrieve(ucfg, "general", "username"); 11507 if (!secret) 11508 secret = ast_variable_retrieve(ucfg, "general", "secret"); 11509 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 11510 if (!ast_strlen_zero(secret)) 11511 snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); 11512 else 11513 snprintf(tmp, sizeof(tmp), "%s@%s", username, host); 11514 iax2_register(tmp, 0); 11515 } 11516 } 11517 } 11518 cat = ast_category_browse(ucfg, cat); 11519 } 11520 ast_config_destroy(ucfg); 11521 } 11522 11523 cat = ast_category_browse(cfg, NULL); 11524 while(cat) { 11525 if (strcasecmp(cat, "general")) { 11526 utype = ast_variable_retrieve(cfg, cat, "type"); 11527 if (utype) { 11528 if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { 11529 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 11530 if (user) { 11531 ao2_link(users, user); 11532 user = user_unref(user); 11533 } 11534 } 11535 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { 11536 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 11537 if (peer) { 11538 if (ast_test_flag(peer, IAX_DYNAMIC)) 11539 reg_source_db(peer); 11540 ao2_link(peers, peer); 11541 peer = peer_unref(peer); 11542 } 11543 } else if (strcasecmp(utype, "user")) { 11544 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file); 11545 } 11546 } else 11547 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 11548 } 11549 cat = ast_category_browse(cfg, cat); 11550 } 11551 ast_config_destroy(cfg); 11552 set_timing(); 11553 return 1; 11554 }
static void set_config_destroy | ( | void | ) | [static] |
Definition at line 11148 of file chan_iax2.c.
References ast_clear_flag, delete_users(), globalflags, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, and MAX_TRUNKDATA.
Referenced by set_config().
11149 { 11150 strcpy(accountcode, ""); 11151 strcpy(language, ""); 11152 strcpy(mohinterpret, "default"); 11153 strcpy(mohsuggest, ""); 11154 trunkmaxsize = MAX_TRUNKDATA; 11155 amaflags = 0; 11156 delayreject = 0; 11157 ast_clear_flag((&globalflags), IAX_NOTRANSFER); 11158 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 11159 ast_clear_flag((&globalflags), IAX_USEJITTERBUF); 11160 ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF); 11161 delete_users(); 11162 }
static void set_timing | ( | void | ) | [static] |
Definition at line 11133 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by set_config().
11134 { 11135 #ifdef HAVE_DAHDI 11136 int bs = trunkfreq * 8; 11137 if (timingfd > -1) { 11138 if ( 11139 #ifdef DAHDI_TIMERACK 11140 ioctl(timingfd, DAHDI_TIMERCONFIG, &bs) && 11141 #endif 11142 ioctl(timingfd, DAHDI_SET_BLOCKSIZE, &bs)) 11143 ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n"); 11144 } 11145 #endif 11146 }
static void signal_condition | ( | ast_mutex_t * | lock, | |
ast_cond_t * | cond | |||
) | [static] |
Definition at line 790 of file chan_iax2.c.
References ast_cond_signal(), ast_mutex_lock(), and ast_mutex_unlock().
Referenced by __schedule_action(), iax2_sched_add(), iax2_sched_replace(), iax2_transmit(), and socket_read().
00791 { 00792 ast_mutex_lock(lock); 00793 ast_cond_signal(cond); 00794 ast_mutex_unlock(lock); 00795 }
static int socket_process | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 8239 of file chan_iax2.c.
References ast_async_goto(), ast_best_codec(), ast_bridged_channel(), ast_calloc, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_free(), ast_channel_trylock, ast_channel_unlock, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_debug, ast_device_state_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_free, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_sched_del(), AST_SCHED_DEL, ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_var_assign(), ast_variables_destroy(), ast_verb, auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax2_peer::callno, iax2_dpcache::callno, iax_frame::callno, check_access(), check_provisioning(), cid_num, complete_dpreply(), complete_transfer(), construct_rr(), ast_channel::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, DEADLOCK_AVOIDANCE, decrypt_frame(), dp_lookup(), ast_var_t::entries, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, f, iax_frame::final, find_callno(), iax2_dpcache::flags, format, ast_frame::frametype, globalflags, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_queue_control_data(), iax2_queue_frame(), iax2_sched_add(), iax2_send(), iax2_variable_datastore_info, iax2_vnak(), IAX_ALLOWFWDOWNLOAD, IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_TRUNK, iaxfrdup2(), ies, inaddrcmp(), ast_datastore::inheritance, iax2_peer::lastms, LOG_ERROR, log_jitterstats(), LOG_NOTICE, LOG_WARNING, make_trunk(), manager_event, iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, iax2_peer::name, ast_channel::name, NEW_ALLOW, NEW_PREVENT, iax_frame::oseqno, pbx_builtin_setvar_helper(), peer_ref(), peer_unref(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, raw_hangup(), REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), remove_by_peercallno(), iax_frame::retries, S_OR, save_osptoken(), save_rr(), sched, schedule_delivery(), send_apathetic_reply(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax2_peer::smoothing, socket_process_meta(), spawn_dp_lookup(), stop_stuff(), store_by_peercallno(), thread, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, try_transfer(), iax_frame::ts, uncompress_subclass(), update_registry(), var, VERBOSE_PREFIX_4, vnak_retransmit(), and ast_iax2_meta_hdr::zeros.
Referenced by handle_deferred_full_frames().
08240 { 08241 struct sockaddr_in sin; 08242 int res; 08243 int updatehistory=1; 08244 int new = NEW_PREVENT; 08245 int dcallno = 0; 08246 struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf; 08247 struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf; 08248 struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf; 08249 struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf; 08250 struct iax_frame *fr; 08251 struct iax_frame *cur; 08252 struct ast_frame f = { 0, }; 08253 struct ast_channel *c = NULL; 08254 struct iax2_dpcache *dp; 08255 struct iax2_peer *peer; 08256 struct iax_ies ies; 08257 struct iax_ie_data ied0, ied1; 08258 int format; 08259 int fd; 08260 int exists; 08261 int minivid = 0; 08262 char empty[32]=""; /* Safety measure */ 08263 struct iax_frame *duped_fr; 08264 char host_pref_buf[128]; 08265 char caller_pref_buf[128]; 08266 struct ast_codec_pref pref; 08267 char *using_prefs = "mine"; 08268 08269 /* allocate an iax_frame with 4096 bytes of data buffer */ 08270 fr = alloca(sizeof(*fr) + 4096); 08271 memset(fr, 0, sizeof(*fr)); 08272 fr->afdatalen = 4096; /* From alloca() above */ 08273 08274 /* Copy frequently used parameters to the stack */ 08275 res = thread->buf_len; 08276 fd = thread->iofd; 08277 memcpy(&sin, &thread->iosin, sizeof(sin)); 08278 08279 if (res < sizeof(*mh)) { 08280 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int) sizeof(*mh)); 08281 return 1; 08282 } 08283 if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { 08284 if (res < sizeof(*vh)) { 08285 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a video frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 08286 return 1; 08287 } 08288 08289 /* This is a video frame, get call number */ 08290 fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0); 08291 minivid = 1; 08292 } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) 08293 return socket_process_meta(res, meta, &sin, fd, fr); 08294 08295 #ifdef DEBUG_SUPPORT 08296 if (iaxdebug && (res >= sizeof(*fh))) 08297 iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh)); 08298 #endif 08299 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08300 if (res < sizeof(*fh)) { 08301 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a full frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 08302 return 1; 08303 } 08304 08305 /* Get the destination call number */ 08306 dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; 08307 /* Retrieve the type and subclass */ 08308 f.frametype = fh->type; 08309 if (f.frametype == AST_FRAME_VIDEO) { 08310 f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 08311 } else { 08312 f.subclass = uncompress_subclass(fh->csub); 08313 } 08314 08315 /* Deal with POKE/PONG without allocating a callno */ 08316 if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_POKE) { 08317 /* Reply back with a PONG, but don't care about the result. */ 08318 send_apathetic_reply(1, ntohs(fh->scallno), &sin, IAX_COMMAND_PONG, ntohl(fh->ts), fh->iseqno + 1); 08319 return 1; 08320 } else if (f.frametype == AST_FRAME_IAX && f.subclass == IAX_COMMAND_ACK && dcallno == 1) { 08321 /* Ignore */ 08322 return 1; 08323 } 08324 08325 if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) || 08326 (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) || 08327 (f.subclass == IAX_COMMAND_REGREL))) 08328 new = NEW_ALLOW; 08329 } else { 08330 /* Don't know anything about it yet */ 08331 f.frametype = AST_FRAME_NULL; 08332 f.subclass = 0; 08333 } 08334 08335 if (!fr->callno) { 08336 int check_dcallno = 0; 08337 08338 /* 08339 * We enforce accurate destination call numbers for all full frames except 08340 * LAGRQ and PING commands. This is because older versions of Asterisk 08341 * schedule these commands to get sent very quickly, and they will sometimes 08342 * be sent before they receive the first frame from the other side. When 08343 * that happens, it doesn't contain the destination call number. However, 08344 * not checking it for these frames is safe. 08345 * 08346 * Discussed in the following thread: 08347 * http://lists.digium.com/pipermail/asterisk-dev/2008-May/033217.html 08348 */ 08349 08350 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08351 check_dcallno = f.frametype == AST_FRAME_IAX ? (f.subclass != IAX_COMMAND_PING && f.subclass != IAX_COMMAND_LAGRQ) : 1; 08352 } 08353 08354 fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, check_dcallno); 08355 } 08356 08357 if (fr->callno > 0) 08358 ast_mutex_lock(&iaxsl[fr->callno]); 08359 08360 if (!fr->callno || !iaxs[fr->callno]) { 08361 /* A call arrived for a nonexistent destination. Unless it's an "inval" 08362 frame, reply with an inval */ 08363 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08364 /* We can only raw hangup control frames */ 08365 if (((f.subclass != IAX_COMMAND_INVAL) && 08366 (f.subclass != IAX_COMMAND_TXCNT) && 08367 (f.subclass != IAX_COMMAND_TXACC) && 08368 (f.subclass != IAX_COMMAND_FWDOWNL))|| 08369 (f.frametype != AST_FRAME_IAX)) 08370 raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL, 08371 fd); 08372 } 08373 if (fr->callno > 0) 08374 ast_mutex_unlock(&iaxsl[fr->callno]); 08375 return 1; 08376 } 08377 if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) { 08378 if (decrypt_frame(fr->callno, fh, &f, &res)) { 08379 ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); 08380 ast_mutex_unlock(&iaxsl[fr->callno]); 08381 return 1; 08382 } 08383 #ifdef DEBUG_SUPPORT 08384 else if (iaxdebug) 08385 iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh)); 08386 #endif 08387 } 08388 08389 /* count this frame */ 08390 iaxs[fr->callno]->frames_received++; 08391 08392 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid && 08393 f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */ 08394 f.subclass != IAX_COMMAND_TXACC) { /* for attended transfer */ 08395 unsigned short new_peercallno; 08396 08397 new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL); 08398 if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) { 08399 if (iaxs[fr->callno]->peercallno) { 08400 remove_by_peercallno(iaxs[fr->callno]); 08401 } 08402 iaxs[fr->callno]->peercallno = new_peercallno; 08403 store_by_peercallno(iaxs[fr->callno]); 08404 } 08405 } 08406 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 08407 if (iaxdebug) 08408 ast_debug(1, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); 08409 /* Check if it's out of order (and not an ACK or INVAL) */ 08410 fr->oseqno = fh->oseqno; 08411 fr->iseqno = fh->iseqno; 08412 fr->ts = ntohl(fh->ts); 08413 #ifdef IAXTESTS 08414 if (test_resync) { 08415 ast_debug(1, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync); 08416 fr->ts += test_resync; 08417 } 08418 #endif /* IAXTESTS */ 08419 #if 0 08420 if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || 08421 ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX && 08422 (f.subclass == IAX_COMMAND_NEW || 08423 f.subclass == IAX_COMMAND_AUTHREQ || 08424 f.subclass == IAX_COMMAND_ACCEPT || 08425 f.subclass == IAX_COMMAND_REJECT)) ) ) 08426 #endif 08427 if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE)) 08428 updatehistory = 0; 08429 if ((iaxs[fr->callno]->iseqno != fr->oseqno) && 08430 (iaxs[fr->callno]->iseqno || 08431 ((f.subclass != IAX_COMMAND_TXCNT) && 08432 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 08433 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 08434 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 08435 (f.subclass != IAX_COMMAND_TXACC)) || 08436 (f.frametype != AST_FRAME_IAX))) { 08437 if ( 08438 ((f.subclass != IAX_COMMAND_ACK) && 08439 (f.subclass != IAX_COMMAND_INVAL) && 08440 (f.subclass != IAX_COMMAND_TXCNT) && 08441 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 08442 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 08443 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 08444 (f.subclass != IAX_COMMAND_TXACC) && 08445 (f.subclass != IAX_COMMAND_VNAK)) || 08446 (f.frametype != AST_FRAME_IAX)) { 08447 /* If it's not an ACK packet, it's out of order. */ 08448 ast_debug(1, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 08449 iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass); 08450 /* Check to see if we need to request retransmission, 08451 * and take sequence number wraparound into account */ 08452 if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) { 08453 /* If we've already seen it, ack it XXX There's a border condition here XXX */ 08454 if ((f.frametype != AST_FRAME_IAX) || 08455 ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) { 08456 ast_debug(1, "Acking anyway\n"); 08457 /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if 08458 we have anything to send, we'll retransmit and get an ACK back anyway XXX */ 08459 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08460 } 08461 } else { 08462 /* Send a VNAK requesting retransmission */ 08463 iax2_vnak(fr->callno); 08464 } 08465 ast_mutex_unlock(&iaxsl[fr->callno]); 08466 return 1; 08467 } 08468 } else { 08469 /* Increment unless it's an ACK or VNAK */ 08470 if (((f.subclass != IAX_COMMAND_ACK) && 08471 (f.subclass != IAX_COMMAND_INVAL) && 08472 (f.subclass != IAX_COMMAND_TXCNT) && 08473 (f.subclass != IAX_COMMAND_TXACC) && 08474 (f.subclass != IAX_COMMAND_VNAK)) || 08475 (f.frametype != AST_FRAME_IAX)) 08476 iaxs[fr->callno]->iseqno++; 08477 } 08478 /* A full frame */ 08479 if (res < sizeof(*fh)) { 08480 ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int) sizeof(*fh)); 08481 ast_mutex_unlock(&iaxsl[fr->callno]); 08482 return 1; 08483 } 08484 /* Ensure text frames are NULL-terminated */ 08485 if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') { 08486 if (res < thread->buf_size) 08487 thread->buf[res++] = '\0'; 08488 else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */ 08489 thread->buf[res - 1] = '\0'; 08490 } 08491 f.datalen = res - sizeof(*fh); 08492 08493 /* Handle implicit ACKing unless this is an INVAL, and only if this is 08494 from the real peer, not the transfer peer */ 08495 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 08496 ((f.subclass != IAX_COMMAND_INVAL) || 08497 (f.frametype != AST_FRAME_IAX))) { 08498 unsigned char x; 08499 int call_to_destroy; 08500 /* XXX This code is not very efficient. Surely there is a better way which still 08501 properly handles boundary conditions? XXX */ 08502 /* First we have to qualify that the ACKed value is within our window */ 08503 for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++) 08504 if (fr->iseqno == x) 08505 break; 08506 if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) { 08507 /* The acknowledgement is within our window. Time to acknowledge everything 08508 that it says to */ 08509 for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) { 08510 /* Ack the packet with the given timestamp */ 08511 if (iaxdebug) 08512 ast_debug(1, "Cancelling transmission of packet %d\n", x); 08513 call_to_destroy = 0; 08514 AST_LIST_LOCK(&frame_queue); 08515 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 08516 /* If it's our call, and our timestamp, mark -1 retries */ 08517 if ((fr->callno == cur->callno) && (x == cur->oseqno)) { 08518 cur->retries = -1; 08519 /* Destroy call if this is the end */ 08520 if (cur->final) 08521 call_to_destroy = fr->callno; 08522 } 08523 } 08524 AST_LIST_UNLOCK(&frame_queue); 08525 if (call_to_destroy) { 08526 if (iaxdebug) 08527 ast_debug(1, "Really destroying %d, having been acked on final message\n", call_to_destroy); 08528 ast_mutex_lock(&iaxsl[call_to_destroy]); 08529 iax2_destroy(call_to_destroy); 08530 ast_mutex_unlock(&iaxsl[call_to_destroy]); 08531 } 08532 } 08533 /* Note how much we've received acknowledgement for */ 08534 if (iaxs[fr->callno]) 08535 iaxs[fr->callno]->rseqno = fr->iseqno; 08536 else { 08537 /* Stop processing now */ 08538 ast_mutex_unlock(&iaxsl[fr->callno]); 08539 return 1; 08540 } 08541 } else { 08542 ast_debug(1, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno); 08543 } 08544 } 08545 if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 08546 ((f.frametype != AST_FRAME_IAX) || 08547 ((f.subclass != IAX_COMMAND_TXACC) && 08548 (f.subclass != IAX_COMMAND_TXCNT)))) { 08549 /* Only messages we accept from a transfer host are TXACC and TXCNT */ 08550 ast_mutex_unlock(&iaxsl[fr->callno]); 08551 return 1; 08552 } 08553 08554 if (f.datalen) { 08555 if (f.frametype == AST_FRAME_IAX) { 08556 if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) { 08557 ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); 08558 ast_mutex_unlock(&iaxsl[fr->callno]); 08559 return 1; 08560 } 08561 f.data = NULL; 08562 f.datalen = 0; 08563 } else { 08564 f.data = thread->buf + sizeof(*fh); 08565 memset(&ies, 0, sizeof(ies)); 08566 } 08567 } else { 08568 if (f.frametype == AST_FRAME_IAX) 08569 f.data = NULL; 08570 else 08571 f.data = empty; 08572 memset(&ies, 0, sizeof(ies)); 08573 } 08574 08575 /* when we receive the first full frame for a new incoming channel, 08576 it is safe to start the PBX on the channel because we have now 08577 completed a 3-way handshake with the peer */ 08578 if ((f.frametype == AST_FRAME_VOICE) || 08579 (f.frametype == AST_FRAME_VIDEO) || 08580 (f.frametype == AST_FRAME_IAX)) { 08581 if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) { 08582 ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 08583 if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) { 08584 ast_mutex_unlock(&iaxsl[fr->callno]); 08585 return 1; 08586 } 08587 } 08588 08589 if (ies.vars) { 08590 struct ast_datastore *variablestore; 08591 struct ast_variable *var, *prev = NULL; 08592 AST_LIST_HEAD(, ast_var_t) *varlist; 08593 if ((c = iaxs[fr->callno]->owner)) { 08594 varlist = ast_calloc(1, sizeof(*varlist)); 08595 variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); 08596 if (variablestore && varlist) { 08597 variablestore->data = varlist; 08598 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 08599 AST_LIST_HEAD_INIT(varlist); 08600 ast_debug(1, "I can haz IAX vars?\n"); 08601 for (var = ies.vars; var; var = var->next) { 08602 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 08603 if (prev) { 08604 ast_free(prev); 08605 } 08606 prev = var; 08607 if (!newvar) { 08608 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 08609 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 08610 } else { 08611 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 08612 } 08613 } 08614 if (prev) { 08615 ast_free(prev); 08616 } 08617 ies.vars = NULL; 08618 ast_channel_datastore_add(c, variablestore); 08619 } else { 08620 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 08621 if (variablestore) { 08622 ast_channel_datastore_free(variablestore); 08623 } 08624 if (varlist) { 08625 ast_free(varlist); 08626 } 08627 } 08628 } else { 08629 /* No channel yet, so transfer the variables directly over to the pvt, 08630 * for later inheritance. */ 08631 ast_debug(1, "No channel, so populating IAXVARs to the pvt, as an intermediate step.\n"); 08632 for (var = ies.vars; var && var->next; var = var->next); 08633 if (var) { 08634 var->next = iaxs[fr->callno]->iaxvars; 08635 iaxs[fr->callno]->iaxvars = ies.vars; 08636 ies.vars = NULL; 08637 } 08638 } 08639 } 08640 } 08641 08642 if (ies.vars) { 08643 ast_debug(1, "I have IAX variables, but they were not processed\n"); 08644 } 08645 08646 if (f.frametype == AST_FRAME_VOICE) { 08647 if (f.subclass != iaxs[fr->callno]->voiceformat) { 08648 iaxs[fr->callno]->voiceformat = f.subclass; 08649 ast_debug(1, "Ooh, voice format changed to %d\n", f.subclass); 08650 if (iaxs[fr->callno]->owner) { 08651 int orignative; 08652 retryowner: 08653 if (ast_channel_trylock(iaxs[fr->callno]->owner)) { 08654 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 08655 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; 08656 } 08657 if (iaxs[fr->callno]) { 08658 if (iaxs[fr->callno]->owner) { 08659 orignative = iaxs[fr->callno]->owner->nativeformats; 08660 iaxs[fr->callno]->owner->nativeformats = f.subclass; 08661 if (iaxs[fr->callno]->owner->readformat) 08662 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 08663 iaxs[fr->callno]->owner->nativeformats = orignative; 08664 ast_channel_unlock(iaxs[fr->callno]->owner); 08665 } 08666 } else { 08667 ast_debug(1, "Neat, somebody took away the channel at a magical time but i found it!\n"); 08668 /* Free remote variables (if any) */ 08669 if (ies.vars) { 08670 ast_variables_destroy(ies.vars); 08671 ast_debug(1, "I can haz iaxvars, but they is no good. :-(\n"); 08672 ies.vars = NULL; 08673 } 08674 ast_mutex_unlock(&iaxsl[fr->callno]); 08675 return 1; 08676 } 08677 } 08678 } 08679 } 08680 if (f.frametype == AST_FRAME_VIDEO) { 08681 if (f.subclass != iaxs[fr->callno]->videoformat) { 08682 ast_debug(1, "Ooh, video format changed to %d\n", f.subclass & ~0x1); 08683 iaxs[fr->callno]->videoformat = f.subclass & ~0x1; 08684 } 08685 } 08686 if (f.frametype == AST_FRAME_CONTROL && iaxs[fr->callno]->owner) { 08687 if (f.subclass == AST_CONTROL_BUSY) { 08688 iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_BUSY; 08689 } else if (f.subclass == AST_CONTROL_CONGESTION) { 08690 iaxs[fr->callno]->owner->hangupcause = AST_CAUSE_CONGESTION; 08691 } 08692 } 08693 if (f.frametype == AST_FRAME_IAX) { 08694 AST_SCHED_DEL(sched, iaxs[fr->callno]->initid); 08695 /* Handle the IAX pseudo frame itself */ 08696 if (iaxdebug) 08697 ast_debug(1, "IAX subclass %d received\n", f.subclass); 08698 08699 /* Update last ts unless the frame's timestamp originated with us. */ 08700 if (iaxs[fr->callno]->last < fr->ts && 08701 f.subclass != IAX_COMMAND_ACK && 08702 f.subclass != IAX_COMMAND_PONG && 08703 f.subclass != IAX_COMMAND_LAGRP) { 08704 iaxs[fr->callno]->last = fr->ts; 08705 if (iaxdebug) 08706 ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts); 08707 } 08708 iaxs[fr->callno]->last_iax_message = f.subclass; 08709 if (!iaxs[fr->callno]->first_iax_message) { 08710 iaxs[fr->callno]->first_iax_message = f.subclass; 08711 } 08712 switch(f.subclass) { 08713 case IAX_COMMAND_ACK: 08714 /* Do nothing */ 08715 break; 08716 case IAX_COMMAND_QUELCH: 08717 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08718 /* Generate Manager Hold event, if necessary*/ 08719 if (iaxs[fr->callno]->owner) { 08720 manager_event(EVENT_FLAG_CALL, "Hold", 08721 "Status: On\r\n" 08722 "Channel: %s\r\n" 08723 "Uniqueid: %s\r\n", 08724 iaxs[fr->callno]->owner->name, 08725 iaxs[fr->callno]->owner->uniqueid); 08726 } 08727 08728 ast_set_flag(iaxs[fr->callno], IAX_QUELCH); 08729 if (ies.musiconhold) { 08730 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 08731 const char *mohsuggest = iaxs[fr->callno]->mohsuggest; 08732 iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, 08733 S_OR(mohsuggest, NULL), 08734 !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0); 08735 if (!iaxs[fr->callno]) { 08736 ast_mutex_unlock(&iaxsl[fr->callno]); 08737 return 1; 08738 } 08739 } 08740 } 08741 } 08742 break; 08743 case IAX_COMMAND_UNQUELCH: 08744 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08745 /* Generate Manager Unhold event, if necessary*/ 08746 if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) { 08747 manager_event(EVENT_FLAG_CALL, "Hold", 08748 "Status: Off\r\n" 08749 "Channel: %s\r\n" 08750 "Uniqueid: %s\r\n", 08751 iaxs[fr->callno]->owner->name, 08752 iaxs[fr->callno]->owner->uniqueid); 08753 } 08754 08755 ast_clear_flag(iaxs[fr->callno], IAX_QUELCH); 08756 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 08757 iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); 08758 if (!iaxs[fr->callno]) { 08759 ast_mutex_unlock(&iaxsl[fr->callno]); 08760 return 1; 08761 } 08762 } 08763 } 08764 break; 08765 case IAX_COMMAND_TXACC: 08766 if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { 08767 /* Ack the packet with the given timestamp */ 08768 AST_LIST_LOCK(&frame_queue); 08769 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 08770 /* Cancel any outstanding txcnt's */ 08771 if ((fr->callno == cur->callno) && (cur->transfer)) 08772 cur->retries = -1; 08773 } 08774 AST_LIST_UNLOCK(&frame_queue); 08775 memset(&ied1, 0, sizeof(ied1)); 08776 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno); 08777 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1); 08778 iaxs[fr->callno]->transferring = TRANSFER_READY; 08779 } 08780 break; 08781 case IAX_COMMAND_NEW: 08782 /* Ignore if it's already up */ 08783 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) 08784 break; 08785 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 08786 ast_mutex_unlock(&iaxsl[fr->callno]); 08787 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 08788 ast_mutex_lock(&iaxsl[fr->callno]); 08789 if (!iaxs[fr->callno]) { 08790 ast_mutex_unlock(&iaxsl[fr->callno]); 08791 return 1; 08792 } 08793 } 08794 /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ 08795 if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) { 08796 int new_callno; 08797 if ((new_callno = make_trunk(fr->callno, 1)) != -1) 08798 fr->callno = new_callno; 08799 } 08800 /* For security, always ack immediately */ 08801 if (delayreject) 08802 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 08803 if (check_access(fr->callno, &sin, &ies)) { 08804 /* They're not allowed on */ 08805 auth_fail(fr->callno, IAX_COMMAND_REJECT); 08806 if (authdebug) 08807 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, who was trying to reach '%s@%s'\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 08808 break; 08809 } 08810 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 08811 const char *context, *exten, *cid_num; 08812 08813 context = ast_strdupa(iaxs[fr->callno]->context); 08814 exten = ast_strdupa(iaxs[fr->callno]->exten); 08815 cid_num = ast_strdupa(iaxs[fr->callno]->cid_num); 08816 08817 /* This might re-enter the IAX code and need the lock */ 08818 ast_mutex_unlock(&iaxsl[fr->callno]); 08819 exists = ast_exists_extension(NULL, context, exten, 1, cid_num); 08820 ast_mutex_lock(&iaxsl[fr->callno]); 08821 08822 if (!iaxs[fr->callno]) { 08823 ast_mutex_unlock(&iaxsl[fr->callno]); 08824 return 1; 08825 } 08826 } else 08827 exists = 0; 08828 /* Get OSP token if it does exist */ 08829 save_osptoken(fr, &ies); 08830 if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { 08831 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 08832 memset(&ied0, 0, sizeof(ied0)); 08833 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 08834 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 08835 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08836 if (!iaxs[fr->callno]) { 08837 ast_mutex_unlock(&iaxsl[fr->callno]); 08838 return 1; 08839 } 08840 if (authdebug) 08841 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 08842 } else { 08843 /* Select an appropriate format */ 08844 08845 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08846 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08847 using_prefs = "reqonly"; 08848 } else { 08849 using_prefs = "disabled"; 08850 } 08851 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 08852 memset(&pref, 0, sizeof(pref)); 08853 strcpy(caller_pref_buf, "disabled"); 08854 strcpy(host_pref_buf, "disabled"); 08855 } else { 08856 using_prefs = "mine"; 08857 /* If the information elements are in here... use them */ 08858 if (ies.codec_prefs) 08859 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 08860 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08861 /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ 08862 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08863 pref = iaxs[fr->callno]->rprefs; 08864 using_prefs = "caller"; 08865 } else { 08866 pref = iaxs[fr->callno]->prefs; 08867 } 08868 } else 08869 pref = iaxs[fr->callno]->prefs; 08870 08871 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 08872 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 08873 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 08874 } 08875 if (!format) { 08876 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08877 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 08878 if (!format) { 08879 memset(&ied0, 0, sizeof(ied0)); 08880 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08881 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08882 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08883 if (!iaxs[fr->callno]) { 08884 ast_mutex_unlock(&iaxsl[fr->callno]); 08885 return 1; 08886 } 08887 if (authdebug) { 08888 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 08889 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 08890 else 08891 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 08892 } 08893 } else { 08894 /* Pick one... */ 08895 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 08896 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 08897 format = 0; 08898 } else { 08899 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 08900 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 08901 memset(&pref, 0, sizeof(pref)); 08902 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08903 strcpy(caller_pref_buf,"disabled"); 08904 strcpy(host_pref_buf,"disabled"); 08905 } else { 08906 using_prefs = "mine"; 08907 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 08908 /* Do the opposite of what we tried above. */ 08909 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 08910 pref = iaxs[fr->callno]->prefs; 08911 } else { 08912 pref = iaxs[fr->callno]->rprefs; 08913 using_prefs = "caller"; 08914 } 08915 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 08916 08917 } else /* if no codec_prefs IE do it the old way */ 08918 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08919 } 08920 } 08921 08922 if (!format) { 08923 memset(&ied0, 0, sizeof(ied0)); 08924 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 08925 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 08926 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 08927 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 08928 if (!iaxs[fr->callno]) { 08929 ast_mutex_unlock(&iaxsl[fr->callno]); 08930 return 1; 08931 } 08932 if (authdebug) 08933 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 08934 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 08935 break; 08936 } 08937 } 08938 } 08939 if (format) { 08940 /* No authentication required, let them in */ 08941 memset(&ied1, 0, sizeof(ied1)); 08942 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 08943 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 08944 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 08945 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 08946 ast_verb(3, "Accepting UNAUTHENTICATED call from %s:\n" 08947 "%srequested format = %s,\n" 08948 "%srequested prefs = %s,\n" 08949 "%sactual format = %s,\n" 08950 "%shost prefs = %s,\n" 08951 "%spriority = %s\n", 08952 ast_inet_ntoa(sin.sin_addr), 08953 VERBOSE_PREFIX_4, 08954 ast_getformatname(iaxs[fr->callno]->peerformat), 08955 VERBOSE_PREFIX_4, 08956 caller_pref_buf, 08957 VERBOSE_PREFIX_4, 08958 ast_getformatname(format), 08959 VERBOSE_PREFIX_4, 08960 host_pref_buf, 08961 VERBOSE_PREFIX_4, 08962 using_prefs); 08963 08964 iaxs[fr->callno]->chosenformat = format; 08965 ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 08966 } else { 08967 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 08968 /* If this is a TBD call, we're ready but now what... */ 08969 ast_verb(3, "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 08970 } 08971 } 08972 } 08973 break; 08974 } 08975 if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5) 08976 merge_encryption(iaxs[fr->callno],ies.encmethods); 08977 else 08978 iaxs[fr->callno]->encmethods = 0; 08979 if (!authenticate_request(fr->callno) && iaxs[fr->callno]) 08980 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); 08981 if (!iaxs[fr->callno]) { 08982 ast_mutex_unlock(&iaxsl[fr->callno]); 08983 return 1; 08984 } 08985 break; 08986 case IAX_COMMAND_DPREQ: 08987 /* Request status in the dialplan */ 08988 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) && 08989 !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) { 08990 if (iaxcompat) { 08991 /* Spawn a thread for the lookup */ 08992 spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num); 08993 } else { 08994 /* Just look it up */ 08995 dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1); 08996 } 08997 } 08998 break; 08999 case IAX_COMMAND_HANGUP: 09000 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 09001 ast_debug(1, "Immediately destroying %d, having received hangup\n", fr->callno); 09002 /* Set hangup cause according to remote */ 09003 if (ies.causecode && iaxs[fr->callno]->owner) 09004 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 09005 /* Send ack immediately, before we destroy */ 09006 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09007 iax2_destroy(fr->callno); 09008 break; 09009 case IAX_COMMAND_REJECT: 09010 /* Set hangup cause according to remote */ 09011 if (ies.causecode && iaxs[fr->callno]->owner) 09012 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 09013 09014 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 09015 if (iaxs[fr->callno]->owner && authdebug) 09016 ast_log(LOG_WARNING, "Call rejected by %s: %s\n", 09017 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), 09018 ies.cause ? ies.cause : "<Unknown>"); 09019 ast_debug(1, "Immediately destroying %d, having received reject\n", 09020 fr->callno); 09021 } 09022 /* Send ack immediately, before we destroy */ 09023 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, 09024 fr->ts, NULL, 0, fr->iseqno); 09025 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) 09026 iaxs[fr->callno]->error = EPERM; 09027 iax2_destroy(fr->callno); 09028 break; 09029 case IAX_COMMAND_TRANSFER: 09030 { 09031 struct ast_channel *bridged_chan; 09032 09033 if (iaxs[fr->callno]->owner && (bridged_chan = ast_bridged_channel(iaxs[fr->callno]->owner)) && ies.called_number) { 09034 /* Set BLINDTRANSFER channel variables */ 09035 09036 ast_mutex_unlock(&iaxsl[fr->callno]); 09037 pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", bridged_chan->name); 09038 ast_mutex_lock(&iaxsl[fr->callno]); 09039 if (!iaxs[fr->callno]) { 09040 ast_mutex_unlock(&iaxsl[fr->callno]); 09041 return 1; 09042 } 09043 09044 pbx_builtin_setvar_helper(bridged_chan, "BLINDTRANSFER", iaxs[fr->callno]->owner->name); 09045 if (!strcmp(ies.called_number, ast_parking_ext())) { 09046 struct ast_channel *saved_channel = iaxs[fr->callno]->owner; 09047 ast_mutex_unlock(&iaxsl[fr->callno]); 09048 if (iax_park(bridged_chan, saved_channel)) { 09049 ast_log(LOG_WARNING, "Failed to park call on '%s'\n", bridged_chan->name); 09050 } else { 09051 ast_debug(1, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name); 09052 } 09053 ast_mutex_lock(&iaxsl[fr->callno]); 09054 } else { 09055 if (ast_async_goto(bridged_chan, iaxs[fr->callno]->context, ies.called_number, 1)) 09056 ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", bridged_chan->name, 09057 ies.called_number, iaxs[fr->callno]->context); 09058 else { 09059 ast_debug(1, "Async goto of '%s' to '%s@%s' started\n", bridged_chan->name, 09060 ies.called_number, iaxs[fr->callno]->context); 09061 } 09062 } 09063 } else { 09064 ast_debug(1, "Async goto not applicable on call %d\n", fr->callno); 09065 } 09066 09067 break; 09068 } 09069 case IAX_COMMAND_ACCEPT: 09070 /* Ignore if call is already up or needs authentication or is a TBD */ 09071 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED)) 09072 break; 09073 if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 09074 /* Send ack immediately, before we destroy */ 09075 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09076 iax2_destroy(fr->callno); 09077 break; 09078 } 09079 if (ies.format) { 09080 iaxs[fr->callno]->peerformat = ies.format; 09081 } else { 09082 if (iaxs[fr->callno]->owner) 09083 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; 09084 else 09085 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; 09086 } 09087 ast_verb(3, "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat)); 09088 if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { 09089 memset(&ied0, 0, sizeof(ied0)); 09090 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09091 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09092 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09093 if (!iaxs[fr->callno]) { 09094 ast_mutex_unlock(&iaxsl[fr->callno]); 09095 return 1; 09096 } 09097 if (authdebug) 09098 ast_log(LOG_NOTICE, "Rejected call to %s, format 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 09099 } else { 09100 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09101 if (iaxs[fr->callno]->owner) { 09102 /* Switch us to use a compatible format */ 09103 iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; 09104 ast_verb(3, "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); 09105 retryowner2: 09106 if (ast_channel_trylock(iaxs[fr->callno]->owner)) { 09107 DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]); 09108 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; 09109 } 09110 09111 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { 09112 /* Setup read/write formats properly. */ 09113 if (iaxs[fr->callno]->owner->writeformat) 09114 ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); 09115 if (iaxs[fr->callno]->owner->readformat) 09116 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 09117 ast_channel_unlock(iaxs[fr->callno]->owner); 09118 } 09119 } 09120 } 09121 if (iaxs[fr->callno]) { 09122 AST_LIST_LOCK(&dpcache); 09123 AST_LIST_TRAVERSE(&iaxs[fr->callno]->dpentries, dp, peer_list) 09124 if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) 09125 iax2_dprequest(dp, fr->callno); 09126 AST_LIST_UNLOCK(&dpcache); 09127 } 09128 break; 09129 case IAX_COMMAND_POKE: 09130 /* Send back a pong packet with the original timestamp */ 09131 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); 09132 if (!iaxs[fr->callno]) { 09133 ast_mutex_unlock(&iaxsl[fr->callno]); 09134 return 1; 09135 } 09136 break; 09137 case IAX_COMMAND_PING: 09138 { 09139 struct iax_ie_data pingied; 09140 construct_rr(iaxs[fr->callno], &pingied); 09141 /* Send back a pong packet with the original timestamp */ 09142 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1); 09143 } 09144 break; 09145 case IAX_COMMAND_PONG: 09146 /* Calculate ping time */ 09147 iaxs[fr->callno]->pingtime = calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts; 09148 /* save RR info */ 09149 save_rr(fr, &ies); 09150 09151 /* Good time to write jb stats for this call */ 09152 log_jitterstats(fr->callno); 09153 09154 if (iaxs[fr->callno]->peerpoke) { 09155 peer = iaxs[fr->callno]->peerpoke; 09156 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) { 09157 if (iaxs[fr->callno]->pingtime <= peer->maxms) { 09158 ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime); 09159 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 09160 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 09161 } 09162 } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) { 09163 if (iaxs[fr->callno]->pingtime > peer->maxms) { 09164 ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime); 09165 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 09166 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 09167 } 09168 } 09169 peer->lastms = iaxs[fr->callno]->pingtime; 09170 if (peer->smoothing && (peer->lastms > -1)) 09171 peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2; 09172 else if (peer->smoothing && peer->lastms < 0) 09173 peer->historicms = (0 + peer->historicms) / 2; 09174 else 09175 peer->historicms = iaxs[fr->callno]->pingtime; 09176 09177 /* Remove scheduled iax2_poke_noanswer */ 09178 if (peer->pokeexpire > -1) { 09179 if (!ast_sched_del(sched, peer->pokeexpire)) { 09180 peer_unref(peer); 09181 peer->pokeexpire = -1; 09182 } 09183 } 09184 /* Schedule the next cycle */ 09185 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) 09186 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer_ref(peer)); 09187 else 09188 peer->pokeexpire = iax2_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer_ref(peer)); 09189 if (peer->pokeexpire == -1) 09190 peer_unref(peer); 09191 /* and finally send the ack */ 09192 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09193 /* And wrap up the qualify call */ 09194 iax2_destroy(fr->callno); 09195 peer->callno = 0; 09196 ast_debug(1, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms); 09197 } 09198 break; 09199 case IAX_COMMAND_LAGRQ: 09200 case IAX_COMMAND_LAGRP: 09201 f.src = "LAGRQ"; 09202 f.mallocd = 0; 09203 f.offset = 0; 09204 f.samples = 0; 09205 iax_frame_wrap(fr, &f); 09206 if(f.subclass == IAX_COMMAND_LAGRQ) { 09207 /* Received a LAGRQ - echo back a LAGRP */ 09208 fr->af.subclass = IAX_COMMAND_LAGRP; 09209 iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0); 09210 } else { 09211 /* Received LAGRP in response to our LAGRQ */ 09212 unsigned int ts; 09213 /* This is a reply we've been given, actually measure the difference */ 09214 ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af); 09215 iaxs[fr->callno]->lag = ts - fr->ts; 09216 if (iaxdebug) 09217 ast_debug(1, "Peer %s lag measured as %dms\n", 09218 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag); 09219 } 09220 break; 09221 case IAX_COMMAND_AUTHREQ: 09222 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 09223 ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 09224 break; 09225 } 09226 if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) { 09227 struct ast_frame hangup_fr = { .frametype = AST_FRAME_CONTROL, 09228 .subclass = AST_CONTROL_HANGUP, 09229 }; 09230 ast_log(LOG_WARNING, 09231 "I don't know how to authenticate %s to %s\n", 09232 ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); 09233 iax2_queue_frame(fr->callno, &hangup_fr); 09234 } 09235 if (!iaxs[fr->callno]) { 09236 ast_mutex_unlock(&iaxsl[fr->callno]); 09237 return 1; 09238 } 09239 break; 09240 case IAX_COMMAND_AUTHREP: 09241 /* For security, always ack immediately */ 09242 if (delayreject) 09243 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09244 /* Ignore once we've started */ 09245 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 09246 ast_log(LOG_WARNING, "Call on %s is already up, can't start on it\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 09247 break; 09248 } 09249 if (authenticate_verify(iaxs[fr->callno], &ies)) { 09250 if (authdebug) 09251 ast_log(LOG_NOTICE, "Host %s failed to authenticate as %s\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->username); 09252 memset(&ied0, 0, sizeof(ied0)); 09253 auth_fail(fr->callno, IAX_COMMAND_REJECT); 09254 break; 09255 } 09256 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 09257 /* This might re-enter the IAX code and need the lock */ 09258 exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num); 09259 } else 09260 exists = 0; 09261 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 09262 if (authdebug) 09263 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 09264 memset(&ied0, 0, sizeof(ied0)); 09265 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 09266 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 09267 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09268 if (!iaxs[fr->callno]) { 09269 ast_mutex_unlock(&iaxsl[fr->callno]); 09270 return 1; 09271 } 09272 } else { 09273 /* Select an appropriate format */ 09274 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 09275 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09276 using_prefs = "reqonly"; 09277 } else { 09278 using_prefs = "disabled"; 09279 } 09280 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 09281 memset(&pref, 0, sizeof(pref)); 09282 strcpy(caller_pref_buf, "disabled"); 09283 strcpy(host_pref_buf, "disabled"); 09284 } else { 09285 using_prefs = "mine"; 09286 if (ies.codec_prefs) 09287 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 09288 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 09289 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 09290 pref = iaxs[fr->callno]->rprefs; 09291 using_prefs = "caller"; 09292 } else { 09293 pref = iaxs[fr->callno]->prefs; 09294 } 09295 } else /* if no codec_prefs IE do it the old way */ 09296 pref = iaxs[fr->callno]->prefs; 09297 09298 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 09299 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 09300 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 09301 } 09302 if (!format) { 09303 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09304 ast_debug(1, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability); 09305 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 09306 } 09307 if (!format) { 09308 if (authdebug) { 09309 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 09310 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 09311 else 09312 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 09313 } 09314 memset(&ied0, 0, sizeof(ied0)); 09315 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09316 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09317 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09318 if (!iaxs[fr->callno]) { 09319 ast_mutex_unlock(&iaxsl[fr->callno]); 09320 return 1; 09321 } 09322 } else { 09323 /* Pick one... */ 09324 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 09325 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 09326 format = 0; 09327 } else { 09328 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 09329 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 09330 memset(&pref, 0, sizeof(pref)); 09331 format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? 09332 iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09333 strcpy(caller_pref_buf,"disabled"); 09334 strcpy(host_pref_buf,"disabled"); 09335 } else { 09336 using_prefs = "mine"; 09337 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 09338 /* Do the opposite of what we tried above. */ 09339 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 09340 pref = iaxs[fr->callno]->prefs; 09341 } else { 09342 pref = iaxs[fr->callno]->rprefs; 09343 using_prefs = "caller"; 09344 } 09345 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 09346 } else /* if no codec_prefs IE do it the old way */ 09347 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09348 } 09349 } 09350 if (!format) { 09351 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 09352 if (authdebug) { 09353 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 09354 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->capability); 09355 else 09356 ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat, iaxs[fr->callno]->peercapability, iaxs[fr->callno]->capability); 09357 } 09358 memset(&ied0, 0, sizeof(ied0)); 09359 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 09360 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 09361 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09362 if (!iaxs[fr->callno]) { 09363 ast_mutex_unlock(&iaxsl[fr->callno]); 09364 return 1; 09365 } 09366 } 09367 } 09368 } 09369 if (format) { 09370 /* Authentication received */ 09371 memset(&ied1, 0, sizeof(ied1)); 09372 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 09373 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 09374 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 09375 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09376 ast_verb(3, "Accepting AUTHENTICATED call from %s:\n" 09377 "%srequested format = %s,\n" 09378 "%srequested prefs = %s,\n" 09379 "%sactual format = %s,\n" 09380 "%shost prefs = %s,\n" 09381 "%spriority = %s\n", 09382 ast_inet_ntoa(sin.sin_addr), 09383 VERBOSE_PREFIX_4, 09384 ast_getformatname(iaxs[fr->callno]->peerformat), 09385 VERBOSE_PREFIX_4, 09386 caller_pref_buf, 09387 VERBOSE_PREFIX_4, 09388 ast_getformatname(format), 09389 VERBOSE_PREFIX_4, 09390 host_pref_buf, 09391 VERBOSE_PREFIX_4, 09392 using_prefs); 09393 09394 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09395 if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format))) 09396 iax2_destroy(fr->callno); 09397 else if (ies.vars) { 09398 struct ast_datastore *variablestore; 09399 struct ast_variable *var, *prev = NULL; 09400 AST_LIST_HEAD(, ast_var_t) *varlist; 09401 varlist = ast_calloc(1, sizeof(*varlist)); 09402 variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); 09403 if (variablestore && varlist) { 09404 variablestore->data = varlist; 09405 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 09406 AST_LIST_HEAD_INIT(varlist); 09407 ast_debug(1, "I can haz IAX vars? w00t\n"); 09408 for (var = ies.vars; var; var = var->next) { 09409 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 09410 if (prev) 09411 ast_free(prev); 09412 prev = var; 09413 if (!newvar) { 09414 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 09415 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09416 } else { 09417 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 09418 } 09419 } 09420 if (prev) 09421 ast_free(prev); 09422 ies.vars = NULL; 09423 ast_channel_datastore_add(c, variablestore); 09424 } else { 09425 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09426 if (variablestore) 09427 ast_channel_datastore_free(variablestore); 09428 if (varlist) 09429 ast_free(varlist); 09430 } 09431 } 09432 } else { 09433 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 09434 /* If this is a TBD call, we're ready but now what... */ 09435 ast_verb(3, "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 09436 } 09437 } 09438 } 09439 break; 09440 case IAX_COMMAND_DIAL: 09441 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) { 09442 ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 09443 ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); 09444 if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { 09445 if (authdebug) 09446 ast_log(LOG_NOTICE, "Rejected dial attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->exten, iaxs[fr->callno]->context); 09447 memset(&ied0, 0, sizeof(ied0)); 09448 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 09449 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 09450 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09451 if (!iaxs[fr->callno]) { 09452 ast_mutex_unlock(&iaxsl[fr->callno]); 09453 return 1; 09454 } 09455 } else { 09456 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09457 ast_verb(3, "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat); 09458 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 09459 send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); 09460 if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat))) 09461 iax2_destroy(fr->callno); 09462 else if (ies.vars) { 09463 struct ast_datastore *variablestore; 09464 struct ast_variable *var, *prev = NULL; 09465 AST_LIST_HEAD(, ast_var_t) *varlist; 09466 varlist = ast_calloc(1, sizeof(*varlist)); 09467 variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); 09468 if (variablestore && varlist) { 09469 variablestore->data = varlist; 09470 variablestore->inheritance = DATASTORE_INHERIT_FOREVER; 09471 AST_LIST_HEAD_INIT(varlist); 09472 for (var = ies.vars; var; var = var->next) { 09473 struct ast_var_t *newvar = ast_var_assign(var->name, var->value); 09474 if (prev) 09475 ast_free(prev); 09476 prev = var; 09477 if (!newvar) { 09478 /* Don't abort list traversal, as this would leave ies.vars in an inconsistent state. */ 09479 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09480 } else { 09481 AST_LIST_INSERT_TAIL(varlist, newvar, entries); 09482 } 09483 } 09484 if (prev) 09485 ast_free(prev); 09486 ies.vars = NULL; 09487 ast_channel_datastore_add(c, variablestore); 09488 } else { 09489 ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); 09490 if (variablestore) 09491 ast_channel_datastore_free(variablestore); 09492 if (varlist) 09493 ast_free(varlist); 09494 } 09495 } 09496 } 09497 } 09498 break; 09499 case IAX_COMMAND_INVAL: 09500 iaxs[fr->callno]->error = ENOTCONN; 09501 ast_debug(1, "Immediately destroying %d, having received INVAL\n", fr->callno); 09502 iax2_destroy(fr->callno); 09503 ast_debug(1, "Destroying call %d\n", fr->callno); 09504 break; 09505 case IAX_COMMAND_VNAK: 09506 ast_debug(1, "Received VNAK: resending outstanding frames\n"); 09507 /* Force retransmission */ 09508 vnak_retransmit(fr->callno, fr->iseqno); 09509 break; 09510 case IAX_COMMAND_REGREQ: 09511 case IAX_COMMAND_REGREL: 09512 /* For security, always ack immediately */ 09513 if (delayreject) 09514 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09515 if (register_verify(fr->callno, &sin, &ies)) { 09516 if (!iaxs[fr->callno]) { 09517 ast_mutex_unlock(&iaxsl[fr->callno]); 09518 return 1; 09519 } 09520 /* Send delayed failure */ 09521 auth_fail(fr->callno, IAX_COMMAND_REGREJ); 09522 break; 09523 } 09524 if (!iaxs[fr->callno]) { 09525 ast_mutex_unlock(&iaxsl[fr->callno]); 09526 return 1; 09527 } 09528 if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 09529 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED)) { 09530 09531 if (f.subclass == IAX_COMMAND_REGREL) 09532 memset(&sin, 0, sizeof(sin)); 09533 if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) 09534 ast_log(LOG_WARNING, "Registry error\n"); 09535 if (!iaxs[fr->callno]) { 09536 ast_mutex_unlock(&iaxsl[fr->callno]); 09537 return 1; 09538 } 09539 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { 09540 ast_mutex_unlock(&iaxsl[fr->callno]); 09541 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 09542 ast_mutex_lock(&iaxsl[fr->callno]); 09543 if (!iaxs[fr->callno]) { 09544 ast_mutex_unlock(&iaxsl[fr->callno]); 09545 return 1; 09546 } 09547 } 09548 break; 09549 } 09550 registry_authrequest(fr->callno); 09551 if (!iaxs[fr->callno]) { 09552 ast_mutex_unlock(&iaxsl[fr->callno]); 09553 return 1; 09554 } 09555 break; 09556 case IAX_COMMAND_REGACK: 09557 if (iax2_ack_registry(&ies, &sin, fr->callno)) 09558 ast_log(LOG_WARNING, "Registration failure\n"); 09559 /* Send ack immediately, before we destroy */ 09560 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09561 iax2_destroy(fr->callno); 09562 break; 09563 case IAX_COMMAND_REGREJ: 09564 if (iaxs[fr->callno]->reg) { 09565 if (authdebug) { 09566 ast_log(LOG_NOTICE, "Registration of '%s' rejected: '%s' from: '%s'\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>", ast_inet_ntoa(sin.sin_addr)); 09567 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>"); 09568 } 09569 iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; 09570 } 09571 /* Send ack immediately, before we destroy */ 09572 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09573 iax2_destroy(fr->callno); 09574 break; 09575 case IAX_COMMAND_REGAUTH: 09576 /* Authentication request */ 09577 if (registry_rerequest(&ies, fr->callno, &sin)) { 09578 memset(&ied0, 0, sizeof(ied0)); 09579 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); 09580 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 09581 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09582 if (!iaxs[fr->callno]) { 09583 ast_mutex_unlock(&iaxsl[fr->callno]); 09584 return 1; 09585 } 09586 } 09587 break; 09588 case IAX_COMMAND_TXREJ: 09589 iaxs[fr->callno]->transferring = 0; 09590 ast_verb(3, "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 09591 memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer)); 09592 if (iaxs[fr->callno]->bridgecallno) { 09593 if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { 09594 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0; 09595 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 09596 } 09597 } 09598 break; 09599 case IAX_COMMAND_TXREADY: 09600 if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || 09601 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) { 09602 if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) 09603 iaxs[fr->callno]->transferring = TRANSFER_MREADY; 09604 else 09605 iaxs[fr->callno]->transferring = TRANSFER_READY; 09606 ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 09607 if (iaxs[fr->callno]->bridgecallno) { 09608 if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || 09609 (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { 09610 /* They're both ready, now release them. */ 09611 if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) { 09612 ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 09613 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 09614 09615 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; 09616 iaxs[fr->callno]->transferring = TRANSFER_MEDIA; 09617 09618 memset(&ied0, 0, sizeof(ied0)); 09619 memset(&ied1, 0, sizeof(ied1)); 09620 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 09621 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 09622 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1); 09623 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1); 09624 } else { 09625 ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 09626 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 09627 09628 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED; 09629 iaxs[fr->callno]->transferring = TRANSFER_RELEASED; 09630 ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE); 09631 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 09632 09633 /* Stop doing lag & ping requests */ 09634 stop_stuff(fr->callno); 09635 stop_stuff(iaxs[fr->callno]->bridgecallno); 09636 09637 memset(&ied0, 0, sizeof(ied0)); 09638 memset(&ied1, 0, sizeof(ied1)); 09639 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 09640 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 09641 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1); 09642 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1); 09643 } 09644 09645 } 09646 } 09647 } 09648 break; 09649 case IAX_COMMAND_TXREQ: 09650 try_transfer(iaxs[fr->callno], &ies); 09651 break; 09652 case IAX_COMMAND_TXCNT: 09653 if (iaxs[fr->callno]->transferring) 09654 send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); 09655 break; 09656 case IAX_COMMAND_TXREL: 09657 /* Send ack immediately, rather than waiting until we've changed addresses */ 09658 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09659 complete_transfer(fr->callno, &ies); 09660 stop_stuff(fr->callno); /* for attended transfer to work with libiax */ 09661 break; 09662 case IAX_COMMAND_TXMEDIA: 09663 if (iaxs[fr->callno]->transferring == TRANSFER_READY) { 09664 AST_LIST_LOCK(&frame_queue); 09665 AST_LIST_TRAVERSE(&frame_queue, cur, list) { 09666 /* Cancel any outstanding frames and start anew */ 09667 if ((fr->callno == cur->callno) && (cur->transfer)) 09668 cur->retries = -1; 09669 } 09670 AST_LIST_UNLOCK(&frame_queue); 09671 /* Start sending our media to the transfer address, but otherwise leave the call as-is */ 09672 iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS; 09673 } 09674 break; 09675 case IAX_COMMAND_DPREP: 09676 complete_dpreply(iaxs[fr->callno], &ies); 09677 break; 09678 case IAX_COMMAND_UNSUPPORT: 09679 ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown); 09680 break; 09681 case IAX_COMMAND_FWDOWNL: 09682 /* Firmware download */ 09683 if (!ast_test_flag(&globalflags, IAX_ALLOWFWDOWNLOAD)) { 09684 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, NULL, 0, -1); 09685 break; 09686 } 09687 memset(&ied0, 0, sizeof(ied0)); 09688 res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc); 09689 if (res < 0) 09690 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 09691 else if (res > 0) 09692 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 09693 else 09694 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 09695 if (!iaxs[fr->callno]) { 09696 ast_mutex_unlock(&iaxsl[fr->callno]); 09697 return 1; 09698 } 09699 break; 09700 default: 09701 ast_debug(1, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno); 09702 memset(&ied0, 0, sizeof(ied0)); 09703 iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass); 09704 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1); 09705 } 09706 /* Free remote variables (if any) */ 09707 if (ies.vars) { 09708 ast_variables_destroy(ies.vars); 09709 ast_debug(1, "I can haz IAX vars, but they is no good :-(\n"); 09710 ies.vars = NULL; 09711 } 09712 09713 /* Don't actually pass these frames along */ 09714 if ((f.subclass != IAX_COMMAND_ACK) && 09715 (f.subclass != IAX_COMMAND_TXCNT) && 09716 (f.subclass != IAX_COMMAND_TXACC) && 09717 (f.subclass != IAX_COMMAND_INVAL) && 09718 (f.subclass != IAX_COMMAND_VNAK)) { 09719 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 09720 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09721 } 09722 ast_mutex_unlock(&iaxsl[fr->callno]); 09723 return 1; 09724 } 09725 /* Unless this is an ACK or INVAL frame, ack it */ 09726 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 09727 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 09728 } else if (minivid) { 09729 f.frametype = AST_FRAME_VIDEO; 09730 if (iaxs[fr->callno]->videoformat > 0) 09731 f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); 09732 else { 09733 ast_log(LOG_WARNING, "Received mini frame before first full video frame\n"); 09734 iax2_vnak(fr->callno); 09735 ast_mutex_unlock(&iaxsl[fr->callno]); 09736 return 1; 09737 } 09738 f.datalen = res - sizeof(*vh); 09739 if (f.datalen) 09740 f.data = thread->buf + sizeof(*vh); 09741 else 09742 f.data = NULL; 09743 #ifdef IAXTESTS 09744 if (test_resync) { 09745 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff); 09746 } else 09747 #endif /* IAXTESTS */ 09748 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff); 09749 } else { 09750 /* A mini frame */ 09751 f.frametype = AST_FRAME_VOICE; 09752 if (iaxs[fr->callno]->voiceformat > 0) 09753 f.subclass = iaxs[fr->callno]->voiceformat; 09754 else { 09755 ast_debug(1, "Received mini frame before first full voice frame\n"); 09756 iax2_vnak(fr->callno); 09757 ast_mutex_unlock(&iaxsl[fr->callno]); 09758 return 1; 09759 } 09760 f.datalen = res - sizeof(struct ast_iax2_mini_hdr); 09761 if (f.datalen < 0) { 09762 ast_log(LOG_WARNING, "Datalen < 0?\n"); 09763 ast_mutex_unlock(&iaxsl[fr->callno]); 09764 return 1; 09765 } 09766 if (f.datalen) 09767 f.data = thread->buf + sizeof(*mh); 09768 else 09769 f.data = NULL; 09770 #ifdef IAXTESTS 09771 if (test_resync) { 09772 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff); 09773 } else 09774 #endif /* IAXTESTS */ 09775 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts); 09776 /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */ 09777 } 09778 /* Don't pass any packets until we're started */ 09779 if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 09780 ast_mutex_unlock(&iaxsl[fr->callno]); 09781 return 1; 09782 } 09783 /* Common things */ 09784 f.src = "IAX2"; 09785 f.mallocd = 0; 09786 f.offset = 0; 09787 f.len = 0; 09788 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { 09789 f.samples = ast_codec_get_samples(&f); 09790 /* We need to byteswap incoming slinear samples from network byte order */ 09791 if (f.subclass == AST_FORMAT_SLINEAR) 09792 ast_frame_byteswap_be(&f); 09793 } else 09794 f.samples = 0; 09795 iax_frame_wrap(fr, &f); 09796 09797 /* If this is our most recent packet, use it as our basis for timestamping */ 09798 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 09799 /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/ 09800 fr->outoforder = 0; 09801 } else { 09802 if (iaxdebug && iaxs[fr->callno]) 09803 ast_debug(1, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr->ts, iaxs[fr->callno]->last); 09804 fr->outoforder = -1; 09805 } 09806 fr->cacheable = ((f.frametype == AST_FRAME_VOICE) || (f.frametype == AST_FRAME_VIDEO)); 09807 duped_fr = iaxfrdup2(fr); 09808 if (duped_fr) { 09809 schedule_delivery(duped_fr, updatehistory, 0, &fr->ts); 09810 } 09811 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 09812 iaxs[fr->callno]->last = fr->ts; 09813 #if 1 09814 if (iaxdebug) 09815 ast_debug(1, "For call=%d, set last=%d\n", fr->callno, fr->ts); 09816 #endif 09817 } 09818 09819 /* Always run again */ 09820 ast_mutex_unlock(&iaxsl[fr->callno]); 09821 return 1; 09822 }
static int socket_process_meta | ( | int | packet_len, | |
struct ast_iax2_meta_hdr * | meta, | |||
struct sockaddr_in * | sin, | |||
int | sockfd, | |||
struct iax_frame * | fr | |||
) | [static] |
Definition at line 8039 of file chan_iax2.c.
References ast_codec_get_samples(), AST_FRAME_VOICE, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_test_flag, ast_tvnow(), ast_tvzero(), iax_frame::callno, ast_iax2_mini_hdr::callno, f, find_callno_locked(), find_tpeer(), fix_peerts(), iax2_vnak(), IAX_FLAG_FULL, iax_frame_wrap(), IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_STATE_STARTED, iaxfrdup2(), ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_WARNING, ast_iax2_meta_trunk_mini::mini, NEW_PREVENT, iax_frame::outoforder, iax2_trunk_peer::rxtrunktime, schedule_delivery(), iax2_trunk_peer::trunkact, iax_frame::ts, and ast_iax2_mini_hdr::ts.
Referenced by socket_process().
08041 { 08042 unsigned char metatype; 08043 struct ast_iax2_meta_trunk_mini *mtm; 08044 struct ast_iax2_meta_trunk_hdr *mth; 08045 struct ast_iax2_meta_trunk_entry *mte; 08046 struct iax2_trunk_peer *tpeer; 08047 unsigned int ts; 08048 void *ptr; 08049 struct timeval rxtrunktime; 08050 struct ast_frame f = { 0, }; 08051 08052 if (packet_len < sizeof(*meta)) { 08053 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", 08054 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 08055 return 1; 08056 } 08057 08058 if (meta->metacmd != IAX_META_TRUNK) 08059 return 1; 08060 08061 if (packet_len < (sizeof(*meta) + sizeof(*mth))) { 08062 ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %d min)\n", packet_len, 08063 (int) (sizeof(*meta) + sizeof(*mth))); 08064 return 1; 08065 } 08066 mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data); 08067 ts = ntohl(mth->ts); 08068 metatype = meta->cmddata; 08069 packet_len -= (sizeof(*meta) + sizeof(*mth)); 08070 ptr = mth->data; 08071 tpeer = find_tpeer(sin, sockfd); 08072 if (!tpeer) { 08073 ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", 08074 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 08075 return 1; 08076 } 08077 tpeer->trunkact = ast_tvnow(); 08078 if (!ts || ast_tvzero(tpeer->rxtrunktime)) 08079 tpeer->rxtrunktime = tpeer->trunkact; 08080 rxtrunktime = tpeer->rxtrunktime; 08081 ast_mutex_unlock(&tpeer->lock); 08082 while (packet_len >= sizeof(*mte)) { 08083 /* Process channels */ 08084 unsigned short callno, trunked_ts, len; 08085 08086 if (metatype == IAX_META_TRUNK_MINI) { 08087 mtm = (struct ast_iax2_meta_trunk_mini *) ptr; 08088 ptr += sizeof(*mtm); 08089 packet_len -= sizeof(*mtm); 08090 len = ntohs(mtm->len); 08091 callno = ntohs(mtm->mini.callno); 08092 trunked_ts = ntohs(mtm->mini.ts); 08093 } else if (metatype == IAX_META_TRUNK_SUPERMINI) { 08094 mte = (struct ast_iax2_meta_trunk_entry *)ptr; 08095 ptr += sizeof(*mte); 08096 packet_len -= sizeof(*mte); 08097 len = ntohs(mte->len); 08098 callno = ntohs(mte->callno); 08099 trunked_ts = 0; 08100 } else { 08101 ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 08102 break; 08103 } 08104 /* Stop if we don't have enough data */ 08105 if (len > packet_len) 08106 break; 08107 fr->callno = find_callno_locked(callno & ~IAX_FLAG_FULL, 0, sin, NEW_PREVENT, sockfd, 0); 08108 if (!fr->callno) 08109 continue; 08110 08111 /* If it's a valid call, deliver the contents. If not, we 08112 drop it, since we don't have a scallno to use for an INVAL */ 08113 /* Process as a mini frame */ 08114 memset(&f, 0, sizeof(f)); 08115 f.frametype = AST_FRAME_VOICE; 08116 if (!iaxs[fr->callno]) { 08117 /* drop it */ 08118 } else if (iaxs[fr->callno]->voiceformat == 0) { 08119 ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n"); 08120 iax2_vnak(fr->callno); 08121 } else { 08122 f.subclass = iaxs[fr->callno]->voiceformat; 08123 f.datalen = len; 08124 if (f.datalen >= 0) { 08125 if (f.datalen) 08126 f.data = ptr; 08127 else 08128 f.data = NULL; 08129 if (trunked_ts) 08130 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff); 08131 else 08132 fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts); 08133 /* Don't pass any packets until we're started */ 08134 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 08135 struct iax_frame *duped_fr; 08136 08137 /* Common things */ 08138 f.src = "IAX2"; 08139 f.mallocd = 0; 08140 f.offset = 0; 08141 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 08142 f.samples = ast_codec_get_samples(&f); 08143 else 08144 f.samples = 0; 08145 fr->outoforder = 0; 08146 iax_frame_wrap(fr, &f); 08147 duped_fr = iaxfrdup2(fr); 08148 if (duped_fr) 08149 schedule_delivery(duped_fr, 1, 1, &fr->ts); 08150 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) 08151 iaxs[fr->callno]->last = fr->ts; 08152 } 08153 } else { 08154 ast_log(LOG_WARNING, "Datalen < 0?\n"); 08155 } 08156 } 08157 ast_mutex_unlock(&iaxsl[fr->callno]); 08158 ptr += len; 08159 packet_len -= len; 08160 } 08161 08162 return 1; 08163 }
static int socket_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 7961 of file chan_iax2.c.
References ast_copy_string(), ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), iax2_thread::callno, ast_iax2_full_hdr::csub, defer_full_frame(), errno, iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), iax2_thread::list, LOG_WARNING, ast_iax2_full_hdr::scallno, signal_condition(), iax2_thread::sin, thread, and ast_iax2_full_hdr::type.
Referenced by network_thread(), peer_set_srcaddr(), and set_config().
07962 { 07963 struct iax2_thread *thread; 07964 socklen_t len; 07965 time_t t; 07966 static time_t last_errtime = 0; 07967 struct ast_iax2_full_hdr *fh; 07968 07969 if (!(thread = find_idle_thread())) { 07970 time(&t); 07971 if (t != last_errtime) 07972 ast_debug(1, "Out of idle IAX2 threads for I/O, pausing!\n"); 07973 last_errtime = t; 07974 usleep(1); 07975 return 1; 07976 } 07977 07978 len = sizeof(thread->iosin); 07979 thread->iofd = fd; 07980 thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len); 07981 thread->buf_size = sizeof(thread->readbuf); 07982 thread->buf = thread->readbuf; 07983 if (thread->buf_len < 0) { 07984 if (errno != ECONNREFUSED && errno != EAGAIN) 07985 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 07986 handle_error(); 07987 thread->iostate = IAX_IOSTATE_IDLE; 07988 signal_condition(&thread->lock, &thread->cond); 07989 return 1; 07990 } 07991 if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */ 07992 thread->iostate = IAX_IOSTATE_IDLE; 07993 signal_condition(&thread->lock, &thread->cond); 07994 return 1; 07995 } 07996 07997 /* Determine if this frame is a full frame; if so, and any thread is currently 07998 processing a full frame for the same callno from this peer, then drop this 07999 frame (and the peer will retransmit it) */ 08000 fh = (struct ast_iax2_full_hdr *) thread->buf; 08001 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 08002 struct iax2_thread *cur = NULL; 08003 uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL; 08004 08005 AST_LIST_LOCK(&active_list); 08006 AST_LIST_TRAVERSE(&active_list, cur, list) { 08007 if ((cur->ffinfo.callno == callno) && 08008 !inaddrcmp(&cur->ffinfo.sin, &thread->iosin)) 08009 break; 08010 } 08011 if (cur) { 08012 /* we found another thread processing a full frame for this call, 08013 so queue it up for processing later. */ 08014 defer_full_frame(thread, cur); 08015 AST_LIST_UNLOCK(&active_list); 08016 thread->iostate = IAX_IOSTATE_IDLE; 08017 signal_condition(&thread->lock, &thread->cond); 08018 return 1; 08019 } else { 08020 /* this thread is going to process this frame, so mark it */ 08021 thread->ffinfo.callno = callno; 08022 memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin)); 08023 thread->ffinfo.type = fh->type; 08024 thread->ffinfo.csub = fh->csub; 08025 } 08026 AST_LIST_UNLOCK(&active_list); 08027 } 08028 08029 /* Mark as ready and send on its way */ 08030 thread->iostate = IAX_IOSTATE_READY; 08031 #ifdef DEBUG_SCHED_MULTITHREAD 08032 ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc)); 08033 #endif 08034 signal_condition(&thread->lock, &thread->cond); 08035 08036 return 1; 08037 }
static void spawn_dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid | |||
) | [static] |
Definition at line 7677 of file chan_iax2.c.
References ast_calloc, ast_copy_string(), ast_log(), ast_pthread_create_detached, ast_strdup, dp_lookup_thread(), and LOG_WARNING.
Referenced by socket_process().
07678 { 07679 pthread_t newthread; 07680 struct dpreq_data *dpr; 07681 07682 if (!(dpr = ast_calloc(1, sizeof(*dpr)))) 07683 return; 07684 07685 dpr->callno = callno; 07686 ast_copy_string(dpr->context, context, sizeof(dpr->context)); 07687 ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum)); 07688 if (callerid) 07689 dpr->callerid = ast_strdup(callerid); 07690 if (ast_pthread_create_detached(&newthread, NULL, dp_lookup_thread, dpr)) { 07691 ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); 07692 } 07693 }
static int start_network_thread | ( | void | ) | [static] |
Definition at line 10427 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create_detached, iax2_process_thread(), IAX_THREAD_TYPE_POOL, iaxthreadcount, iax2_thread::list, LOG_WARNING, and thread.
Referenced by load_module().
10428 { 10429 struct iax2_thread *thread; 10430 int threadcount = 0; 10431 int x; 10432 for (x = 0; x < iaxthreadcount; x++) { 10433 thread = ast_calloc(1, sizeof(*thread)); 10434 if (thread) { 10435 thread->type = IAX_THREAD_TYPE_POOL; 10436 thread->threadnum = ++threadcount; 10437 ast_mutex_init(&thread->lock); 10438 ast_cond_init(&thread->cond, NULL); 10439 if (ast_pthread_create_detached(&thread->threadid, NULL, iax2_process_thread, thread)) { 10440 ast_log(LOG_WARNING, "Failed to create new thread!\n"); 10441 ast_free(thread); 10442 thread = NULL; 10443 } 10444 AST_LIST_LOCK(&idle_list); 10445 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 10446 AST_LIST_UNLOCK(&idle_list); 10447 } 10448 } 10449 ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL); 10450 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 10451 ast_verb(2, "%d helper threads started\n", threadcount); 10452 return 0; 10453 }
static void stop_stuff | ( | int | callno | ) | [static] |
Definition at line 7365 of file chan_iax2.c.
References iax2_destroy_helper().
Referenced by socket_process().
07366 { 07367 iax2_destroy_helper(iaxs[callno]); 07368 }
static void store_by_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1662 of file chan_iax2.c.
References ao2_link(), ast_log(), iax_peercallno_pvts, LOG_ERROR, and chan_iax2_pvt::peercallno.
Referenced by __find_callno(), complete_transfer(), and socket_process().
01663 { 01664 if (!pvt->peercallno) { 01665 ast_log(LOG_ERROR, "This should not be called without a peer call number.\n"); 01666 return; 01667 } 01668 01669 ao2_link(iax_peercallno_pvts, pvt); 01670 }
static void store_by_transfercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1643 of file chan_iax2.c.
References ao2_link(), ast_log(), iax_transfercallno_pvts, LOG_ERROR, and chan_iax2_pvt::transfercallno.
Referenced by try_transfer().
01644 { 01645 if (!pvt->transfercallno) { 01646 ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n"); 01647 return; 01648 } 01649 01650 ao2_link(iax_transfercallno_pvts, pvt); 01651 }
static int timing_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 7551 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_debug, ast_free, ast_inet_ntoa(), AST_IO_PRI, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_tvnow(), ast_verbose(), iax2_trunk_expired(), iax2_trunk_peer::lock, LOG_WARNING, send_trunk(), totalcalls, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.
Referenced by network_thread().
07552 { 07553 char buf[1024]; 07554 int res, processed = 0, totalcalls = 0; 07555 struct iax2_trunk_peer *tpeer = NULL, *drop = NULL; 07556 #ifdef DAHDI_TIMERACK 07557 int x = 1; 07558 #endif 07559 struct timeval now = ast_tvnow(); 07560 if (iaxtrunkdebug) 07561 ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", trunkmaxsize); 07562 if (events & AST_IO_PRI) { 07563 #ifdef DAHDI_TIMERACK 07564 /* Great, this is a timing interface, just call the ioctl */ 07565 if (ioctl(fd, DAHDI_TIMERACK, &x)) { 07566 ast_log(LOG_WARNING, "Unable to acknowledge DAHDI timer. IAX trunking will fail!\n"); 07567 usleep(1); 07568 return -1; 07569 } 07570 #endif 07571 } else { 07572 /* Read and ignore from the pseudo channel for timing */ 07573 res = read(fd, buf, sizeof(buf)); 07574 if (res < 1) { 07575 ast_log(LOG_WARNING, "Unable to read from timing fd\n"); 07576 return 1; 07577 } 07578 } 07579 /* For each peer that supports trunking... */ 07580 AST_LIST_LOCK(&tpeers); 07581 AST_LIST_TRAVERSE_SAFE_BEGIN(&tpeers, tpeer, list) { 07582 processed++; 07583 res = 0; 07584 ast_mutex_lock(&tpeer->lock); 07585 /* We can drop a single tpeer per pass. That makes all this logic 07586 substantially easier */ 07587 if (!drop && iax2_trunk_expired(tpeer, &now)) { 07588 /* Take it out of the list, but don't free it yet, because it 07589 could be in use */ 07590 AST_LIST_REMOVE_CURRENT(list); 07591 drop = tpeer; 07592 } else { 07593 res = send_trunk(tpeer, &now); 07594 trunk_timed++; 07595 if (iaxtrunkdebug) 07596 ast_verbose(" - Trunk peer (%s:%d) has %d call chunk%s in transit, %d bytes backloged and has hit a high water mark of %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), res, (res != 1) ? "s" : "", tpeer->trunkdatalen, tpeer->trunkdataalloc); 07597 } 07598 totalcalls += res; 07599 res = 0; 07600 ast_mutex_unlock(&tpeer->lock); 07601 } 07602 AST_LIST_TRAVERSE_SAFE_END; 07603 AST_LIST_UNLOCK(&tpeers); 07604 07605 if (drop) { 07606 ast_mutex_lock(&drop->lock); 07607 /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 07608 because by the time they could get tpeerlock, we've already grabbed it */ 07609 ast_debug(1, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); 07610 if (drop->trunkdata) { 07611 ast_free(drop->trunkdata); 07612 drop->trunkdata = NULL; 07613 } 07614 ast_mutex_unlock(&drop->lock); 07615 ast_mutex_destroy(&drop->lock); 07616 ast_free(drop); 07617 07618 } 07619 07620 if (iaxtrunkdebug) 07621 ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls); 07622 iaxtrunkdebug = 0; 07623 07624 return 1; 07625 }
static int transfercallno_pvt_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 12387 of file chan_iax2.c.
References CMP_MATCH, CMP_STOP, chan_iax2_pvt::frames_received, and match().
Referenced by load_module().
12388 { 12389 struct chan_iax2_pvt *pvt = obj, *pvt2 = arg; 12390 12391 /* The frames_received field is used to hold whether we're matching 12392 * against a full frame or not ... */ 12393 12394 return match(&pvt2->transfer, pvt2->transfercallno, pvt2->callno, pvt, 12395 pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0; 12396 }
static int transfercallno_pvt_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 12380 of file chan_iax2.c.
References chan_iax2_pvt::transfercallno.
Referenced by load_module().
12381 { 12382 const struct chan_iax2_pvt *pvt = obj; 12383 12384 return pvt->transfercallno; 12385 }
static int transmit_trunk | ( | struct iax_frame * | f, | |
struct sockaddr_in * | sin, | |||
int | sockfd | |||
) | [static] |
Definition at line 2262 of file chan_iax2.c.
References ast_debug, errno, f, and handle_error().
Referenced by send_trunk().
02263 { 02264 int res; 02265 res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin, 02266 sizeof(*sin)); 02267 if (res < 0) { 02268 ast_debug(1, "Received error: %s\n", strerror(errno)); 02269 handle_error(); 02270 } else 02271 res = 0; 02272 return res; 02273 }
static int try_firmware | ( | char * | s | ) | [static] |
Definition at line 1964 of file chan_iax2.c.
References ast_calloc, AST_FILE_MODE, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_random(), ast_strlen_zero(), ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, errno, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, iax2_trunk_peer::list, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), and ast_iax2_firmware_header::version.
Referenced by reload_firmware().
01965 { 01966 struct stat stbuf; 01967 struct iax_firmware *cur = NULL; 01968 int ifd, fd, res, len, chunk; 01969 struct ast_iax2_firmware_header *fwh, fwh2; 01970 struct MD5Context md5; 01971 unsigned char sum[16], buf[1024]; 01972 char *s2, *last; 01973 01974 if (!(s2 = alloca(strlen(s) + 100))) { 01975 ast_log(LOG_WARNING, "Alloca failed!\n"); 01976 return -1; 01977 } 01978 01979 last = strrchr(s, '/'); 01980 if (last) 01981 last++; 01982 else 01983 last = s; 01984 01985 snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random()); 01986 01987 if ((res = stat(s, &stbuf) < 0)) { 01988 ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno)); 01989 return -1; 01990 } 01991 01992 /* Make sure it's not a directory */ 01993 if (S_ISDIR(stbuf.st_mode)) 01994 return -1; 01995 ifd = open(s, O_RDONLY); 01996 if (ifd < 0) { 01997 ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); 01998 return -1; 01999 } 02000 fd = open(s2, O_RDWR | O_CREAT | O_EXCL, AST_FILE_MODE); 02001 if (fd < 0) { 02002 ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); 02003 close(ifd); 02004 return -1; 02005 } 02006 /* Unlink our newly created file */ 02007 unlink(s2); 02008 02009 /* Now copy the firmware into it */ 02010 len = stbuf.st_size; 02011 while(len) { 02012 chunk = len; 02013 if (chunk > sizeof(buf)) 02014 chunk = sizeof(buf); 02015 res = read(ifd, buf, chunk); 02016 if (res != chunk) { 02017 ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 02018 close(ifd); 02019 close(fd); 02020 return -1; 02021 } 02022 res = write(fd, buf, chunk); 02023 if (res != chunk) { 02024 ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 02025 close(ifd); 02026 close(fd); 02027 return -1; 02028 } 02029 len -= chunk; 02030 } 02031 close(ifd); 02032 /* Return to the beginning */ 02033 lseek(fd, 0, SEEK_SET); 02034 if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) { 02035 ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s); 02036 close(fd); 02037 return -1; 02038 } 02039 if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) { 02040 ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s); 02041 close(fd); 02042 return -1; 02043 } 02044 if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) { 02045 ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s); 02046 close(fd); 02047 return -1; 02048 } 02049 if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) { 02050 ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s); 02051 close(fd); 02052 return -1; 02053 } 02054 fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 02055 if (fwh == MAP_FAILED) { 02056 ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno)); 02057 close(fd); 02058 return -1; 02059 } 02060 MD5Init(&md5); 02061 MD5Update(&md5, fwh->data, ntohl(fwh->datalen)); 02062 MD5Final(sum, &md5); 02063 if (memcmp(sum, fwh->chksum, sizeof(sum))) { 02064 ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s); 02065 munmap((void*)fwh, stbuf.st_size); 02066 close(fd); 02067 return -1; 02068 } 02069 02070 AST_LIST_TRAVERSE(&firmwares, cur, list) { 02071 if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) { 02072 /* Found a candidate */ 02073 if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version))) 02074 /* The version we have on loaded is older, load this one instead */ 02075 break; 02076 /* This version is no newer than what we have. Don't worry about it. 02077 We'll consider it a proper load anyhow though */ 02078 munmap((void*)fwh, stbuf.st_size); 02079 close(fd); 02080 return 0; 02081 } 02082 } 02083 02084 if (!cur && ((cur = ast_calloc(1, sizeof(*cur))))) { 02085 cur->fd = -1; 02086 AST_LIST_INSERT_TAIL(&firmwares, cur, list); 02087 } 02088 02089 if (cur) { 02090 if (cur->fwh) 02091 munmap((void*)cur->fwh, cur->mmaplen); 02092 if (cur->fd > -1) 02093 close(cur->fd); 02094 cur->fwh = fwh; 02095 cur->fd = fd; 02096 cur->mmaplen = stbuf.st_size; 02097 cur->dead = 0; 02098 } 02099 02100 return 0; 02101 }
static int try_transfer | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 6733 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, ies, inet_aton(), LOG_WARNING, send_command_transfer(), store_by_transfercallno(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.
Referenced by socket_process().
06734 { 06735 int newcall = 0; 06736 char newip[256]; 06737 struct iax_ie_data ied; 06738 struct sockaddr_in new; 06739 06740 06741 memset(&ied, 0, sizeof(ied)); 06742 if (ies->apparent_addr) 06743 memmove(&new, ies->apparent_addr, sizeof(new)); 06744 if (ies->callno) 06745 newcall = ies->callno; 06746 if (!newcall || !new.sin_addr.s_addr || !new.sin_port) { 06747 ast_log(LOG_WARNING, "Invalid transfer request\n"); 06748 return -1; 06749 } 06750 pvt->transfercallno = newcall; 06751 memcpy(&pvt->transfer, &new, sizeof(pvt->transfer)); 06752 inet_aton(newip, &pvt->transfer.sin_addr); 06753 pvt->transfer.sin_family = AF_INET; 06754 pvt->transferring = TRANSFER_BEGIN; 06755 pvt->transferid = ies->transferid; 06756 store_by_transfercallno(pvt); 06757 if (ies->transferid) 06758 iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid); 06759 send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); 06760 return 0; 06761 }
static int uncompress_subclass | ( | unsigned char | csub | ) | [static] |
Definition at line 1263 of file chan_iax2.c.
References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.
Referenced by decode_frame(), and socket_process().
01264 { 01265 /* If the SC_LOG flag is set, return 2^csub otherwise csub */ 01266 if (csub & IAX_FLAG_SC_LOG) { 01267 /* special case for 'compressed' -1 */ 01268 if (csub == 0xff) 01269 return -1; 01270 else 01271 return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); 01272 } 01273 else 01274 return csub; 01275 }
static void unlink_peer | ( | struct iax2_peer * | peer | ) | [static] |
Definition at line 7013 of file chan_iax2.c.
References ao2_unlink(), ast_sched_del(), iax2_peer::expire, peer_unref(), iax2_peer::pokeexpire, and sched.
Referenced by __expire_registry(), build_peer(), and prune_peers().
07014 { 07015 if (peer->expire > -1) { 07016 if (!ast_sched_del(sched, peer->expire)) { 07017 peer->expire = -1; 07018 peer_unref(peer); 07019 } 07020 } 07021 07022 if (peer->pokeexpire > -1) { 07023 if (!ast_sched_del(sched, peer->pokeexpire)) { 07024 peer->pokeexpire = -1; 07025 peer_unref(peer); 07026 } 07027 } 07028 07029 ao2_unlink(peers, peer); 07030 }
static int unload_module | ( | void | ) | [static] |
Definition at line 12345 of file chan_iax2.c.
References __unload_module(), ast_custom_function_unregister(), iaxpeer_function, and iaxvar_function.
12346 { 12347 ast_custom_function_unregister(&iaxpeer_function); 12348 ast_custom_function_unregister(&iaxvar_function); 12349 return __unload_module(); 12350 }
static void unlock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3983 of file chan_iax2.c.
References ast_mutex_unlock().
Referenced by iax2_bridge().
03984 { 03985 ast_mutex_unlock(&iaxsl[callno1]); 03986 ast_mutex_unlock(&iaxsl[callno0]); 03987 }
static void unwrap_timestamp | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2928 of file chan_iax2.c.
References iax_frame::af, ast_debug, AST_FRAME_VIDEO, iax_frame::callno, ast_frame::frametype, and iax_frame::ts.
Referenced by schedule_delivery().
02929 { 02930 /* Video mini frames only encode the lower 15 bits of the session 02931 * timestamp, but other frame types (e.g. audio) encode 16 bits. */ 02932 const int ts_shift = (fr->af.frametype == AST_FRAME_VIDEO) ? 15 : 16; 02933 const int lower_mask = (1 << ts_shift) - 1; 02934 const int upper_mask = ~lower_mask; 02935 const int last_upper = iaxs[fr->callno]->last & upper_mask; 02936 02937 if ( (fr->ts & upper_mask) == last_upper ) { 02938 const int x = fr->ts - iaxs[fr->callno]->last; 02939 const int threshold = (ts_shift == 15) ? 25000 : 50000; 02940 02941 if (x < -threshold) { 02942 /* Sudden big jump backwards in timestamp: 02943 What likely happened here is that miniframe timestamp has circled but we haven't 02944 gotten the update from the main packet. We'll just pretend that we did, and 02945 update the timestamp appropriately. */ 02946 fr->ts = (last_upper + (1 << ts_shift)) | (fr->ts & lower_mask); 02947 if (iaxdebug) 02948 ast_debug(1, "schedule_delivery: pushed forward timestamp\n"); 02949 } else if (x > threshold) { 02950 /* Sudden apparent big jump forwards in timestamp: 02951 What's likely happened is this is an old miniframe belonging to the previous 02952 top 15 or 16-bit timestamp that has turned up out of order. 02953 Adjust the timestamp appropriately. */ 02954 fr->ts = (last_upper - (1 << ts_shift)) | (fr->ts & lower_mask); 02955 if (iaxdebug) 02956 ast_debug(1, "schedule_delivery: pushed back timestamp\n"); 02957 } 02958 } 02959 }
static void update_jbsched | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 2963 of file chan_iax2.c.
References ast_tvdiff_ms(), ast_tvnow(), chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), iax2_sched_replace(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, chan_iax2_pvt::rxcore, and sched.
Referenced by __get_from_jb(), and schedule_delivery().
02964 { 02965 int when; 02966 02967 when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore); 02968 02969 when = jb_next(pvt->jb) - when; 02970 02971 if (when <= 0) { 02972 /* XXX should really just empty until when > 0.. */ 02973 when = 1; 02974 } 02975 02976 pvt->jbid = iax2_sched_replace(pvt->jbid, sched, when, get_from_jb, 02977 CALLNO_TO_PTR(pvt->callno)); 02978 }
static void update_max_nontrunk | ( | void | ) | [static] |
Definition at line 1579 of file chan_iax2.c.
References ast_debug, and TRUNK_CALL_START.
Referenced by __find_callno(), and make_trunk().
01580 { 01581 int max = 1; 01582 int x; 01583 /* XXX Prolly don't need locks here XXX */ 01584 for (x=1;x<TRUNK_CALL_START - 1; x++) { 01585 if (iaxs[x]) 01586 max = x + 1; 01587 } 01588 maxnontrunkcall = max; 01589 if (iaxdebug) 01590 ast_debug(1, "New max nontrunk callno is %d\n", max); 01591 }
static void update_max_trunk | ( | void | ) | [static] |
Definition at line 1562 of file chan_iax2.c.
References ARRAY_LEN, ast_debug, and TRUNK_CALL_START.
Referenced by iax2_destroy(), and make_trunk().
01563 { 01564 int max = TRUNK_CALL_START; 01565 int x; 01566 01567 /* XXX Prolly don't need locks here XXX */ 01568 for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) { 01569 if (iaxs[x]) { 01570 max = x + 1; 01571 } 01572 } 01573 01574 maxtrunkcall = max; 01575 if (iaxdebug) 01576 ast_debug(1, "New max trunk callno is %d\n", max); 01577 }
static int update_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 2392 of file chan_iax2.c.
References build_rand_pad(), ast_iax2_full_hdr::dcallno, decode_frame(), encrypt_frame(), f, IAX_FLAG_RETRANS, and ast_iax2_full_hdr::iseqno.
Referenced by __attempt_transmit().
02393 { 02394 /* Called with iaxsl lock held, and iaxs[callno] non-NULL */ 02395 struct ast_iax2_full_hdr *fh = f->data; 02396 struct ast_frame af; 02397 02398 /* if frame is encrypted. decrypt before updating it. */ 02399 if (f->encmethods) { 02400 decode_frame(&f->mydcx, fh, &af, &f->datalen); 02401 } 02402 /* Mark this as a retransmission */ 02403 fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno); 02404 /* Update iseqno */ 02405 f->iseqno = iaxs[f->callno]->iseqno; 02406 fh->iseqno = f->iseqno; 02407 02408 /* Now re-encrypt the frame */ 02409 if (f->encmethods) { 02410 /* since this is a retransmit frame, create a new random padding 02411 * before re-encrypting. */ 02412 build_rand_pad(f->semirand, sizeof(f->semirand)); 02413 encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen); 02414 } 02415 return 0; 02416 }
static int update_registry | ( | struct sockaddr_in * | sin, | |
int | callno, | |||
char * | devtype, | |||
int | fd, | |||
unsigned short | refresh | |||
) | [static] |
Definition at line 7122 of file chan_iax2.c.
References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), ast_device_state_changed(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verb, iax2_peer::cid_name, iax2_peer::cid_num, EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), globalflags, iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax2_sched_add(), iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, inaddrcmp(), LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mailbox, manager_event, iax2_peer::name, peer_ref(), peer_unref(), realtime_update_peer(), register_peer_exten(), sched, send_command_final(), iax2_peer::sockfd, strsep(), version, and iax2_peer::zonetag.
Referenced by socket_process().
07123 { 07124 /* Called from IAX thread only, with proper iaxsl lock */ 07125 struct iax_ie_data ied; 07126 struct iax2_peer *p; 07127 int msgcount; 07128 char data[80]; 07129 int version; 07130 const char *peer_name; 07131 int res = -1; 07132 07133 memset(&ied, 0, sizeof(ied)); 07134 07135 peer_name = ast_strdupa(iaxs[callno]->peer); 07136 07137 /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ 07138 ast_mutex_unlock(&iaxsl[callno]); 07139 if (!(p = find_peer(peer_name, 1))) { 07140 ast_mutex_lock(&iaxsl[callno]); 07141 ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); 07142 return -1; 07143 } 07144 ast_mutex_lock(&iaxsl[callno]); 07145 if (!iaxs[callno]) 07146 goto return_unref; 07147 07148 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { 07149 if (sin->sin_addr.s_addr) { 07150 time_t nowtime; 07151 time(&nowtime); 07152 realtime_update_peer(peer_name, sin, nowtime); 07153 } else { 07154 realtime_update_peer(peer_name, sin, 0); 07155 } 07156 } 07157 if (inaddrcmp(&p->addr, sin)) { 07158 if (iax2_regfunk) 07159 iax2_regfunk(p->name, 1); 07160 /* Stash the IP address from which they registered */ 07161 memcpy(&p->addr, sin, sizeof(p->addr)); 07162 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry); 07163 if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) { 07164 ast_db_put("IAX/Registry", p->name, data); 07165 ast_verb(3, "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 07166 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 07167 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name); 07168 register_peer_exten(p, 1); 07169 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 07170 } else if (!ast_test_flag(p, IAX_TEMPONLY)) { 07171 ast_verb(3, "Unregistered IAX2 '%s' (%s)\n", p->name, 07172 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED"); 07173 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name); 07174 register_peer_exten(p, 0); 07175 ast_db_del("IAX/Registry", p->name); 07176 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 07177 } 07178 /* Update the host */ 07179 /* Verify that the host is really there */ 07180 iax2_poke_peer(p, callno); 07181 } 07182 07183 /* Make sure our call still exists, an INVAL at the right point may make it go away */ 07184 if (!iaxs[callno]) { 07185 res = -1; 07186 goto return_unref; 07187 } 07188 07189 /* Store socket fd */ 07190 p->sockfd = fd; 07191 /* Setup the expiry */ 07192 if (p->expire > -1) { 07193 if (!ast_sched_del(sched, p->expire)) { 07194 p->expire = -1; 07195 peer_unref(p); 07196 } 07197 } 07198 /* treat an unspecified refresh interval as the minimum */ 07199 if (!refresh) 07200 refresh = min_reg_expire; 07201 if (refresh > max_reg_expire) { 07202 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 07203 p->name, max_reg_expire, refresh); 07204 p->expiry = max_reg_expire; 07205 } else if (refresh < min_reg_expire) { 07206 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 07207 p->name, min_reg_expire, refresh); 07208 p->expiry = min_reg_expire; 07209 } else { 07210 p->expiry = refresh; 07211 } 07212 if (p->expiry && sin->sin_addr.s_addr) { 07213 p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); 07214 if (p->expire == -1) 07215 peer_unref(p); 07216 } 07217 iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); 07218 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); 07219 if (sin->sin_addr.s_addr) { 07220 iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); 07221 iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); 07222 if (!ast_strlen_zero(p->mailbox)) { 07223 struct ast_event *event; 07224 int new, old; 07225 char *mailbox, *context; 07226 07227 context = mailbox = ast_strdupa(p->mailbox); 07228 strsep(&context, "@"); 07229 if (ast_strlen_zero(context)) 07230 context = "default"; 07231 07232 event = ast_event_get_cached(AST_EVENT_MWI, 07233 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 07234 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 07235 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 07236 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 07237 AST_EVENT_IE_END); 07238 if (event) { 07239 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 07240 old = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 07241 ast_event_destroy(event); 07242 } else /* Fall back on checking the mailbox directly */ 07243 ast_app_inboxcount(p->mailbox, &new, &old); 07244 07245 if (new > 255) 07246 new = 255; 07247 if (old > 255) 07248 old = 255; 07249 msgcount = (old << 8) | new; 07250 07251 iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount); 07252 } 07253 if (ast_test_flag(p, IAX_HASCALLERID)) { 07254 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num); 07255 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name); 07256 } 07257 } 07258 version = iax_check_version(devtype); 07259 if (version) 07260 iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version); 07261 07262 res = 0; 07263 07264 return_unref: 07265 peer_unref(p); 07266 07267 return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1); 07268 }
static int user_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1310 of file chan_iax2.c.
References CMP_MATCH, and user.
Referenced by load_module().
01311 { 01312 struct iax2_user *user = obj, *user2 = arg; 01313 01314 return !strcmp(user->name, user2->name) ? CMP_MATCH : 0; 01315 }
static int user_delme_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 11068 of file chan_iax2.c.
References ast_set_flag, IAX_DELME, and user.
Referenced by delete_users().
11069 { 11070 struct iax2_user *user = obj; 11071 11072 ast_set_flag(user, IAX_DELME); 11073 11074 return 0; 11075 }
static void user_destructor | ( | void * | obj | ) | [static] |
Definition at line 10833 of file chan_iax2.c.
References ast_free_ha(), ast_string_field_free_memory, ast_variables_destroy(), free_context(), and user.
Referenced by build_user().
10834 { 10835 struct iax2_user *user = obj; 10836 10837 ast_free_ha(user->ha); 10838 free_context(user->contexts); 10839 if(user->vars) { 10840 ast_variables_destroy(user->vars); 10841 user->vars = NULL; 10842 } 10843 ast_string_field_free_memory(user); 10844 }
static int user_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1300 of file chan_iax2.c.
References ast_str_hash(), and user.
Referenced by load_module().
01301 { 01302 const struct iax2_user *user = obj; 01303 01304 return ast_str_hash(user->name); 01305 }
Definition at line 1363 of file chan_iax2.c.
References ao2_ref(), and user.
Referenced by authenticate_request(), authenticate_verify(), build_user(), check_access(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_users(), iax2_destroy_helper(), prune_users(), and set_config().
static void vnak_retransmit | ( | int | callno, | |
int | last | |||
) | [static] |
Definition at line 7466 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, f, iax_frame::list, and send_packet().
Referenced by socket_process().
07467 { 07468 struct iax_frame *f; 07469 07470 AST_LIST_LOCK(&frame_queue); 07471 AST_LIST_TRAVERSE(&frame_queue, f, list) { 07472 /* Send a copy immediately */ 07473 if ((f->callno == callno) && iaxs[f->callno] && 07474 ((unsigned char ) (f->oseqno - last) < 128) && 07475 (f->retries >= 0)) { 07476 send_packet(f); 07477 } 07478 } 07479 AST_LIST_UNLOCK(&frame_queue); 07480 }
static int wait_for_peercallno | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 3881 of file chan_iax2.c.
References chan_iax2_pvt::callno, DEADLOCK_AVOIDANCE, and chan_iax2_pvt::peercallno.
Referenced by iax2_indicate(), and iax2_setoption().
03882 { 03883 unsigned short callno = pvt->callno; 03884 03885 if (!pvt->peercallno) { 03886 /* We don't know the remote side's call number, yet. :( */ 03887 int count = 10; 03888 while (count-- && pvt && !pvt->peercallno) { 03889 DEADLOCK_AVOIDANCE(&iaxsl[callno]); 03890 pvt = iaxs[callno]; 03891 } 03892 if (!pvt->peercallno) { 03893 return -1; 03894 } 03895 } 03896 03897 return 0; 03898 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Inter Asterisk eXchange (Ver 2)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 12524 of file chan_iax2.c.
char accountcode[AST_MAX_ACCOUNT_CODE] [static] |
Definition at line 227 of file chan_iax2.c.
Referenced by __ast_channel_alloc_ap(), __oh323_new(), ast_call_forward(), ast_cdr_setaccount(), begin_dial_channel(), build_device(), build_gateway(), dahdi_new(), dial_exec_full(), do_forward(), features_call(), gtalk_new(), jingle_new(), local_call(), mgcp_new(), rpt_call(), skinny_new(), and tds_log().
int adsi = 0 [static] |
int amaflags = 0 [static] |
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 12524 of file chan_iax2.c.
int authdebug = 1 [static] |
Definition at line 161 of file chan_iax2.c.
int autokill = 0 [static] |
Definition at line 162 of file chan_iax2.c.
struct ast_cli_entry cli_iax2[] [static] |
struct ast_cli_entry cli_iax2_set_debug_deprecated = { .handler = handle_cli_iax2_set_debug_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } [static] |
Definition at line 12233 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_set_debug_jb_deprecated = { .handler = handle_cli_iax2_set_debug_jb_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } [static] |
Definition at line 12235 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_set_debug_trunk_deprecated = { .handler = handle_cli_iax2_set_debug_trunk_deprecated , .summary = "Enable/Disable IAX debugging" ,__VA_ARGS__ } [static] |
Definition at line 12234 of file chan_iax2.c.
char context[80] = "default" [static] |
Definition at line 142 of file chan_iax2.c.
unsigned int cos = 0 [static] |
Definition at line 172 of file chan_iax2.c.
int defaultsockfd = -1 [static] |
Definition at line 183 of file chan_iax2.c.
int delayreject = 0 [static] |
Definition at line 232 of file chan_iax2.c.
int global_max_trunk_mtu [static] |
Maximum MTU, 0 if not used
Definition at line 138 of file chan_iax2.c.
int global_rtautoclear = 120 [static] |
Definition at line 285 of file chan_iax2.c.
struct ast_flags globalflags = { 0 } [static] |
Definition at line 235 of file chan_iax2.c.
Referenced by __expire_registry(), __find_callno(), aji_create_client(), aji_load_config(), apply_general_options(), build_peer(), build_user(), find_or_create(), find_user(), find_user_realtime(), forward_message(), handle_minivm_show_settings(), iax2_request(), iax2_trunk_queue(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), send_trunk(), sendmail(), set_config(), set_config_destroy(), socket_process(), update_registry(), and vm_execmain().
int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static] |
Definition at line 213 of file chan_iax2.c.
int iax2_encryption = 0 [static] |
Definition at line 233 of file chan_iax2.c.
int(*) iax2_regfunk(const char *username, int onoff) = NULL |
Definition at line 185 of file chan_iax2.c.
Referenced by __expire_registry(), reg_source_db(), and update_registry().
struct ast_switch iax2_switch [static] |
struct ast_channel_tech iax2_tech [static] |
Definition at line 952 of file chan_iax2.c.
Referenced by __unload_module(), acf_channel_read(), acf_channel_write(), ast_iax2_new(), function_iaxpeer(), iax2_bridge(), iax2_prov_app(), and load_module().
struct ast_datastore_info iax2_variable_datastore_info [static] |
Initial value:
{ .type = "IAX2_VARIABLE", .duplicate = iax2_dup_variable_datastore, .destroy = iax2_free_variable_datastore, }
Definition at line 997 of file chan_iax2.c.
Referenced by acf_iaxvar_read(), acf_iaxvar_write(), ast_iax2_new(), authenticate_reply(), iax2_call(), and socket_process().
struct ao2_container* iax_peercallno_pvts [static] |
Another container of iax2_pvt structures.
Active IAX2 pvt structs are also stored in this container, if they are a part of an active call where we know the remote side's call number. The reason for this is that incoming media frames do not contain our call number. So, instead of having to iterate the entire iaxs array, we use this container to look up calls where the remote side is using a given call number.
Definition at line 863 of file chan_iax2.c.
Referenced by __find_callno(), __unload_module(), load_module(), remove_by_peercallno(), and store_by_peercallno().
struct ao2_container* iax_transfercallno_pvts [static] |
Another container of iax2_pvt structures.
*
Active IAX2 pvt stucts used during transfering a call are stored here.
Definition at line 900 of file chan_iax2.c.
Referenced by __find_callno(), __unload_module(), load_module(), remove_by_transfercallno(), and store_by_transfercallno().
int iaxactivethreadcount = 0 [static] |
Definition at line 464 of file chan_iax2.c.
Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().
int iaxcompat = 0 [static] |
Definition at line 163 of file chan_iax2.c.
int iaxdebug = 0 [static] |
Definition at line 215 of file chan_iax2.c.
int iaxdefaultdpcache = 10 * 60 [static] |
Definition at line 166 of file chan_iax2.c.
int iaxdefaulttimeout = 5 [static] |
Definition at line 168 of file chan_iax2.c.
int iaxdynamicthreadcount = 0 [static] |
Definition at line 462 of file chan_iax2.c.
Referenced by find_idle_thread(), and iax2_process_thread().
int iaxdynamicthreadnum = 0 [static] |
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 852 of file chan_iax2.c.
ast_mutex_t iaxsl[ARRAY_LEN(iaxs)] [static] |
chan_iax2_pvt structure locks
These locks are used when accessing a pvt structure in the iaxs array. The index used here is the same as used in the iaxs array. It is the local call number for the associated pvt struct.
Definition at line 872 of file chan_iax2.c.
int iaxthreadcount = DEFAULT_THREAD_COUNT [static] |
Definition at line 460 of file chan_iax2.c.
Referenced by handle_cli_iax2_show_threads(), set_config(), and start_network_thread().
int iaxtrunkdebug = 0 [static] |
Definition at line 217 of file chan_iax2.c.
struct ast_custom_function iaxvar_function [static] |
struct io_context* io [static] |
Definition at line 210 of file chan_iax2.c.
int jittertargetextra = 40 [static] |
Definition at line 154 of file chan_iax2.c.
int lagrq_time = 10 [static] |
Definition at line 150 of file chan_iax2.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 144 of file chan_iax2.c.
int last_authmethod = 0 [static] |
Definition at line 164 of file chan_iax2.c.
The last time a call number was used.
It is important to know the last time that a call number was used locally so that it is not used again too soon. The reason for this is the same as the reason that the TCP protocol state machine requires a "TIME WAIT" state.
For example, say that a call is up. Then, the remote side sends a HANGUP, which we respond to with an ACK. However, there is no way to know whether the ACK made it there successfully. If it were to get lost, the remote side may retransmit the HANGUP. If in the meantime, this call number has been reused locally, given the right set of circumstances, this retransmitted HANGUP could potentially improperly hang up the new session. So, to avoid this potential issue, we must wait a specified timeout period before reusing a local call number.
The specified time that we must wait before reusing a local call number is defined as MIN_REUSE_TIME, with a default of 60 seconds.
Definition at line 893 of file chan_iax2.c.
int max_reg_expire [static] |
Definition at line 175 of file chan_iax2.c.
int max_retries = 4 [static] |
Definition at line 148 of file chan_iax2.c.
int maxauthreq = 3 [static] |
Definition at line 147 of file chan_iax2.c.
int maxjitterbuffer = 1000 [static] |
Definition at line 151 of file chan_iax2.c.
int maxjitterinterps = 10 [static] |
Definition at line 153 of file chan_iax2.c.
int maxnontrunkcall = 1 [static] |
Definition at line 907 of file chan_iax2.c.
int maxtrunkcall = TRUNK_CALL_START [static] |
Definition at line 906 of file chan_iax2.c.
int min_reg_expire [static] |
Definition at line 174 of file chan_iax2.c.
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 228 of file chan_iax2.c.
char mohsuggest[MAX_MUSICCLASS] [static] |
struct ast_netsock_list* netsock [static] |
Definition at line 181 of file chan_iax2.c.
Referenced by __unload_module(), ast_netsock_destroy(), load_module(), peer_set_srcaddr(), and set_config().
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 237 of file chan_iax2.c.
struct ast_netsock_list* outsock [static] |
used if sourceaddress specified and bindaddr == INADDR_ANY
Definition at line 182 of file chan_iax2.c.
Referenced by __unload_module(), load_module(), peer_set_srcaddr(), and set_config().
char* papp = "IAX2Provision" [static] |
char* pdescrip [static] |
Initial value:
" IAX2Provision([template]): Provisions the calling IAXy (assuming\n" "the calling entity is in fact an IAXy) with the given template or\n" "default if one is not specified. Returns -1 on error or 0 on success.\n"
Definition at line 10063 of file chan_iax2.c.
Referenced by load_module().
struct ao2_container* peers [static] |
Definition at line 677 of file chan_iax2.c.
int ping_time = 21 [static] |
Definition at line 149 of file chan_iax2.c.
struct ast_codec_pref prefs [static] |
Definition at line 129 of file chan_iax2.c.
Referenced by ast_best_codec(), ast_rtp_codec_setpref(), build_peer(), build_user(), check_access(), create_addr(), gtalk_create_member(), gtalk_load_config(), jingle_create_member(), jingle_load_config(), new_iax(), set_config(), set_local_capabilities(), and set_peer_capabilities().
char* psyn = "Provision a calling IAXy with a given template" [static] |
char regcontext[AST_MAX_CONTEXT] = "" [static] |
Definition at line 145 of file chan_iax2.c.
Referenced by handle_skinny_show_settings(), register_exten(), reload_config(), and unregister_exten().
int resyncthreshold = 1000 [static] |
Definition at line 152 of file chan_iax2.c.
struct sched_context* sched [static] |
Definition at line 211 of file chan_iax2.c.
ast_cond_t sched_cond [static] |
Definition at line 240 of file chan_iax2.c.
ast_mutex_t sched_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 239 of file chan_iax2.c.
Referenced by __unload_module(), iax2_sched_add(), iax2_sched_replace(), iax2_transmit(), and sched_thread().
pthread_t schedthreadid = AST_PTHREADT_NULL [static] |
Definition at line 238 of file chan_iax2.c.
int srvlookup = 0 [static] |
const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static] |
Definition at line 131 of file chan_iax2.c.
int test_losspct = 0 [static] |
Definition at line 219 of file chan_iax2.c.
int timingfd = -1 [static] |
Definition at line 179 of file chan_iax2.c.
unsigned int tos = 0 [static] |
Definition at line 170 of file chan_iax2.c.
int trunk_maxmtu [static] |
Definition at line 139 of file chan_iax2.c.
int trunk_nmaxmtu [static] |
Trunk MTU statistics
Definition at line 139 of file chan_iax2.c.
int trunk_timed [static] |
Definition at line 139 of file chan_iax2.c.
int trunk_untimed [static] |
Definition at line 139 of file chan_iax2.c.
int trunkfreq = 20 [static] |
Definition at line 158 of file chan_iax2.c.
int trunkmaxsize = MAX_TRUNKDATA [static] |
Definition at line 159 of file chan_iax2.c.
struct ao2_container* users [static] |
Definition at line 680 of file chan_iax2.c.