#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/md5.h"
#include "asterisk/cdr.h"
#include "asterisk/crypto.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/app.h"
#include "asterisk/astdb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/localtime.h"
#include "asterisk/aes.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/netsock.h"
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
#include "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
#include "jitterbuf.h"
Go to the source code of this file.
Data Structures | |
struct | ast_firmware_list |
struct | ast_iax2_queue |
struct | chan_iax2_pvt |
struct | create_addr_info |
struct | dpreq_data |
struct | iax2_context |
struct | iax2_dpcache |
struct | iax2_peer |
struct | iax2_pkt_buf |
struct | iax2_registry |
struct | iax2_thread |
struct | iax2_trunk_peer |
struct | iax2_user |
struct | iax_dual |
struct | iax_firmware |
struct | iax_rr |
struct | parsed_dial_string |
Defines | |
#define | CACHE_FLAG_CANEXIST (1 << 2) |
#define | CACHE_FLAG_EXISTS (1 << 0) |
#define | CACHE_FLAG_MATCHMORE (1 << 7) |
#define | CACHE_FLAG_NONEXISTENT (1 << 1) |
#define | CACHE_FLAG_PENDING (1 << 3) |
#define | CACHE_FLAG_TIMEOUT (1 << 4) |
#define | CACHE_FLAG_TRANSMITTED (1 << 5) |
#define | CACHE_FLAG_UNKNOWN (1 << 6) |
#define | CALLNO_TO_PTR(a) ((void *)(unsigned long)(a)) |
#define | DEBUG_SCHED_MULTITHREAD |
#define | DEBUG_SUPPORT |
#define | DEFAULT_DROP 3 |
#define | DEFAULT_FREQ_NOTOK 10 * 1000 |
#define | DEFAULT_FREQ_OK 60 * 1000 |
#define | DEFAULT_MAX_THREAD_COUNT 100 |
#define | DEFAULT_MAXMS 2000 |
#define | DEFAULT_RETRY_TIME 1000 |
#define | DEFAULT_THREAD_COUNT 10 |
#define | DEFAULT_TRUNKDATA 640 * 10 |
#define | FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" |
#define | FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
#define | FORMAT "%-15.15s %-15d %-15d\n" |
#define | FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
#define | FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
#define | FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" |
#define | FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
#define | FORMAT2 "%-15.15s %-15.15s %-15.15s\n" |
#define | FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
#define | FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
#define | FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
#define | GAMMA (0.01) |
#define | IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
#define | IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF |
#define | IAX_CAPABILITY_LOWBANDWIDTH |
#define | IAX_CAPABILITY_LOWFREE |
#define | IAX_CAPABILITY_MEDBANDWIDTH |
#define | IAX_IOSTATE_IDLE 0 |
#define | IAX_IOSTATE_PROCESSING 2 |
#define | IAX_IOSTATE_READY 1 |
#define | IAX_IOSTATE_SCHEDREADY 3 |
#define | IAX_TYPE_DYNAMIC 2 |
#define | IAX_TYPE_POOL 1 |
#define | IPTOS_MINCOST 0x02 |
#define | MAX_JITTER_BUFFER 50 |
#define | MAX_RETRY_TIME 10000 |
#define | MAX_TIMESTAMP_SKEW 160 |
#define | MAX_TRUNKDATA 640 * 200 |
#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 0x4000 |
#define | TS_GAP_FOR_JB_RESYNC 5000 |
Enumerations | |
enum | { IAX_STATE_STARTED = (1 << 0), IAX_STATE_AUTHENTICATED = (1 << 1), IAX_STATE_TBD = (1 << 2), IAX_STATE_UNCHANGED = (1 << 3) } |
enum | { IAX_HASCALLERID = (1 << 0), IAX_DELME = (1 << 1), IAX_TEMPONLY = (1 << 2), IAX_TRUNK = (1 << 3), IAX_NOTRANSFER = (1 << 4), IAX_USEJITTERBUF = (1 << 5), IAX_DYNAMIC = (1 << 6), IAX_SENDANI = (1 << 7), IAX_ALREADYGONE = (1 << 9), IAX_PROVISION = (1 << 10), IAX_QUELCH = (1 << 11), IAX_ENCRYPTED = (1 << 12), IAX_KEYPOPULATED = (1 << 13), IAX_CODEC_USER_FIRST = (1 << 14), IAX_CODEC_NOPREFS = (1 << 15), IAX_CODEC_NOCAP = (1 << 16), IAX_RTCACHEFRIENDS = (1 << 17), IAX_RTUPDATE = (1 << 18), IAX_RTAUTOCLEAR = (1 << 19), IAX_FORCEJITTERBUF = (1 << 20), IAX_RTIGNOREREGEXPIRE = (1 << 21), IAX_TRUNKTIMESTAMPS = (1 << 22), IAX_TRANSFERMEDIA = (1 << 23), IAX_MAXAUTHREQ = (1 << 24), IAX_DELAYPBXSTART = (1 << 25) } |
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 (void *data) |
static void | __auth_reject (void *nothing) |
static void | __auto_congest (void *nothing) |
static void | __auto_hangup (void *nothing) |
static int | __do_deliver (void *data) |
static void | __expire_registry (void *data) |
static void | __get_from_jb (void *p) |
static void | __iax2_do_register_s (void *data) |
static void | __iax2_poke_noanswer (void *data) |
static void | __iax2_poke_peer_s (void *data) |
static int | __iax2_show_peers (int manager, int fd, struct mansession *s, int argc, char *argv[]) |
static int | __schedule_action (void(*func)(void *data), 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 (void *data) |
static void | __send_ping (void *data) |
static int | __unload_module (void) |
static int | apply_context (struct iax2_context *con, const char *context) |
static int | ast_cli_netstats (struct mansession *s, int fd, int limit_fmt) |
static struct ast_channel * | ast_iax2_new (int callno, int state, int capability) |
Create new call, interface with the PBX core. | |
static | AST_LIST_HEAD_STATIC (dynamic_list, iax2_thread) |
static | AST_LIST_HEAD_STATIC (active_list, iax2_thread) |
static | AST_LIST_HEAD_STATIC (idle_list, iax2_thread) |
static | AST_LIST_HEAD_STATIC (peers, iax2_peer) |
static | AST_LIST_HEAD_STATIC (users, iax2_user) |
static | AST_LIST_HEAD_STATIC (registrations, iax2_registry) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Inter Asterisk eXchange (Ver 2)",.load=load_module,.unload=unload_module,.reload=reload,) | |
AST_MUTEX_DEFINE_STATIC (dpcache_lock) | |
AST_MUTEX_DEFINE_STATIC (tpeerlock) | |
AST_MUTEX_DEFINE_STATIC (sched_lock) | |
static int | attempt_transmit (void *data) |
static int | auth_fail (int callno, int failcode) |
static int | auth_reject (void *data) |
static int | authenticate (const char *challenge, const char *secret, const char *keyn, int authmethods, struct iax_ie_data *ied, struct sockaddr_in *sin, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx) |
static int | authenticate_reply (struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, const char *override, const char *okey) |
static int | authenticate_request (struct chan_iax2_pvt *p) |
static int | authenticate_verify (struct chan_iax2_pvt *p, struct iax_ies *ies) |
static int | auto_congest (void *data) |
static int | auto_hangup (void *data) |
static struct iax2_context * | build_context (char *context) |
static void | build_enc_keys (const unsigned char *digest, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx) |
static struct iax2_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) |
Create peer structure based on configuration. | |
static struct iax2_user * | build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly) |
Create in-memory user structure from configuration. | |
static int | cache_get_callno_locked (const char *data) |
static unsigned int | calc_rxstamp (struct chan_iax2_pvt *p, unsigned int offset) |
static unsigned int | calc_timestamp (struct chan_iax2_pvt *p, unsigned int ts, struct ast_frame *f) |
static unsigned int | calc_txpeerstamp (struct iax2_trunk_peer *tpeer, int sampms, struct timeval *tv) |
static int | check_access (int callno, struct sockaddr_in *sin, struct iax_ies *ies) |
static int | check_provisioning (struct sockaddr_in *sin, int sockfd, char *si, unsigned int ver) |
static int | check_srcaddr (struct sockaddr *sa, socklen_t salen) |
Check if address can be used as packet source. | |
static int | complete_dpreply (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
static char * | complete_iax2_show_peer (const char *line, const char *word, int pos, int state) |
static int | complete_transfer (int callno, struct iax_ies *ies) |
static unsigned char | compress_subclass (int subclass) |
static void | construct_rr (struct chan_iax2_pvt *pvt, struct iax_ie_data *iep) |
static int | create_addr (const char *peername, struct sockaddr_in *sin, struct create_addr_info *cai) |
static int | decode_frame (aes_decrypt_ctx *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static int | decrypt_frame (int callno, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen) |
static void | defer_full_frame (struct iax2_thread *from_here, struct iax2_thread *to_here) |
Queue the last read full frame for processing by a certain thread. | |
static void | delete_users (void) |
static void | destroy_firmware (struct iax_firmware *cur) |
static void | destroy_peer (struct iax2_peer *peer) |
static void | destroy_user (struct iax2_user *user) |
static void | dp_lookup (int callno, const char *context, const char *callednum, const char *callerid, int skiplock) |
static void * | dp_lookup_thread (void *data) |
static int | encrypt_frame (aes_encrypt_ctx *ecx, struct ast_iax2_full_hdr *fh, unsigned char *poo, int *datalen) |
static int | expire_registry (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 lockpeer, int sockfd) |
static struct iax2_thread * | find_idle_thread (void) |
static struct iax2_peer * | find_peer (const char *name, int realtime) |
static struct iax2_trunk_peer * | find_tpeer (struct sockaddr_in *sin, int fd) |
static unsigned int | fix_peerts (struct timeval *tv, int callno, unsigned int ts) |
static void | free_context (struct iax2_context *con) |
static int | function_iaxpeer (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
static int | get_auth_methods (char *value) |
static int | get_encrypt_methods (const char *s) |
static int | get_from_jb (void *p) |
static void | handle_deferred_full_frames (struct iax2_thread *thread) |
Handle any deferred full frames for this thread. | |
static int | handle_error (void) |
static int | iax2_ack_registry (struct iax_ies *ies, struct sockaddr_in *sin, int callno) |
Acknowledgment received for OUR registration. | |
static int | iax2_answer (struct ast_channel *c) |
static enum ast_bridge_result | iax2_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
static int | iax2_call (struct ast_channel *c, char *dest, int timeout) |
static int | iax2_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
part of the IAX2 dial plan switch interface | |
static unsigned int | iax2_datetime (const char *tz) |
static void | iax2_destroy (int callno) |
static void | iax2_destroy_helper (struct chan_iax2_pvt *pvt) |
static int | iax2_devicestate (void *data) |
Part of the device state notification system ---. | |
static int | iax2_digit_begin (struct ast_channel *c, char digit) |
static int | iax2_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
static int | iax2_do_debug (int fd, int argc, char *argv[]) |
static int | iax2_do_jb_debug (int fd, int argc, char *argv[]) |
static int | iax2_do_register (struct iax2_registry *reg) |
static int | iax2_do_register_s (void *data) |
static int | iax2_do_trunk_debug (int fd, int argc, char *argv[]) |
static void | iax2_dprequest (struct iax2_dpcache *dp, int callno) |
static int | iax2_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Execute IAX2 dialplan switch. | |
static int | iax2_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 switch interface. | |
static int | iax2_fixup (struct ast_channel *oldchannel, struct ast_channel *newchan) |
static void | iax2_frame_free (struct iax_frame *fr) |
static int | iax2_getpeername (struct sockaddr_in sin, char *host, int len, int lockpeer) |
static int | iax2_getpeertrunk (struct sockaddr_in sin) |
static int | iax2_hangup (struct ast_channel *c) |
static int | iax2_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen) |
static int | iax2_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
Part of the IAX2 Switch interface. | |
static int | iax2_no_debug (int fd, int argc, char *argv[]) |
static int | iax2_no_jb_debug (int fd, int argc, char *argv[]) |
static int | iax2_no_trunk_debug (int fd, int argc, char *argv[]) |
static int | iax2_poke_noanswer (void *data) |
static int | iax2_poke_peer (struct iax2_peer *peer, int heldcall) |
static int | iax2_poke_peer_s (void *data) |
static int | iax2_predestroy (int callno) |
static void * | iax2_process_thread (void *data) |
static void | iax2_process_thread_cleanup (void *data) |
static int | iax2_prov_app (struct ast_channel *chan, void *data) |
static int | iax2_prov_cmd (int fd, int argc, char *argv[]) |
static char * | iax2_prov_complete_template_3rd (const char *line, const char *word, int pos, int state) |
static int | iax2_provision (struct sockaddr_in *end, int sockfd, char *dest, const char *template, int force) |
static int | iax2_prune_realtime (int fd, int argc, char *argv[]) |
static int | iax2_queue_frame (int callno, struct ast_frame *f) |
Queue a frame to a call's owning asterisk channel. | |
static struct ast_frame * | iax2_read (struct ast_channel *c) |
static int | iax2_register (char *value, int lineno) |
static int | iax2_reload (int fd, int argc, char *argv[]) |
static struct ast_channel * | iax2_request (const char *type, int format, void *data, int *cause) |
static int | iax2_send (struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned int ts, int seqno, int now, int transfer, int final) |
static int | iax2_sendhtml (struct ast_channel *c, int subclass, const char *data, int datalen) |
static int | iax2_sendimage (struct ast_channel *c, struct ast_frame *img) |
static int | iax2_sendtext (struct ast_channel *c, const char *text) |
static int | iax2_setoption (struct ast_channel *c, int option, void *data, int datalen) |
static int | iax2_show_cache (int fd, int argc, char *argv[]) |
static int | iax2_show_channels (int fd, int argc, char *argv[]) |
static int | iax2_show_firmware (int fd, int argc, char *argv[]) |
static int | iax2_show_netstats (int fd, int argc, char *argv[]) |
static int | iax2_show_peer (int fd, int argc, char *argv[]) |
Show one peer in detail. | |
static int | iax2_show_peers (int fd, int argc, char *argv[]) |
static int | iax2_show_registry (int fd, int argc, char *argv[]) |
static int | iax2_show_stats (int fd, int argc, char *argv[]) |
static int | iax2_show_threads (int fd, int argc, char *argv[]) |
static int | iax2_show_users (int fd, int argc, char *argv[]) |
static int | iax2_start_transfer (unsigned short callno0, unsigned short callno1, int mediaonly) |
static int | iax2_test_losspct (int fd, int argc, char *argv[]) |
static int | iax2_transfer (struct ast_channel *c, const char *dest) |
static int | iax2_transmit (struct iax_frame *fr) |
static int | iax2_trunk_expired (struct iax2_trunk_peer *tpeer, struct timeval *now) |
static int | iax2_trunk_queue (struct chan_iax2_pvt *pvt, struct iax_frame *fr) |
static int | iax2_vnak (int callno) |
static int | iax2_write (struct ast_channel *c, struct ast_frame *f) |
static int | iax_check_version (char *dev) |
static void | iax_debug_output (const char *data) |
static void | iax_error_output (const char *data) |
static int | iax_firmware_append (struct iax_ie_data *ied, const unsigned char *dev, unsigned int desc) |
static int | iax_park (struct ast_channel *chan1, struct ast_channel *chan2) |
static void * | iax_park_thread (void *stuff) |
static struct iax_frame * | iaxfrdup2 (struct iax_frame *fr) |
static void | insert_idle_thread (struct iax2_thread *thread) |
static void | jb_debug_output (const char *fmt,...) |
static void | jb_error_output (const char *fmt,...) |
static void | jb_warning_output (const char *fmt,...) |
static int | load_module (void) |
Load IAX2 module, load configuraiton ---. | |
static void | lock_both (unsigned short callno0, unsigned short callno1) |
static int | make_trunk (unsigned short callno, int locked) |
static int | manager_iax2_show_netstats (struct mansession *s, const struct message *m) |
static int | manager_iax2_show_peers (struct mansession *s, const struct message *m) |
static int | match (struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, struct chan_iax2_pvt *cur) |
static void | memcpy_decrypt (unsigned char *dst, const unsigned char *src, int len, aes_decrypt_ctx *dcx) |
static void | memcpy_encrypt (unsigned char *dst, const unsigned char *src, int len, aes_encrypt_ctx *ecx) |
static void | merge_encryption (struct chan_iax2_pvt *p, unsigned int enc) |
static void * | network_thread (void *ignore) |
static struct chan_iax2_pvt * | new_iax (struct sockaddr_in *sin, int lockpeer, 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_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 void | prune_peers (void) |
static void | prune_users (void) |
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) |
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 (const char *name, 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 (void) |
static void | save_rr (struct iax_frame *fr, struct iax_ies *ies) |
static void * | sched_thread (void *ignore) |
static int | schedule_delivery (struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout) |
static int | send_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 (void *data) |
static int | send_packet (struct iax_frame *f) |
static int | send_ping (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_timing (void) |
static void | signal_condition (ast_mutex_t *lock, ast_cond_t *cond) |
static int | socket_process (struct iax2_thread *thread) |
static int | socket_read (int *id, int fd, short events, void *cbdata) |
static void | spawn_dp_lookup (int callno, const char *context, const char *callednum, const char *callerid) |
static int | start_network_thread (void) |
static void | stop_stuff (int callno) |
static int | timing_read (int *id, int fd, short events, void *cbdata) |
static int | transmit_trunk (struct iax_frame *f, struct sockaddr_in *sin, int sockfd) |
static int | try_firmware (char *s) |
static int | try_transfer (struct chan_iax2_pvt *pvt, struct iax_ies *ies) |
static int | uncompress_subclass (unsigned char csub) |
static 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 (const char *name, struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) |
static void | vnak_retransmit (int callno, int last) |
Variables | |
static char | accountcode [AST_MAX_ACCOUNT_CODE] |
static int | adsi = 0 |
static int | amaflags = 0 |
static int | authdebug = 1 |
static int | autokill = 0 |
static struct ast_cli_entry | cli_iax2 [] |
static struct ast_cli_entry | cli_iax2_jb_debug_deprecated |
static struct ast_cli_entry | cli_iax2_no_debug_deprecated |
static struct ast_cli_entry | cli_iax2_no_jb_debug_deprecated |
static struct ast_cli_entry | cli_iax2_no_trunk_debug_deprecated |
static struct ast_cli_entry | cli_iax2_trunk_debug_deprecated |
static char | context [80] = "default" |
static char | debug_jb_usage [] |
static char | debug_trunk_usage [] |
static char | debug_usage [] |
static int | defaultsockfd = -1 |
static int | delayreject = 0 |
static struct iax2_dpcache * | dpcache |
static int | global_rtautoclear = 120 |
static struct ast_flags | globalflags = { 0 } |
static int | iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH |
static int | iax2_encryption = 0 |
enum { ... } | iax2_flags |
int(* | iax2_regfunk )(const char *username, int onoff) = NULL |
static char | iax2_reload_usage [] |
enum { ... } | iax2_state |
static struct ast_switch | iax2_switch |
static struct ast_channel_tech | iax2_tech |
static char | iax2_test_losspct_usage [] |
static int | iaxactivethreadcount = 0 |
static int | iaxcompat = 0 |
static int | iaxdebug = 0 |
static int | iaxdefaultdpcache = 10 * 60 |
static int | iaxdefaulttimeout = 5 |
static int | iaxdynamicthreadcount = 0 |
static int | iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT |
struct ast_custom_function | iaxpeer_function |
static struct ast_iax2_queue | iaxq |
static struct chan_iax2_pvt * | iaxs [IAX_MAX_CALLS] |
static ast_mutex_t | iaxsl [IAX_MAX_CALLS] |
static int | iaxthreadcount = DEFAULT_THREAD_COUNT |
static int | iaxtrunkdebug = 0 |
static struct io_context * | io |
static int | lagrq_time = 10 |
static char | language [MAX_LANGUAGE] = "" |
static struct timeval | lastused [IAX_MAX_CALLS] |
static int | max_reg_expire |
static int | max_retries = 4 |
static int | maxauthreq = 3 |
static int | maxjitterbuffer = 1000 |
static int | maxjitterinterps = 10 |
static int | maxnontrunkcall = 1 |
static int | maxtrunkcall = TRUNK_CALL_START |
static int | min_reg_expire |
static char | mohinterpret [MAX_MUSICCLASS] |
static char | mohsuggest [MAX_MUSICCLASS] |
static struct ast_netsock_list * | netsock |
static pthread_t | netthreadid = AST_PTHREADT_NULL |
static char | no_debug_jb_usage [] |
static char | no_debug_trunk_usage [] |
static char | no_debug_usage [] |
static struct ast_netsock_list * | outsock |
static char * | papp = "IAX2Provision" |
static char * | pdescrip |
static int | ping_time = 21 |
static struct ast_codec_pref | prefs |
static char | prune_realtime_usage [] |
static char * | psyn = "Provision a calling IAXy with a given template" |
static char | regcontext [AST_MAX_CONTEXT] = "" |
static int | resyncthreshold = 1000 |
static struct sched_context * | sched |
static ast_cond_t | sched_cond |
static pthread_t | schedthreadid = AST_PTHREADT_NULL |
static char | show_cache_usage [] |
static char | show_channels_usage [] |
static char | show_firmware_usage [] |
static char | show_netstats_usage [] |
static char | show_peer_usage [] |
static char | show_peers_usage [] |
static char | show_prov_usage [] |
static char | show_reg_usage [] |
static char | show_stats_usage [] |
static char | show_threads_usage [] |
static char | show_users_usage [] |
static const char | tdesc [] = "Inter Asterisk eXchange Driver (Ver 2)" |
static int | test_losspct = 0 |
static int | timingfd = -1 |
static unsigned int | tos = 0 |
static struct iax2_trunk_peer * | tpeers |
static int | trunkfreq = 20 |
static struct ast_firmware_list | waresl |
Definition in file chan_iax2.c.
#define CACHE_FLAG_CANEXIST (1 << 2) |
Extension can exist
Definition at line 649 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_canmatch(), and iax2_show_cache().
#define CACHE_FLAG_EXISTS (1 << 0) |
Extension exists
Definition at line 645 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_exec(), iax2_exists(), and iax2_show_cache().
#define CACHE_FLAG_MATCHMORE (1 << 7) |
Matchmore
Definition at line 659 of file chan_iax2.c.
Referenced by complete_dpreply(), iax2_matchmore(), and iax2_show_cache().
#define CACHE_FLAG_NONEXISTENT (1 << 1) |
Extension is nonexistent
Definition at line 647 of file chan_iax2.c.
Referenced by complete_dpreply(), and iax2_show_cache().
#define CACHE_FLAG_PENDING (1 << 3) |
Waiting to hear back response
Definition at line 651 of file chan_iax2.c.
Referenced by complete_dpreply(), find_cache(), and iax2_show_cache().
#define CACHE_FLAG_TIMEOUT (1 << 4) |
Timed out
Definition at line 653 of file chan_iax2.c.
Referenced by find_cache(), and iax2_show_cache().
#define CACHE_FLAG_TRANSMITTED (1 << 5) |
Request transmitted
Definition at line 655 of file chan_iax2.c.
Referenced by iax2_dprequest(), iax2_show_cache(), and socket_process().
#define CACHE_FLAG_UNKNOWN (1 << 6) |
Timeout
Definition at line 657 of file chan_iax2.c.
Referenced by complete_dpreply(), and iax2_show_cache().
#define CALLNO_TO_PTR | ( | a | ) | ((void *)(unsigned long)(a)) |
Definition at line 121 of file chan_iax2.c.
Referenced by ast_iax2_new(), iax2_call(), and update_jbsched().
#define DEBUG_SCHED_MULTITHREAD |
Definition at line 109 of file chan_iax2.c.
#define DEBUG_SUPPORT |
Definition at line 132 of file chan_iax2.c.
#define DEFAULT_DROP 3 |
Definition at line 127 of file chan_iax2.c.
#define DEFAULT_FREQ_NOTOK 10 * 1000 |
Definition at line 199 of file chan_iax2.c.
Referenced by build_peer(), handle_response_peerpoke(), and sip_poke_noanswer().
#define DEFAULT_FREQ_OK 60 * 1000 |
Definition at line 198 of file chan_iax2.c.
Referenced by build_peer(), and handle_response_peerpoke().
#define DEFAULT_MAX_THREAD_COUNT 100 |
Definition at line 124 of file chan_iax2.c.
#define DEFAULT_MAXMS 2000 |
Definition at line 197 of file chan_iax2.c.
#define DEFAULT_RETRY_TIME 1000 |
#define DEFAULT_THREAD_COUNT 10 |
Definition at line 123 of file chan_iax2.c.
#define DEFAULT_TRUNKDATA 640 * 10 |
40ms, uncompressed linear * 10 channels
Definition at line 443 of file chan_iax2.c.
Referenced by iax2_trunk_queue().
#define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" |
#define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" |
#define FORMAT "%-15.15s %-15d %-15d\n" |
#define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" |
#define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" |
#define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" |
#define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" |
#define FORMAT2 "%-15.15s %-15.15s %-15.15s\n" |
#define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" |
#define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" |
#define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" |
#define GAMMA (0.01) |
Definition at line 137 of file chan_iax2.c.
#define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) |
#define IAX_CAPABILITY_FULLBANDWIDTH 0xFFFF |
Definition at line 180 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), and set_config().
#define IAX_CAPABILITY_LOWBANDWIDTH |
Value:
(IAX_CAPABILITY_MEDBANDWIDTH & \ ~AST_FORMAT_G726 & \ ~AST_FORMAT_G726_AAL2 & \ ~AST_FORMAT_ADPCM)
Definition at line 188 of file chan_iax2.c.
Referenced by set_config().
#define IAX_CAPABILITY_LOWFREE |
Value:
Definition at line 193 of file chan_iax2.c.
#define IAX_CAPABILITY_MEDBANDWIDTH |
Value:
(IAX_CAPABILITY_FULLBANDWIDTH & \ ~AST_FORMAT_SLINEAR & \ ~AST_FORMAT_ULAW & \ ~AST_FORMAT_ALAW & \ ~AST_FORMAT_G722)
Definition at line 182 of file chan_iax2.c.
Referenced by set_config().
#define IAX_IOSTATE_IDLE 0 |
#define IAX_IOSTATE_PROCESSING 2 |
#define IAX_IOSTATE_READY 1 |
#define IAX_IOSTATE_SCHEDREADY 3 |
Definition at line 684 of file chan_iax2.c.
Referenced by __schedule_action(), and iax2_process_thread().
#define IAX_TYPE_DYNAMIC 2 |
Definition at line 687 of file chan_iax2.c.
Referenced by find_idle_thread(), iax2_process_thread(), iax2_show_threads(), and insert_idle_thread().
#define IAX_TYPE_POOL 1 |
#define IPTOS_MINCOST 0x02 |
Definition at line 112 of file chan_iax2.c.
#define MAX_JITTER_BUFFER 50 |
Definition at line 440 of file chan_iax2.c.
#define MAX_RETRY_TIME 10000 |
#define MAX_TIMESTAMP_SKEW 160 |
maximum difference between actual and predicted ts for sending
Definition at line 446 of file chan_iax2.c.
#define MAX_TRUNKDATA 640 * 200 |
40ms, uncompressed linear * 200 channels
Definition at line 444 of file chan_iax2.c.
Referenced by iax2_trunk_queue(), and timing_read().
#define MEMORY_SIZE 100 |
Definition at line 126 of file chan_iax2.c.
#define MIN_JITTER_BUFFER 10 |
Definition at line 441 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 1150 of file chan_iax2.c.
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_poke_peer(), iax2_provision(), and iax2_request().
#define NEW_PREVENT 0 |
#define PTR_TO_CALLNO | ( | a | ) | ((unsigned short)(unsigned long)(a)) |
Definition at line 120 of file chan_iax2.c.
Referenced by __auto_congest(), __get_from_jb(), function_iaxpeer(), iax2_answer(), iax2_bridge(), iax2_call(), iax2_digit_begin(), iax2_digit_end(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_prov_app(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), iax2_transfer(), and iax2_write().
#define SCHED_MULTITHREADED |
Definition at line 105 of file chan_iax2.c.
Definition at line 951 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 0x4000 |
Definition at line 130 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 449 of file chan_iax2.c.
anonymous enum |
Definition at line 233 of file chan_iax2.c.
00233 { 00234 IAX_STATE_STARTED = (1 << 0), 00235 IAX_STATE_AUTHENTICATED = (1 << 1), 00236 IAX_STATE_TBD = (1 << 2), 00237 IAX_STATE_UNCHANGED = (1 << 3), 00238 } iax2_state;
anonymous enum |
Definition at line 245 of file chan_iax2.c.
00245 { 00246 IAX_HASCALLERID = (1 << 0), /*!< CallerID has been specified */ 00247 IAX_DELME = (1 << 1), /*!< Needs to be deleted */ 00248 IAX_TEMPONLY = (1 << 2), /*!< Temporary (realtime) */ 00249 IAX_TRUNK = (1 << 3), /*!< Treat as a trunk */ 00250 IAX_NOTRANSFER = (1 << 4), /*!< Don't native bridge */ 00251 IAX_USEJITTERBUF = (1 << 5), /*!< Use jitter buffer */ 00252 IAX_DYNAMIC = (1 << 6), /*!< dynamic peer */ 00253 IAX_SENDANI = (1 << 7), /*!< Send ANI along with CallerID */ 00254 /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */ 00255 IAX_ALREADYGONE = (1 << 9), /*!< Already disconnected */ 00256 IAX_PROVISION = (1 << 10), /*!< This is a provisioning request */ 00257 IAX_QUELCH = (1 << 11), /*!< Whether or not we quelch audio */ 00258 IAX_ENCRYPTED = (1 << 12), /*!< Whether we should assume encrypted tx/rx */ 00259 IAX_KEYPOPULATED = (1 << 13), /*!< Whether we have a key populated */ 00260 IAX_CODEC_USER_FIRST = (1 << 14), /*!< are we willing to let the other guy choose the codec? */ 00261 IAX_CODEC_NOPREFS = (1 << 15), /*!< Force old behaviour by turning off prefs */ 00262 IAX_CODEC_NOCAP = (1 << 16), /*!< only consider requested format and ignore capabilities*/ 00263 IAX_RTCACHEFRIENDS = (1 << 17), /*!< let realtime stay till your reload */ 00264 IAX_RTUPDATE = (1 << 18), /*!< Send a realtime update */ 00265 IAX_RTAUTOCLEAR = (1 << 19), /*!< erase me on expire */ 00266 IAX_FORCEJITTERBUF = (1 << 20), /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 00267 IAX_RTIGNOREREGEXPIRE = (1 << 21), /*!< When using realtime, ignore registration expiration */ 00268 IAX_TRUNKTIMESTAMPS = (1 << 22), /*!< Send trunk timestamps */ 00269 IAX_TRANSFERMEDIA = (1 << 23), /*!< When doing IAX2 transfers, transfer media only */ 00270 IAX_MAXAUTHREQ = (1 << 24), /*!< Maximum outstanding AUTHREQ restriction is in place */ 00271 IAX_DELAYPBXSTART = (1 << 25), /*!< Don't start a PBX on the channel until the peer sends us a 00272 response, so that we've achieved a three-way handshake with 00273 them before sending voice or anything else*/ 00274 } iax2_flags;
enum iax_reg_state |
REG_STATE_UNREGISTERED | |
REG_STATE_REGSENT | |
REG_STATE_AUTHSENT | |
REG_STATE_REGISTERED | |
REG_STATE_REJECTED | |
REG_STATE_TIMEOUT | |
REG_STATE_NOAUTH |
Definition at line 395 of file chan_iax2.c.
00395 { 00396 REG_STATE_UNREGISTERED = 0, 00397 REG_STATE_REGSENT, 00398 REG_STATE_AUTHSENT, 00399 REG_STATE_REGISTERED, 00400 REG_STATE_REJECTED, 00401 REG_STATE_TIMEOUT, 00402 REG_STATE_NOAUTH 00403 };
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 405 of file chan_iax2.c.
00405 { 00406 TRANSFER_NONE = 0, 00407 TRANSFER_BEGIN, 00408 TRANSFER_READY, 00409 TRANSFER_RELEASED, 00410 TRANSFER_PASSTHROUGH, 00411 TRANSFER_MBEGIN, 00412 TRANSFER_MREADY, 00413 TRANSFER_MRELEASED, 00414 TRANSFER_MPASSTHROUGH, 00415 TRANSFER_MEDIA, 00416 TRANSFER_MEDIAPASS 00417 };
static void __attempt_transmit | ( | void * | data | ) | [static] |
Definition at line 1874 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_IAX, ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), attempt_transmit(), iax_frame::callno, chan_iax2_pvt::error, f, iax_frame::final, ast_frame::frametype, ast_channel::hangupcause, iax2_destroy(), iax2_frame_free(), iax2_queue_frame(), IAX_COMMAND_TXREJ, IAX_DEFAULT_REG_EXPIRE, iaxq, iaxs, iaxsl, LOG_WARNING, MAX_RETRY_TIME, iax_frame::oseqno, chan_iax2_pvt::owner, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_TIMEOUT, iax2_registry::regstate, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_command(), send_packet(), ast_frame::subclass, iax_frame::transfer, iax_frame::ts, update_packet(), and iax2_registry::us.
Referenced by attempt_transmit().
01875 { 01876 /* Attempt to transmit the frame to the remote peer... 01877 Called without iaxsl held. */ 01878 struct iax_frame *f = data; 01879 int freeme=0; 01880 int callno = f->callno; 01881 /* Make sure this call is still active */ 01882 if (callno) 01883 ast_mutex_lock(&iaxsl[callno]); 01884 if (callno && iaxs[callno]) { 01885 if ((f->retries < 0) /* Already ACK'd */ || 01886 (f->retries >= max_retries) /* Too many attempts */) { 01887 /* Record an error if we've transmitted too many times */ 01888 if (f->retries >= max_retries) { 01889 if (f->transfer) { 01890 /* Transfer timeout */ 01891 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 01892 } else if (f->final) { 01893 if (f->final) 01894 iax2_destroy(callno); 01895 } else { 01896 if (iaxs[callno]->owner) 01897 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); 01898 iaxs[callno]->error = ETIMEDOUT; 01899 if (iaxs[callno]->owner) { 01900 struct ast_frame fr = { 0, }; 01901 /* Hangup the fd */ 01902 fr.frametype = AST_FRAME_CONTROL; 01903 fr.subclass = AST_CONTROL_HANGUP; 01904 iax2_queue_frame(callno, &fr); // XXX 01905 /* Remember, owner could disappear */ 01906 if (iaxs[callno] && iaxs[callno]->owner) 01907 iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 01908 } else { 01909 if (iaxs[callno]->reg) { 01910 memset(&iaxs[callno]->reg->us, 0, sizeof(iaxs[callno]->reg->us)); 01911 iaxs[callno]->reg->regstate = REG_STATE_TIMEOUT; 01912 iaxs[callno]->reg->refresh = IAX_DEFAULT_REG_EXPIRE; 01913 } 01914 iax2_destroy(callno); 01915 } 01916 } 01917 01918 } 01919 freeme++; 01920 } else { 01921 /* Update it if it needs it */ 01922 update_packet(f); 01923 /* Attempt transmission */ 01924 send_packet(f); 01925 f->retries++; 01926 /* Try again later after 10 times as long */ 01927 f->retrytime *= 10; 01928 if (f->retrytime > MAX_RETRY_TIME) 01929 f->retrytime = MAX_RETRY_TIME; 01930 /* Transfer messages max out at one second */ 01931 if (f->transfer && (f->retrytime > 1000)) 01932 f->retrytime = 1000; 01933 f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f); 01934 } 01935 } else { 01936 /* Make sure it gets freed */ 01937 f->retries = -1; 01938 freeme++; 01939 } 01940 if (callno) 01941 ast_mutex_unlock(&iaxsl[callno]); 01942 /* Do not try again */ 01943 if (freeme) { 01944 /* Don't attempt delivery, just remove it from the queue */ 01945 AST_LIST_LOCK(&iaxq.queue); 01946 AST_LIST_REMOVE(&iaxq.queue, f, list); 01947 iaxq.count--; 01948 AST_LIST_UNLOCK(&iaxq.queue); 01949 f->retrans = -1; 01950 /* Free the IAX frame */ 01951 iax2_frame_free(f); 01952 } 01953 }
static void __auth_reject | ( | void * | nothing | ) | [static] |
Definition at line 5842 of file chan_iax2.c.
References AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_FACILITY_REJECTED, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, IAX_COMMAND_REGREJ, IAX_COMMAND_REJECT, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().
Referenced by auth_reject().
05843 { 05844 /* Called from IAX thread only, without iaxs lock */ 05845 int callno = (int)(long)(nothing); 05846 struct iax_ie_data ied; 05847 ast_mutex_lock(&iaxsl[callno]); 05848 if (iaxs[callno]) { 05849 memset(&ied, 0, sizeof(ied)); 05850 if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { 05851 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); 05852 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); 05853 } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { 05854 iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); 05855 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 05856 } 05857 send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); 05858 } 05859 ast_mutex_unlock(&iaxsl[callno]); 05860 }
static void __auto_congest | ( | void * | nothing | ) | [static] |
Definition at line 2760 of file chan_iax2.c.
References AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iax2_queue_frame(), iaxs, iaxsl, chan_iax2_pvt::initid, LOG_NOTICE, and PTR_TO_CALLNO.
Referenced by auto_congest().
02761 { 02762 int callno = PTR_TO_CALLNO(nothing); 02763 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; 02764 ast_mutex_lock(&iaxsl[callno]); 02765 if (iaxs[callno]) { 02766 iaxs[callno]->initid = -1; 02767 iax2_queue_frame(callno, &f); 02768 ast_log(LOG_NOTICE, "Auto-congesting call due to slow response\n"); 02769 } 02770 ast_mutex_unlock(&iaxsl[callno]); 02771 }
static void __auto_hangup | ( | void * | nothing | ) | [static] |
Definition at line 5894 of file chan_iax2.c.
References AST_CAUSE_NO_USER_RESPONSE, AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), iax_ie_data::buf, IAX_COMMAND_HANGUP, iax_ie_append_byte(), iax_ie_append_str(), IAX_IE_CAUSE, IAX_IE_CAUSECODE, iaxs, iaxsl, iax_ie_data::pos, and send_command_final().
Referenced by auto_hangup().
05895 { 05896 /* Called from IAX thread only, without iaxs lock */ 05897 int callno = (int)(long)(nothing); 05898 struct iax_ie_data ied; 05899 ast_mutex_lock(&iaxsl[callno]); 05900 if (iaxs[callno]) { 05901 memset(&ied, 0, sizeof(ied)); 05902 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); 05903 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); 05904 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 05905 } 05906 ast_mutex_unlock(&iaxsl[callno]); 05907 }
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 1638 of file chan_iax2.c.
References iax_frame::af, ast_test_flag, iax_frame::callno, ast_frame::has_timing_info, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, and iax_frame::retrans.
Referenced by __get_from_jb(), and schedule_delivery().
01639 { 01640 /* Just deliver the packet by using queueing. This is called by 01641 the IAX thread with the iaxsl lock held. */ 01642 struct iax_frame *fr = data; 01643 fr->retrans = -1; 01644 fr->af.has_timing_info = 0; 01645 if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) 01646 iax2_queue_frame(fr->callno, &fr->af); 01647 /* Free our iax frame */ 01648 iax2_frame_free(fr); 01649 /* And don't run again */ 01650 return 0; 01651 }
static void __expire_registry | ( | void * | data | ) | [static] |
Definition at line 5567 of file chan_iax2.c.
References iax2_peer::addr, ast_db_del(), ast_device_state_changed(), AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_set_flag, ast_test_flag, EVENT_FLAG_SYSTEM, iax2_peer::expire, iax2_peer::expiry, iax2_regfunk, IAX_DELME, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_TEMPONLY, LOG_DEBUG, manager_event(), name, prune_peers(), realtime_update_peer(), and register_peer_exten().
Referenced by expire_registry().
05568 { 05569 char *name = data; 05570 struct iax2_peer *p = NULL; 05571 05572 /* Go through and grab this peer... and if it needs to be removed... then do it */ 05573 AST_LIST_LOCK(&peers); 05574 AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, p, entry) { 05575 if (!strcasecmp(p->name, name)) { 05576 p->expire = -1; 05577 break; 05578 } 05579 } 05580 AST_LIST_TRAVERSE_SAFE_END 05581 AST_LIST_UNLOCK(&peers); 05582 05583 /* Peer is already gone for whatever reason */ 05584 if (!p) 05585 return; 05586 05587 ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", p->name); 05588 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) 05589 realtime_update_peer(p->name, &p->addr, 0); 05590 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", p->name); 05591 /* Reset the address */ 05592 memset(&p->addr, 0, sizeof(p->addr)); 05593 /* Reset expiry value */ 05594 p->expiry = min_reg_expire; 05595 if (!ast_test_flag(p, IAX_TEMPONLY)) 05596 ast_db_del("IAX/Registry", p->name); 05597 register_peer_exten(p, 0); 05598 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05599 if (iax2_regfunk) 05600 iax2_regfunk(p->name, 0); 05601 05602 if (ast_test_flag(p, IAX_RTAUTOCLEAR)) { 05603 ast_set_flag(p, IAX_DELME); 05604 prune_peers(); 05605 } 05606 }
static void __get_from_jb | ( | void * | p | ) | [static] |
Definition at line 2271 of file chan_iax2.c.
References __do_deliver(), ast_codec_interp_len(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_tvadd(), jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), iax2_queue_frame(), IAX_ALREADYGONE, iaxs, iaxsl, chan_iax2_pvt::jb, JB_DROP, JB_EMPTY, jb_get(), JB_INTERP, jb_next(), JB_NOFRAME, JB_OK, chan_iax2_pvt::jbid, jb_frame::ms, ast_frame::offset, PTR_TO_CALLNO, chan_iax2_pvt::rxcore, ast_frame::samples, ast_frame::src, ast_frame::subclass, update_jbsched(), and chan_iax2_pvt::voiceformat.
Referenced by get_from_jb().
02272 { 02273 int callno = PTR_TO_CALLNO(p); 02274 struct chan_iax2_pvt *pvt = NULL; 02275 struct iax_frame *fr; 02276 jb_frame frame; 02277 int ret; 02278 long now; 02279 long next; 02280 struct timeval tv; 02281 02282 /* Make sure we have a valid private structure before going on */ 02283 ast_mutex_lock(&iaxsl[callno]); 02284 pvt = iaxs[callno]; 02285 if (!pvt) { 02286 /* No go! */ 02287 ast_mutex_unlock(&iaxsl[callno]); 02288 return; 02289 } 02290 02291 pvt->jbid = -1; 02292 02293 gettimeofday(&tv,NULL); 02294 /* round up a millisecond since ast_sched_runq does; */ 02295 /* prevents us from spinning while waiting for our now */ 02296 /* to catch up with runq's now */ 02297 tv.tv_usec += 1000; 02298 02299 now = ast_tvdiff_ms(tv, pvt->rxcore); 02300 02301 if(now >= (next = jb_next(pvt->jb))) { 02302 ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat)); 02303 switch(ret) { 02304 case JB_OK: 02305 fr = frame.data; 02306 __do_deliver(fr); 02307 /* __do_deliver() can cause the call to disappear */ 02308 pvt = iaxs[callno]; 02309 break; 02310 case JB_INTERP: 02311 { 02312 struct ast_frame af = { 0, }; 02313 02314 /* create an interpolation frame */ 02315 af.frametype = AST_FRAME_VOICE; 02316 af.subclass = pvt->voiceformat; 02317 af.samples = frame.ms * 8; 02318 af.src = "IAX2 JB interpolation"; 02319 af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000)); 02320 af.offset = AST_FRIENDLY_OFFSET; 02321 02322 /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame, 02323 * which we'd need to malloc, and then it would free it. That seems like a drag */ 02324 if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) { 02325 iax2_queue_frame(callno, &af); 02326 /* iax2_queue_frame() could cause the call to disappear */ 02327 pvt = iaxs[callno]; 02328 } 02329 } 02330 break; 02331 case JB_DROP: 02332 iax2_frame_free(frame.data); 02333 break; 02334 case JB_NOFRAME: 02335 case JB_EMPTY: 02336 /* do nothing */ 02337 break; 02338 default: 02339 /* shouldn't happen */ 02340 break; 02341 } 02342 } 02343 if (pvt) 02344 update_jbsched(pvt); 02345 ast_mutex_unlock(&iaxsl[callno]); 02346 }
static void __iax2_do_register_s | ( | void * | data | ) | [static] |
Definition at line 5284 of file chan_iax2.c.
References iax2_registry::expire, and iax2_do_register().
Referenced by iax2_do_register_s().
05285 { 05286 struct iax2_registry *reg = data; 05287 reg->expire = -1; 05288 iax2_do_register(reg); 05289 }
static void __iax2_poke_noanswer | ( | void * | data | ) | [static] |
Definition at line 8147 of file chan_iax2.c.
References ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), iax2_peer::callno, EVENT_FLAG_SYSTEM, iax2_destroy(), iax2_poke_peer_s(), iaxsl, iax2_peer::lastms, LOG_NOTICE, manager_event(), iax2_peer::pokeexpire, and iax2_peer::pokefreqnotok.
Referenced by iax2_poke_noanswer().
08148 { 08149 struct iax2_peer *peer = data; 08150 if (peer->lastms > -1) { 08151 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms); 08152 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms); 08153 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 08154 } 08155 if (peer->callno > 0) { 08156 ast_mutex_lock(&iaxsl[peer->callno]); 08157 iax2_destroy(peer->callno); 08158 ast_mutex_unlock(&iaxsl[peer->callno]); 08159 } 08160 peer->callno = 0; 08161 peer->lastms = -1; 08162 /* Try again quickly */ 08163 peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer); 08164 }
static void __iax2_poke_peer_s | ( | void * | data | ) | [static] |
Definition at line 5958 of file chan_iax2.c.
References iax2_poke_peer().
Referenced by iax2_poke_peer_s().
05959 { 05960 struct iax2_peer *peer = data; 05961 iax2_poke_peer(peer, 0); 05962 }
static int __iax2_show_peers | ( | int | manager, | |
int | fd, | |||
struct mansession * | s, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4109 of file chan_iax2.c.
References iax2_peer::addr, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, astman_append(), iax2_peer::encmethods, FORMAT, FORMAT2, IAX_DYNAMIC, IAX_TRUNK, iax2_peer::mask, name, peer_status(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
Referenced by iax2_show_peers(), and manager_iax2_show_peers().
04110 { 04111 regex_t regexbuf; 04112 int havepattern = 0; 04113 int total_peers = 0; 04114 int online_peers = 0; 04115 int offline_peers = 0; 04116 int unmonitored_peers = 0; 04117 04118 #define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s" 04119 #define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s" 04120 04121 struct iax2_peer *peer = NULL; 04122 char name[256]; 04123 int registeredonly=0; 04124 char *term = manager ? "\r\n" : "\n"; 04125 04126 switch (argc) { 04127 case 6: 04128 if (!strcasecmp(argv[3], "registered")) 04129 registeredonly = 1; 04130 else 04131 return RESULT_SHOWUSAGE; 04132 if (!strcasecmp(argv[4], "like")) { 04133 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB)) 04134 return RESULT_SHOWUSAGE; 04135 havepattern = 1; 04136 } else 04137 return RESULT_SHOWUSAGE; 04138 break; 04139 case 5: 04140 if (!strcasecmp(argv[3], "like")) { 04141 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04142 return RESULT_SHOWUSAGE; 04143 havepattern = 1; 04144 } else 04145 return RESULT_SHOWUSAGE; 04146 break; 04147 case 4: 04148 if (!strcasecmp(argv[3], "registered")) 04149 registeredonly = 1; 04150 else 04151 return RESULT_SHOWUSAGE; 04152 break; 04153 case 3: 04154 break; 04155 default: 04156 return RESULT_SHOWUSAGE; 04157 } 04158 04159 04160 if (s) 04161 astman_append(s, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04162 else 04163 ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term); 04164 04165 AST_LIST_LOCK(&peers); 04166 AST_LIST_TRAVERSE(&peers, peer, entry) { 04167 char nm[20]; 04168 char status[20]; 04169 char srch[2000]; 04170 int retstatus; 04171 04172 if (registeredonly && !peer->addr.sin_addr.s_addr) 04173 continue; 04174 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) 04175 continue; 04176 04177 if (!ast_strlen_zero(peer->username)) 04178 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 04179 else 04180 ast_copy_string(name, peer->name, sizeof(name)); 04181 04182 retstatus = peer_status(peer, status, sizeof(status)); 04183 if (retstatus > 0) 04184 online_peers++; 04185 else if (!retstatus) 04186 offline_peers++; 04187 else 04188 unmonitored_peers++; 04189 04190 ast_copy_string(nm, ast_inet_ntoa(peer->mask), sizeof(nm)); 04191 04192 snprintf(srch, sizeof(srch), FORMAT, name, 04193 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04194 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04195 nm, 04196 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04197 peer->encmethods ? "(E)" : " ", status, term); 04198 04199 if (s) 04200 astman_append(s, FORMAT, name, 04201 peer->addr.sin_addr.s_addr ? ast_inet_ntoa( peer->addr.sin_addr) : "(Unspecified)", 04202 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04203 nm, 04204 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04205 peer->encmethods ? "(E)" : " ", status, term); 04206 else 04207 ast_cli(fd, FORMAT, name, 04208 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 04209 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)", 04210 nm, 04211 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ", 04212 peer->encmethods ? "(E)" : " ", status, term); 04213 total_peers++; 04214 } 04215 AST_LIST_UNLOCK(&peers); 04216 04217 if (s) 04218 astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04219 else 04220 ast_cli(fd,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term); 04221 04222 if (havepattern) 04223 regfree(®exbuf); 04224 04225 return RESULT_SUCCESS; 04226 #undef FORMAT 04227 #undef FORMAT2 04228 }
static int __schedule_action | ( | void(*)(void *data) | func, | |
void * | data, | |||
const char * | funcname | |||
) | [static] |
Definition at line 926 of file chan_iax2.c.
References ast_log(), find_idle_thread(), func, IAX_IOSTATE_SCHEDREADY, LOG_NOTICE, signal_condition(), t, and thread.
00927 { 00928 struct iax2_thread *thread = NULL; 00929 static time_t lasterror; 00930 static time_t t; 00931 00932 thread = find_idle_thread(); 00933 00934 if (thread != NULL) { 00935 thread->schedfunc = func; 00936 thread->scheddata = data; 00937 thread->iostate = IAX_IOSTATE_SCHEDREADY; 00938 #ifdef DEBUG_SCHED_MULTITHREAD 00939 ast_copy_string(thread->curfunc, funcname, sizeof(thread->curfunc)); 00940 #endif 00941 signal_condition(&thread->lock, &thread->cond); 00942 return 0; 00943 } 00944 time(&t); 00945 if (t != lasterror) 00946 ast_log(LOG_NOTICE, "Out of idle IAX2 threads for scheduling!\n"); 00947 lasterror = t; 00948 00949 return -1; 00950 }
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 4608 of file chan_iax2.c.
References ast_frame::data, ast_frame::datalen, ast_frame::frametype, iax2_send(), ast_frame::src, and ast_frame::subclass.
Referenced by send_command(), send_command_final(), send_command_immediate(), and send_command_transfer().
04610 { 04611 struct ast_frame f = { 0, }; 04612 04613 f.frametype = type; 04614 f.subclass = command; 04615 f.datalen = datalen; 04616 f.src = __FUNCTION__; 04617 f.data = (void *) data; 04618 04619 return iax2_send(i, &f, ts, seqno, now, transfer, final); 04620 }
static void __send_lagrq | ( | void * | data | ) | [static] |
Definition at line 990 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), IAX_COMMAND_LAGRQ, iaxs, iaxsl, chan_iax2_pvt::lagid, send_command(), and send_lagrq().
Referenced by send_lagrq().
00991 { 00992 int callno = (long)data; 00993 /* Ping only if it's real not if it's bridged */ 00994 ast_mutex_lock(&iaxsl[callno]); 00995 if (iaxs[callno] && iaxs[callno]->lagid != -1) { 00996 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_LAGRQ, 0, NULL, 0, -1); 00997 iaxs[callno]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, data); 00998 } 00999 ast_mutex_unlock(&iaxsl[callno]); 01000 }
static void __send_ping | ( | void * | data | ) | [static] |
Definition at line 956 of file chan_iax2.c.
References AST_FRAME_IAX, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), IAX_COMMAND_PING, iaxs, iaxsl, chan_iax2_pvt::pingid, send_command(), and send_ping().
Referenced by send_ping().
00957 { 00958 int callno = (long)data; 00959 ast_mutex_lock(&iaxsl[callno]); 00960 if (iaxs[callno] && iaxs[callno]->pingid != -1) { 00961 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PING, 0, NULL, 0, -1); 00962 iaxs[callno]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, data); 00963 } 00964 ast_mutex_unlock(&iaxsl[callno]); 00965 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 10246 of file chan_iax2.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_signal(), AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_release(), AST_PTHREADT_NULL, ast_unregister_application(), ast_unregister_switch(), cli_iax2, delete_users(), iax2_destroy(), iax2_switch, iax2_tech, IAX_MAX_CALLS, iax_provision_unload(), iaxactivethreadcount, iaxq, iaxs, iaxsl, ast_firmware_list::lock, papp, sched_context_destroy(), thread, and waresl.
Referenced by load_module(), and unload_module().
10247 { 10248 struct iax2_thread *thread = NULL; 10249 int x; 10250 10251 /* Make sure threads do not hold shared resources when they are canceled */ 10252 10253 /* Grab the sched lock resource to keep it away from threads about to die */ 10254 /* Cancel the network thread, close the net socket */ 10255 if (netthreadid != AST_PTHREADT_NULL) { 10256 AST_LIST_LOCK(&iaxq.queue); 10257 ast_mutex_lock(&sched_lock); 10258 pthread_cancel(netthreadid); 10259 ast_cond_signal(&sched_cond); 10260 ast_mutex_unlock(&sched_lock); /* Release the schedule lock resource */ 10261 AST_LIST_UNLOCK(&iaxq.queue); 10262 pthread_join(netthreadid, NULL); 10263 } 10264 if (schedthreadid != AST_PTHREADT_NULL) { 10265 ast_mutex_lock(&sched_lock); 10266 pthread_cancel(schedthreadid); 10267 ast_cond_signal(&sched_cond); 10268 ast_mutex_unlock(&sched_lock); 10269 pthread_join(schedthreadid, NULL); 10270 } 10271 10272 /* Call for all threads to halt */ 10273 AST_LIST_LOCK(&idle_list); 10274 AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) { 10275 AST_LIST_REMOVE_CURRENT(&idle_list, list); 10276 pthread_cancel(thread->threadid); 10277 } 10278 AST_LIST_TRAVERSE_SAFE_END 10279 AST_LIST_UNLOCK(&idle_list); 10280 10281 AST_LIST_LOCK(&active_list); 10282 AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) { 10283 AST_LIST_REMOVE_CURRENT(&active_list, list); 10284 pthread_cancel(thread->threadid); 10285 } 10286 AST_LIST_TRAVERSE_SAFE_END 10287 AST_LIST_UNLOCK(&active_list); 10288 10289 AST_LIST_LOCK(&dynamic_list); 10290 AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) { 10291 AST_LIST_REMOVE_CURRENT(&dynamic_list, list); 10292 pthread_cancel(thread->threadid); 10293 } 10294 AST_LIST_TRAVERSE_SAFE_END 10295 AST_LIST_UNLOCK(&dynamic_list); 10296 10297 AST_LIST_HEAD_DESTROY(&iaxq.queue); 10298 10299 /* Wait for threads to exit */ 10300 while(0 < iaxactivethreadcount) 10301 usleep(10000); 10302 10303 ast_netsock_release(netsock); 10304 ast_netsock_release(outsock); 10305 for (x=0;x<IAX_MAX_CALLS;x++) 10306 if (iaxs[x]) 10307 iax2_destroy(x); 10308 ast_manager_unregister( "IAXpeers" ); 10309 ast_manager_unregister( "IAXnetstats" ); 10310 ast_unregister_application(papp); 10311 ast_cli_unregister_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 10312 ast_unregister_switch(&iax2_switch); 10313 ast_channel_unregister(&iax2_tech); 10314 delete_users(); 10315 iax_provision_unload(); 10316 sched_context_destroy(sched); 10317 10318 ast_mutex_destroy(&waresl.lock); 10319 10320 for (x = 0; x < IAX_MAX_CALLS; x++) 10321 ast_mutex_destroy(&iaxsl[x]); 10322 10323 return 0; 10324 }
static int apply_context | ( | struct iax2_context * | con, | |
const char * | context | |||
) | [static] |
Definition at line 4653 of file chan_iax2.c.
References iax2_context::context, and iax2_context::next.
Referenced by check_access().
04654 { 04655 while(con) { 04656 if (!strcmp(con->context, context) || !strcmp(con->context, "*")) 04657 return -1; 04658 con = con->next; 04659 } 04660 return 0; 04661 }
static int ast_cli_netstats | ( | struct mansession * | s, | |
int | fd, | |||
int | limit_fmt | |||
) | [static] |
Definition at line 4436 of file chan_iax2.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, astman_append(), jb_info::current, iax_rr::delay, iax_rr::dropped, fmt, jb_info::frames_dropped, jb_info::frames_lost, jb_info::frames_ooo, chan_iax2_pvt::frames_received, IAX_MAX_CALLS, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), iax_rr::jitter, jb_info::jitter, iax_rr::losscnt, iax_rr::losspct, jb_info::losspct, jb_info::min, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::pingtime, and chan_iax2_pvt::remote_rr.
Referenced by iax2_show_netstats(), and manager_iax2_show_netstats().
04437 { 04438 int x; 04439 int numchans = 0; 04440 for (x=0;x<IAX_MAX_CALLS;x++) { 04441 ast_mutex_lock(&iaxsl[x]); 04442 if (iaxs[x]) { 04443 int localjitter, localdelay, locallost, locallosspct, localdropped, localooo; 04444 char *fmt; 04445 jb_info jbinfo; 04446 04447 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04448 jb_getinfo(iaxs[x]->jb, &jbinfo); 04449 localjitter = jbinfo.jitter; 04450 localdelay = jbinfo.current - jbinfo.min; 04451 locallost = jbinfo.frames_lost; 04452 locallosspct = jbinfo.losspct/1000; 04453 localdropped = jbinfo.frames_dropped; 04454 localooo = jbinfo.frames_ooo; 04455 } else { 04456 localjitter = -1; 04457 localdelay = 0; 04458 locallost = -1; 04459 locallosspct = -1; 04460 localdropped = 0; 04461 localooo = -1; 04462 } 04463 if (limit_fmt) 04464 fmt = "%-25.25s %4d %4d %4d %5d %3d %5d %4d %6d %4d %4d %5d %3d %5d %4d %6d\n"; 04465 else 04466 fmt = "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"; 04467 if (s) 04468 04469 astman_append(s, fmt, 04470 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04471 iaxs[x]->pingtime, 04472 localjitter, 04473 localdelay, 04474 locallost, 04475 locallosspct, 04476 localdropped, 04477 localooo, 04478 iaxs[x]->frames_received/1000, 04479 iaxs[x]->remote_rr.jitter, 04480 iaxs[x]->remote_rr.delay, 04481 iaxs[x]->remote_rr.losscnt, 04482 iaxs[x]->remote_rr.losspct, 04483 iaxs[x]->remote_rr.dropped, 04484 iaxs[x]->remote_rr.ooo, 04485 iaxs[x]->remote_rr.packets/1000); 04486 else 04487 ast_cli(fd, fmt, 04488 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04489 iaxs[x]->pingtime, 04490 localjitter, 04491 localdelay, 04492 locallost, 04493 locallosspct, 04494 localdropped, 04495 localooo, 04496 iaxs[x]->frames_received/1000, 04497 iaxs[x]->remote_rr.jitter, 04498 iaxs[x]->remote_rr.delay, 04499 iaxs[x]->remote_rr.losscnt, 04500 iaxs[x]->remote_rr.losspct, 04501 iaxs[x]->remote_rr.dropped, 04502 iaxs[x]->remote_rr.ooo, 04503 iaxs[x]->remote_rr.packets/1000 04504 ); 04505 numchans++; 04506 } 04507 ast_mutex_unlock(&iaxsl[x]); 04508 } 04509 return numchans; 04510 }
static struct ast_channel* ast_iax2_new | ( | int | callno, | |
int | state, | |||
int | capability | |||
) | [static, read] |
Create new call, interface with the PBX core.
Definition at line 3345 of file chan_iax2.c.
References chan_iax2_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, chan_iax2_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_string_field_set, ast_strlen_zero(), chan_iax2_pvt::calling_pres, chan_iax2_pvt::calling_tns, chan_iax2_pvt::calling_ton, chan_iax2_pvt::callno, CALLNO_TO_PTR, chan_iax2_pvt::capability, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, iax2_tech, iaxs, iaxsl, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), chan_iax2_pvt::peeradsicpe, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, chan_iax2_pvt::vars, and ast_channel::writeformat.
Referenced by iax2_request(), and socket_process().
03346 { 03347 struct ast_channel *tmp; 03348 struct chan_iax2_pvt *i; 03349 struct ast_variable *v = NULL; 03350 03351 if (!(i = iaxs[callno])) { 03352 ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno); 03353 return NULL; 03354 } 03355 03356 /* Don't hold call lock */ 03357 ast_mutex_unlock(&iaxsl[callno]); 03358 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); 03359 ast_mutex_lock(&iaxsl[callno]); 03360 if (!tmp) 03361 return NULL; 03362 tmp->tech = &iax2_tech; 03363 /* We can support any format by default, until we get restricted */ 03364 tmp->nativeformats = capability; 03365 tmp->readformat = ast_best_codec(capability); 03366 tmp->writeformat = ast_best_codec(capability); 03367 tmp->tech_pvt = CALLNO_TO_PTR(i->callno); 03368 03369 /* Don't use ast_set_callerid() here because it will 03370 * generate a NewCallerID event before the NewChannel event */ 03371 tmp->cid.cid_num = ast_strdup(i->cid_num); 03372 tmp->cid.cid_name = ast_strdup(i->cid_name); 03373 if (!ast_strlen_zero(i->ani)) 03374 tmp->cid.cid_ani = ast_strdup(i->ani); 03375 else 03376 tmp->cid.cid_ani = ast_strdup(i->cid_num); 03377 tmp->cid.cid_dnid = ast_strdup(i->dnid); 03378 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 03379 tmp->cid.cid_pres = i->calling_pres; 03380 tmp->cid.cid_ton = i->calling_ton; 03381 tmp->cid.cid_tns = i->calling_tns; 03382 if (!ast_strlen_zero(i->language)) 03383 ast_string_field_set(tmp, language, i->language); 03384 if (!ast_strlen_zero(i->accountcode)) 03385 ast_string_field_set(tmp, accountcode, i->accountcode); 03386 if (i->amaflags) 03387 tmp->amaflags = i->amaflags; 03388 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 03389 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 03390 if (i->adsi) 03391 tmp->adsicpe = i->peeradsicpe; 03392 else 03393 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 03394 i->owner = tmp; 03395 i->capability = capability; 03396 03397 for (v = i->vars ; v ; v = v->next) 03398 pbx_builtin_setvar_helper(tmp, v->name, v->value); 03399 03400 if (state != AST_STATE_DOWN) { 03401 if (ast_pbx_start(tmp)) { 03402 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 03403 ast_hangup(tmp); 03404 i->owner = NULL; 03405 return NULL; 03406 } 03407 } 03408 03409 ast_module_ref(ast_module_info->self); 03410 03411 return tmp; 03412 }
static AST_LIST_HEAD_STATIC | ( | dynamic_list | , | |
iax2_thread | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | active_list | , | |
iax2_thread | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | idle_list | , | |
iax2_thread | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | peers | , | |
iax2_peer | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | users | , | |
iax2_user | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | registrations | , | |
iax2_registry | ||||
) | [static] |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"Inter Asterisk eXchange (Ver 2)" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
AST_MUTEX_DEFINE_STATIC | ( | dpcache_lock | ) |
AST_MUTEX_DEFINE_STATIC | ( | tpeerlock | ) |
AST_MUTEX_DEFINE_STATIC | ( | sched_lock | ) |
static int attempt_transmit | ( | void * | data | ) | [static] |
Definition at line 1955 of file chan_iax2.c.
References __attempt_transmit(), and schedule_action.
Referenced by __attempt_transmit(), and network_thread().
01956 { 01957 #ifdef SCHED_MULTITHREADED 01958 if (schedule_action(__attempt_transmit, data)) 01959 #endif 01960 __attempt_transmit(data); 01961 return 0; 01962 }
static int auth_fail | ( | int | callno, | |
int | failcode | |||
) | [static] |
Definition at line 5876 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), auth_reject(), chan_iax2_pvt::authfail, chan_iax2_pvt::authid, iaxs, and iaxsl.
Referenced by socket_process().
05877 { 05878 /* Schedule sending the authentication failure in one second, to prevent 05879 guessing */ 05880 ast_mutex_lock(&iaxsl[callno]); 05881 if (iaxs[callno]) { 05882 iaxs[callno]->authfail = failcode; 05883 if (delayreject) { 05884 if (iaxs[callno]->authid > -1) 05885 ast_sched_del(sched, iaxs[callno]->authid); 05886 iaxs[callno]->authid = ast_sched_add(sched, 1000, auth_reject, (void *)(long)callno); 05887 } else 05888 auth_reject((void *)(long)callno); 05889 } 05890 ast_mutex_unlock(&iaxsl[callno]); 05891 return 0; 05892 }
static int auth_reject | ( | void * | data | ) | [static] |
Definition at line 5862 of file chan_iax2.c.
References __auth_reject(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::authid, iaxs, iaxsl, and schedule_action.
Referenced by auth_fail().
05863 { 05864 int callno = (int)(long)(data); 05865 ast_mutex_lock(&iaxsl[callno]); 05866 if (iaxs[callno]) 05867 iaxs[callno]->authid = -1; 05868 ast_mutex_unlock(&iaxsl[callno]); 05869 #ifdef SCHED_MULTITHREADED 05870 if (schedule_action(__auth_reject, data)) 05871 #endif 05872 __auth_reject(data); 05873 return 0; 05874 }
static int authenticate | ( | const char * | challenge, | |
const char * | secret, | |||
const char * | keyn, | |||
int | authmethods, | |||
struct iax_ie_data * | ied, | |||
struct sockaddr_in * | sin, | |||
aes_encrypt_ctx * | ecx, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 5171 of file chan_iax2.c.
References ast_inet_ntoa(), ast_key_get, AST_KEY_PRIVATE, ast_log(), ast_sign, ast_strlen_zero(), build_enc_keys(), IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, iax_ie_append_str(), IAX_IE_MD5_RESULT, IAX_IE_PASSWORD, IAX_IE_RSA_RESULT, key(), LOG_NOTICE, MD5Final(), MD5Init(), and MD5Update().
05172 { 05173 int res = -1; 05174 int x; 05175 if (!ast_strlen_zero(keyn)) { 05176 if (!(authmethods & IAX_AUTH_RSA)) { 05177 if (ast_strlen_zero(secret)) 05178 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)); 05179 } else if (ast_strlen_zero(challenge)) { 05180 ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", ast_inet_ntoa(sin->sin_addr)); 05181 } else { 05182 char sig[256]; 05183 struct ast_key *key; 05184 key = ast_key_get(keyn, AST_KEY_PRIVATE); 05185 if (!key) { 05186 ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn); 05187 } else { 05188 if (ast_sign(key, (char*)challenge, sig)) { 05189 ast_log(LOG_NOTICE, "Unable to sign challenge with key\n"); 05190 res = -1; 05191 } else { 05192 iax_ie_append_str(ied, IAX_IE_RSA_RESULT, sig); 05193 res = 0; 05194 } 05195 } 05196 } 05197 } 05198 /* Fall back */ 05199 if (res && !ast_strlen_zero(secret)) { 05200 if ((authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(challenge)) { 05201 struct MD5Context md5; 05202 unsigned char digest[16]; 05203 char digres[128]; 05204 MD5Init(&md5); 05205 MD5Update(&md5, (unsigned char *)challenge, strlen(challenge)); 05206 MD5Update(&md5, (unsigned char *)secret, strlen(secret)); 05207 MD5Final(digest, &md5); 05208 /* If they support md5, authenticate with it. */ 05209 for (x=0;x<16;x++) 05210 sprintf(digres + (x << 1), "%2.2x", digest[x]); /* safe */ 05211 if (ecx && dcx) 05212 build_enc_keys(digest, ecx, dcx); 05213 iax_ie_append_str(ied, IAX_IE_MD5_RESULT, digres); 05214 res = 0; 05215 } else if (authmethods & IAX_AUTH_PLAINTEXT) { 05216 iax_ie_append_str(ied, IAX_IE_PASSWORD, secret); 05217 res = 0; 05218 } else 05219 ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %d)\n", ast_inet_ntoa(sin->sin_addr), authmethods); 05220 } 05221 return res; 05222 }
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 5224 of file chan_iax2.c.
References iax2_peer::addr, AST_FRAME_IAX, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_set_flag, ast_string_field_set, ast_strlen_zero(), ast_test_flag, authenticate(), iax_ies::authmethods, iax_ie_data::buf, iax_ies::challenge, chan_iax2_pvt::dcx, destroy_peer(), chan_iax2_pvt::ecx, chan_iax2_pvt::encmethods, iax_ies::encmethods, IAX_AUTH_MD5, IAX_COMMAND_AUTHREP, IAX_ENCRYPTED, IAX_KEYPOPULATED, IAX_TEMPONLY, iax2_peer::mask, merge_encryption(), iax_ie_data::pos, realtime_peer(), send_command(), and iax_ies::username.
Referenced by socket_process().
05225 { 05226 struct iax2_peer *peer = NULL; 05227 /* Start pessimistic */ 05228 int res = -1; 05229 int authmethods = 0; 05230 struct iax_ie_data ied; 05231 05232 memset(&ied, 0, sizeof(ied)); 05233 05234 if (ies->username) 05235 ast_string_field_set(p, username, ies->username); 05236 if (ies->challenge) 05237 ast_string_field_set(p, challenge, ies->challenge); 05238 if (ies->authmethods) 05239 authmethods = ies->authmethods; 05240 if (authmethods & IAX_AUTH_MD5) 05241 merge_encryption(p, ies->encmethods); 05242 else 05243 p->encmethods = 0; 05244 05245 /* Check for override RSA authentication first */ 05246 if (!ast_strlen_zero(override) || !ast_strlen_zero(okey)) { 05247 /* Normal password authentication */ 05248 res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05249 } else { 05250 AST_LIST_LOCK(&peers); 05251 AST_LIST_TRAVERSE(&peers, peer, entry) { 05252 if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 05253 /* No peer specified at our end, or this is the peer */ 05254 && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username))) 05255 /* No username specified in peer rule, or this is the right username */ 05256 && (!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))) 05257 /* No specified host, or this is our host */ 05258 ) { 05259 res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05260 if (!res) 05261 break; 05262 } 05263 } 05264 AST_LIST_UNLOCK(&peers); 05265 if (!peer) { 05266 /* We checked our list and didn't find one. It's unlikely, but possible, 05267 that we're trying to authenticate *to* a realtime peer */ 05268 if ((peer = realtime_peer(p->peer, NULL))) { 05269 res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx); 05270 if (ast_test_flag(peer, IAX_TEMPONLY)) 05271 destroy_peer(peer); 05272 } 05273 } 05274 } 05275 if (ies->encmethods) 05276 ast_set_flag(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); 05277 if (!res) 05278 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREP, 0, ied.buf, ied.pos, -1); 05279 return res; 05280 }
static int authenticate_request | ( | struct chan_iax2_pvt * | p | ) | [static] |
Definition at line 4896 of file chan_iax2.c.
References AST_CAUSE_CALL_REJECTED, AST_FRAME_IAX, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_random(), ast_set_flag, ast_string_field_set, ast_test_flag, chan_iax2_pvt::authmethods, iax_ie_data::buf, iax2_user::curauthreq, chan_iax2_pvt::encmethods, IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_AUTHREQ, IAX_COMMAND_REJECT, IAX_ENCRYPTED, iax_ie_append_byte(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_ENCRYPTION, IAX_IE_USERNAME, IAX_MAXAUTHREQ, iax2_user::maxauthreq, iax_ie_data::pos, send_command(), and send_command_final().
Referenced by socket_process().
04897 { 04898 struct iax2_user *user = NULL; 04899 struct iax_ie_data ied; 04900 int res = -1, authreq_restrict = 0; 04901 char challenge[10]; 04902 04903 memset(&ied, 0, sizeof(ied)); 04904 04905 /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */ 04906 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 04907 AST_LIST_LOCK(&users); 04908 AST_LIST_TRAVERSE(&users, user, entry) { 04909 if (!strcmp(user->name, p->username)) { 04910 if (user->curauthreq == user->maxauthreq) 04911 authreq_restrict = 1; 04912 else 04913 user->curauthreq++; 04914 break; 04915 } 04916 } 04917 AST_LIST_UNLOCK(&users); 04918 } 04919 04920 /* If the AUTHREQ limit test failed, send back an error */ 04921 if (authreq_restrict) { 04922 iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached"); 04923 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED); 04924 send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1); 04925 return 0; 04926 } 04927 04928 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 04929 if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) { 04930 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 04931 ast_string_field_set(p, challenge, challenge); 04932 /* snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random()); */ 04933 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge); 04934 } 04935 if (p->encmethods) 04936 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods); 04937 04938 iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username); 04939 04940 res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1); 04941 04942 if (p->encmethods) 04943 ast_set_flag(p, IAX_ENCRYPTED); 04944 04945 return res; 04946 }
static int authenticate_verify | ( | struct chan_iax2_pvt * | p, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 4948 of file chan_iax2.c.
References ast_check_signature, ast_clear_flag, ast_key_get, AST_KEY_PUBLIC, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, chan_iax2_pvt::authmethods, iax2_user::curauthreq, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_MAXAUTHREQ, IAX_STATE_AUTHENTICATED, key(), LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::rsa_result, secret, chan_iax2_pvt::state, and strsep().
Referenced by socket_process().
04949 { 04950 char requeststr[256]; 04951 char md5secret[256] = ""; 04952 char secret[256] = ""; 04953 char rsasecret[256] = ""; 04954 int res = -1; 04955 int x; 04956 struct iax2_user *user = NULL; 04957 04958 AST_LIST_LOCK(&users); 04959 AST_LIST_TRAVERSE(&users, user, entry) { 04960 if (!strcmp(user->name, p->username)) 04961 break; 04962 } 04963 if (user) { 04964 if (ast_test_flag(p, IAX_MAXAUTHREQ)) { 04965 user->curauthreq--; 04966 ast_clear_flag(p, IAX_MAXAUTHREQ); 04967 } 04968 ast_string_field_set(p, host, user->name); 04969 } 04970 AST_LIST_UNLOCK(&users); 04971 04972 if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED)) 04973 return res; 04974 if (ies->password) 04975 ast_copy_string(secret, ies->password, sizeof(secret)); 04976 if (ies->md5_result) 04977 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 04978 if (ies->rsa_result) 04979 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 04980 if ((p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(rsasecret) && !ast_strlen_zero(p->inkeys)) { 04981 struct ast_key *key; 04982 char *keyn; 04983 char tmpkey[256]; 04984 char *stringp=NULL; 04985 ast_copy_string(tmpkey, p->inkeys, sizeof(tmpkey)); 04986 stringp=tmpkey; 04987 keyn = strsep(&stringp, ":"); 04988 while(keyn) { 04989 key = ast_key_get(keyn, AST_KEY_PUBLIC); 04990 if (key && !ast_check_signature(key, p->challenge, rsasecret)) { 04991 res = 0; 04992 break; 04993 } else if (!key) 04994 ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn); 04995 keyn = strsep(&stringp, ":"); 04996 } 04997 } else if (p->authmethods & IAX_AUTH_MD5) { 04998 struct MD5Context md5; 04999 unsigned char digest[16]; 05000 char *tmppw, *stringp; 05001 05002 tmppw = ast_strdupa(p->secret); 05003 stringp = tmppw; 05004 while((tmppw = strsep(&stringp, ";"))) { 05005 MD5Init(&md5); 05006 MD5Update(&md5, (unsigned char *)p->challenge, strlen(p->challenge)); 05007 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05008 MD5Final(digest, &md5); 05009 /* If they support md5, authenticate with it. */ 05010 for (x=0;x<16;x++) 05011 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05012 if (!strcasecmp(requeststr, md5secret)) { 05013 res = 0; 05014 break; 05015 } 05016 } 05017 } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { 05018 if (!strcmp(secret, p->secret)) 05019 res = 0; 05020 } 05021 return res; 05022 }
static int auto_congest | ( | void * | data | ) | [static] |
Definition at line 2773 of file chan_iax2.c.
References __auto_congest(), and schedule_action.
Referenced by iax2_call(), and sip_call().
02774 { 02775 #ifdef SCHED_MULTITHREADED 02776 if (schedule_action(__auto_congest, data)) 02777 #endif 02778 __auto_congest(data); 02779 return 0; 02780 }
static int auto_hangup | ( | void * | data | ) | [static] |
Definition at line 5909 of file chan_iax2.c.
References __auto_hangup(), ast_mutex_lock(), ast_mutex_unlock(), chan_iax2_pvt::autoid, iaxs, iaxsl, and schedule_action.
Referenced by iax2_dprequest(), and iax2_provision().
05910 { 05911 int callno = (int)(long)(data); 05912 ast_mutex_lock(&iaxsl[callno]); 05913 if (iaxs[callno]) { 05914 iaxs[callno]->autoid = -1; 05915 } 05916 ast_mutex_unlock(&iaxsl[callno]); 05917 #ifdef SCHED_MULTITHREADED 05918 if (schedule_action(__auto_hangup, data)) 05919 #endif 05920 __auto_hangup(data); 05921 return 0; 05922 }
static struct iax2_context* build_context | ( | char * | context | ) | [static, read] |
Definition at line 8444 of file chan_iax2.c.
References ast_calloc, and iax2_context::context.
Referenced by build_user().
08445 { 08446 struct iax2_context *con; 08447 08448 if ((con = ast_calloc(1, sizeof(*con)))) 08449 ast_copy_string(con->context, context, sizeof(con->context)); 08450 08451 return con; 08452 }
static void build_enc_keys | ( | const unsigned char * | digest, | |
aes_encrypt_ctx * | ecx, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 3706 of file chan_iax2.c.
References aes_decrypt_key128(), and aes_encrypt_key128().
Referenced by authenticate(), and decrypt_frame().
03707 { 03708 aes_encrypt_key128(digest, ecx); 03709 aes_decrypt_key128(digest, dcx); 03710 }
static struct iax2_peer * build_peer | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static, read] |
Create peer structure based on configuration.
Definition at line 8569 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_clear_flag, ast_copy_flags, ast_dnsmgr_lookup(), ast_free_ha(), ast_get_ip(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_parse_allow_disallow(), ast_sched_del(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_string_field_free_pools, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), iax2_peer::authmethods, iax2_peer::capability, cid_name, cid_num, iax2_peer::defaddr, DEFAULT_FREQ_NOTOK, DEFAULT_FREQ_OK, DEFAULT_MAXMS, iax2_peer::dnsmgr, iax2_peer::encmethods, iax2_peer::expire, iax2_peer::expiry, free, get_auth_methods(), get_encrypt_methods(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_DEFAULT_PORTNO, IAX_DELME, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mailbox, iax2_peer::mask, iax2_peer::maxms, ast_variable::name, ast_variable::next, peer_set_srcaddr(), iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_user::prefs, iax2_peer::prefs, secret, iax2_peer::smoothing, iax2_peer::sockfd, and ast_variable::value.
08570 { 08571 struct iax2_peer *peer = NULL; 08572 struct ast_ha *oldha = NULL; 08573 int maskfound=0; 08574 int found=0; 08575 int firstpass=1; 08576 08577 AST_LIST_LOCK(&peers); 08578 if (!temponly) { 08579 AST_LIST_TRAVERSE(&peers, peer, entry) { 08580 if (!strcmp(peer->name, name)) { 08581 if (!ast_test_flag(peer, IAX_DELME)) 08582 firstpass = 0; 08583 break; 08584 } 08585 } 08586 } else 08587 peer = NULL; 08588 if (peer) { 08589 found++; 08590 if (firstpass) { 08591 oldha = peer->ha; 08592 peer->ha = NULL; 08593 } 08594 AST_LIST_REMOVE(&peers, peer, entry); 08595 AST_LIST_UNLOCK(&peers); 08596 } else { 08597 AST_LIST_UNLOCK(&peers); 08598 if ((peer = ast_calloc(1, sizeof(*peer)))) { 08599 peer->expire = -1; 08600 peer->pokeexpire = -1; 08601 peer->sockfd = defaultsockfd; 08602 if (ast_string_field_init(peer, 32)) { 08603 free(peer); 08604 peer = NULL; 08605 } 08606 } 08607 } 08608 if (peer) { 08609 if (firstpass) { 08610 ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 08611 peer->encmethods = iax2_encryption; 08612 peer->adsi = adsi; 08613 ast_string_field_set(peer,secret,""); 08614 if (!found) { 08615 ast_string_field_set(peer, name, name); 08616 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 08617 peer->expiry = min_reg_expire; 08618 } 08619 peer->prefs = prefs; 08620 peer->capability = iax2_capability; 08621 peer->smoothing = 0; 08622 peer->pokefreqok = DEFAULT_FREQ_OK; 08623 peer->pokefreqnotok = DEFAULT_FREQ_NOTOK; 08624 ast_string_field_set(peer,context,""); 08625 ast_string_field_set(peer,peercontext,""); 08626 ast_clear_flag(peer, IAX_HASCALLERID); 08627 ast_string_field_set(peer, cid_name, ""); 08628 ast_string_field_set(peer, cid_num, ""); 08629 } 08630 08631 if (!v) { 08632 v = alt; 08633 alt = NULL; 08634 } 08635 while(v) { 08636 if (!strcasecmp(v->name, "secret")) { 08637 ast_string_field_set(peer, secret, v->value); 08638 } else if (!strcasecmp(v->name, "mailbox")) { 08639 ast_string_field_set(peer, mailbox, v->value); 08640 } else if (!strcasecmp(v->name, "mohinterpret")) { 08641 ast_string_field_set(peer, mohinterpret, v->value); 08642 } else if (!strcasecmp(v->name, "mohsuggest")) { 08643 ast_string_field_set(peer, mohsuggest, v->value); 08644 } else if (!strcasecmp(v->name, "dbsecret")) { 08645 ast_string_field_set(peer, dbsecret, v->value); 08646 } else if (!strcasecmp(v->name, "trunk")) { 08647 ast_set2_flag(peer, ast_true(v->value), IAX_TRUNK); 08648 if (ast_test_flag(peer, IAX_TRUNK) && (timingfd < 0)) { 08649 ast_log(LOG_WARNING, "Unable to support trunking on peer '%s' without zaptel timing\n", peer->name); 08650 ast_clear_flag(peer, IAX_TRUNK); 08651 } 08652 } else if (!strcasecmp(v->name, "auth")) { 08653 peer->authmethods = get_auth_methods(v->value); 08654 } else if (!strcasecmp(v->name, "encryption")) { 08655 peer->encmethods = get_encrypt_methods(v->value); 08656 } else if (!strcasecmp(v->name, "notransfer")) { 08657 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 08658 ast_clear_flag(peer, IAX_TRANSFERMEDIA); 08659 ast_set2_flag(peer, ast_true(v->value), IAX_NOTRANSFER); 08660 } else if (!strcasecmp(v->name, "transfer")) { 08661 if (!strcasecmp(v->value, "mediaonly")) { 08662 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 08663 } else if (ast_true(v->value)) { 08664 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 08665 } else 08666 ast_set_flags_to(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 08667 } else if (!strcasecmp(v->name, "jitterbuffer")) { 08668 ast_set2_flag(peer, ast_true(v->value), IAX_USEJITTERBUF); 08669 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 08670 ast_set2_flag(peer, ast_true(v->value), IAX_FORCEJITTERBUF); 08671 } else if (!strcasecmp(v->name, "host")) { 08672 if (!strcasecmp(v->value, "dynamic")) { 08673 /* They'll register with us */ 08674 ast_set_flag(peer, IAX_DYNAMIC); 08675 if (!found) { 08676 /* Initialize stuff iff we're not found, otherwise 08677 we keep going with what we had */ 08678 memset(&peer->addr.sin_addr, 0, 4); 08679 if (peer->addr.sin_port) { 08680 /* If we've already got a port, make it the default rather than absolute */ 08681 peer->defaddr.sin_port = peer->addr.sin_port; 08682 peer->addr.sin_port = 0; 08683 } 08684 } 08685 } else { 08686 /* Non-dynamic. Make sure we become that way if we're not */ 08687 if (peer->expire > -1) 08688 ast_sched_del(sched, peer->expire); 08689 peer->expire = -1; 08690 ast_clear_flag(peer, IAX_DYNAMIC); 08691 if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) { 08692 ast_string_field_free_pools(peer); 08693 free(peer); 08694 return NULL; 08695 } 08696 if (!peer->addr.sin_port) 08697 peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); 08698 } 08699 if (!maskfound) 08700 inet_aton("255.255.255.255", &peer->mask); 08701 } else if (!strcasecmp(v->name, "defaultip")) { 08702 if (ast_get_ip(&peer->defaddr, v->value)) { 08703 ast_string_field_free_pools(peer); 08704 free(peer); 08705 return NULL; 08706 } 08707 } else if (!strcasecmp(v->name, "sourceaddress")) { 08708 peer_set_srcaddr(peer, v->value); 08709 } else if (!strcasecmp(v->name, "permit") || 08710 !strcasecmp(v->name, "deny")) { 08711 peer->ha = ast_append_ha(v->name, v->value, peer->ha); 08712 } else if (!strcasecmp(v->name, "mask")) { 08713 maskfound++; 08714 inet_aton(v->value, &peer->mask); 08715 } else if (!strcasecmp(v->name, "context")) { 08716 ast_string_field_set(peer, context, v->value); 08717 } else if (!strcasecmp(v->name, "regexten")) { 08718 ast_string_field_set(peer, regexten, v->value); 08719 } else if (!strcasecmp(v->name, "peercontext")) { 08720 ast_string_field_set(peer, peercontext, v->value); 08721 } else if (!strcasecmp(v->name, "port")) { 08722 if (ast_test_flag(peer, IAX_DYNAMIC)) 08723 peer->defaddr.sin_port = htons(atoi(v->value)); 08724 else 08725 peer->addr.sin_port = htons(atoi(v->value)); 08726 } else if (!strcasecmp(v->name, "username")) { 08727 ast_string_field_set(peer, username, v->value); 08728 } else if (!strcasecmp(v->name, "allow")) { 08729 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1); 08730 } else if (!strcasecmp(v->name, "disallow")) { 08731 ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0); 08732 } else if (!strcasecmp(v->name, "callerid")) { 08733 if (!ast_strlen_zero(v->value)) { 08734 char name2[80]; 08735 char num2[80]; 08736 ast_callerid_split(v->value, name2, 80, num2, 80); 08737 ast_string_field_set(peer, cid_name, name2); 08738 ast_string_field_set(peer, cid_num, num2); 08739 ast_set_flag(peer, IAX_HASCALLERID); 08740 } else { 08741 ast_clear_flag(peer, IAX_HASCALLERID); 08742 ast_string_field_set(peer, cid_name, ""); 08743 ast_string_field_set(peer, cid_num, ""); 08744 } 08745 } else if (!strcasecmp(v->name, "fullname")) { 08746 if (!ast_strlen_zero(v->value)) { 08747 ast_string_field_set(peer, cid_name, v->value); 08748 ast_set_flag(peer, IAX_HASCALLERID); 08749 } else { 08750 ast_string_field_set(peer, cid_name, ""); 08751 if (ast_strlen_zero(peer->cid_num)) 08752 ast_clear_flag(peer, IAX_HASCALLERID); 08753 } 08754 } else if (!strcasecmp(v->name, "cid_number")) { 08755 if (!ast_strlen_zero(v->value)) { 08756 ast_string_field_set(peer, cid_num, v->value); 08757 ast_set_flag(peer, IAX_HASCALLERID); 08758 } else { 08759 ast_string_field_set(peer, cid_num, ""); 08760 if (ast_strlen_zero(peer->cid_name)) 08761 ast_clear_flag(peer, IAX_HASCALLERID); 08762 } 08763 } else if (!strcasecmp(v->name, "sendani")) { 08764 ast_set2_flag(peer, ast_true(v->value), IAX_SENDANI); 08765 } else if (!strcasecmp(v->name, "inkeys")) { 08766 ast_string_field_set(peer, inkeys, v->value); 08767 } else if (!strcasecmp(v->name, "outkey")) { 08768 ast_string_field_set(peer, outkey, v->value); 08769 } else if (!strcasecmp(v->name, "qualify")) { 08770 if (!strcasecmp(v->value, "no")) { 08771 peer->maxms = 0; 08772 } else if (!strcasecmp(v->value, "yes")) { 08773 peer->maxms = DEFAULT_MAXMS; 08774 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 08775 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); 08776 peer->maxms = 0; 08777 } 08778 } else if (!strcasecmp(v->name, "qualifysmoothing")) { 08779 peer->smoothing = ast_true(v->value); 08780 } else if (!strcasecmp(v->name, "qualifyfreqok")) { 08781 if (sscanf(v->value, "%d", &peer->pokefreqok) != 1) { 08782 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); 08783 } 08784 } else if (!strcasecmp(v->name, "qualifyfreqnotok")) { 08785 if (sscanf(v->value, "%d", &peer->pokefreqnotok) != 1) { 08786 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); 08787 } else ast_log(LOG_WARNING, "Set peer->pokefreqnotok to %d\n", peer->pokefreqnotok); 08788 } else if (!strcasecmp(v->name, "timezone")) { 08789 ast_string_field_set(peer, zonetag, v->value); 08790 } else if (!strcasecmp(v->name, "adsi")) { 08791 peer->adsi = ast_true(v->value); 08792 }/* else if (strcasecmp(v->name,"type")) */ 08793 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 08794 v = v->next; 08795 if (!v) { 08796 v = alt; 08797 alt = NULL; 08798 } 08799 } 08800 if (!peer->authmethods) 08801 peer->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 08802 ast_clear_flag(peer, IAX_DELME); 08803 /* Make sure these are IPv4 addresses */ 08804 peer->addr.sin_family = AF_INET; 08805 } 08806 if (oldha) 08807 ast_free_ha(oldha); 08808 return peer; 08809 }
static struct iax2_user * build_user | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | temponly | |||
) | [static, read] |
Create in-memory user structure from configuration.
Definition at line 8812 of file chan_iax2.c.
References iax2_user::adsi, iax2_user::amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_clear_flag, ast_copy_flags, ast_free_ha(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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_pools, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_new(), iax2_user::authmethods, build_context(), iax2_user::capability, cid_name, cid_num, iax2_user::contexts, iax2_user::curauthreq, iax2_user::encmethods, format, free, free_context(), get_auth_methods(), get_encrypt_methods(), iax2_user::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DELME, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, iax2_context::next, iax2_user::prefs, secret, ast_variable::value, and iax2_user::vars.
08813 { 08814 struct iax2_user *user = NULL; 08815 struct iax2_context *con, *conl = NULL; 08816 struct ast_ha *oldha = NULL; 08817 struct iax2_context *oldcon = NULL; 08818 int format; 08819 int firstpass=1; 08820 int oldcurauthreq = 0; 08821 char *varname = NULL, *varval = NULL; 08822 struct ast_variable *tmpvar = NULL; 08823 08824 AST_LIST_LOCK(&users); 08825 if (!temponly) { 08826 AST_LIST_TRAVERSE(&users, user, entry) { 08827 if (!strcmp(user->name, name)) { 08828 if (!ast_test_flag(user, IAX_DELME)) 08829 firstpass = 0; 08830 break; 08831 } 08832 } 08833 } else 08834 user = NULL; 08835 08836 if (user) { 08837 if (firstpass) { 08838 oldcurauthreq = user->curauthreq; 08839 oldha = user->ha; 08840 oldcon = user->contexts; 08841 user->ha = NULL; 08842 user->contexts = NULL; 08843 } 08844 /* Already in the list, remove it and it will be added back (or FREE'd) */ 08845 AST_LIST_REMOVE(&users, user, entry); 08846 AST_LIST_UNLOCK(&users); 08847 } else { 08848 AST_LIST_UNLOCK(&users); 08849 /* This is going to memset'd to 0 in the next block */ 08850 user = ast_calloc(sizeof(*user),1); 08851 } 08852 08853 if (user) { 08854 if (firstpass) { 08855 ast_string_field_free_pools(user); 08856 memset(user, 0, sizeof(struct iax2_user)); 08857 if (ast_string_field_init(user, 32)) { 08858 free(user); 08859 user = NULL; 08860 } 08861 user->maxauthreq = maxauthreq; 08862 user->curauthreq = oldcurauthreq; 08863 user->prefs = prefs; 08864 user->capability = iax2_capability; 08865 user->encmethods = iax2_encryption; 08866 user->adsi = adsi; 08867 ast_string_field_set(user, name, name); 08868 ast_string_field_set(user, language, language); 08869 ast_copy_flags(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP); 08870 ast_clear_flag(user, IAX_HASCALLERID); 08871 ast_string_field_set(user, cid_name, ""); 08872 ast_string_field_set(user, cid_num, ""); 08873 } 08874 if (!v) { 08875 v = alt; 08876 alt = NULL; 08877 } 08878 while(v) { 08879 if (!strcasecmp(v->name, "context")) { 08880 con = build_context(v->value); 08881 if (con) { 08882 if (conl) 08883 conl->next = con; 08884 else 08885 user->contexts = con; 08886 conl = con; 08887 } 08888 } else if (!strcasecmp(v->name, "permit") || 08889 !strcasecmp(v->name, "deny")) { 08890 user->ha = ast_append_ha(v->name, v->value, user->ha); 08891 } else if (!strcasecmp(v->name, "setvar")) { 08892 varname = ast_strdupa(v->value); 08893 if (varname && (varval = strchr(varname,'='))) { 08894 *varval = '\0'; 08895 varval++; 08896 if((tmpvar = ast_variable_new(varname, varval))) { 08897 tmpvar->next = user->vars; 08898 user->vars = tmpvar; 08899 } 08900 } 08901 } else if (!strcasecmp(v->name, "allow")) { 08902 ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1); 08903 } else if (!strcasecmp(v->name, "disallow")) { 08904 ast_parse_allow_disallow(&user->prefs, &user->capability,v->value, 0); 08905 } else if (!strcasecmp(v->name, "trunk")) { 08906 ast_set2_flag(user, ast_true(v->value), IAX_TRUNK); 08907 if (ast_test_flag(user, IAX_TRUNK) && (timingfd < 0)) { 08908 ast_log(LOG_WARNING, "Unable to support trunking on user '%s' without zaptel timing\n", user->name); 08909 ast_clear_flag(user, IAX_TRUNK); 08910 } 08911 } else if (!strcasecmp(v->name, "auth")) { 08912 user->authmethods = get_auth_methods(v->value); 08913 } else if (!strcasecmp(v->name, "encryption")) { 08914 user->encmethods = get_encrypt_methods(v->value); 08915 } else if (!strcasecmp(v->name, "notransfer")) { 08916 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 08917 ast_clear_flag(user, IAX_TRANSFERMEDIA); 08918 ast_set2_flag(user, ast_true(v->value), IAX_NOTRANSFER); 08919 } else if (!strcasecmp(v->name, "transfer")) { 08920 if (!strcasecmp(v->value, "mediaonly")) { 08921 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 08922 } else if (ast_true(v->value)) { 08923 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 08924 } else 08925 ast_set_flags_to(user, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 08926 } else if (!strcasecmp(v->name, "codecpriority")) { 08927 if(!strcasecmp(v->value, "caller")) 08928 ast_set_flag(user, IAX_CODEC_USER_FIRST); 08929 else if(!strcasecmp(v->value, "disabled")) 08930 ast_set_flag(user, IAX_CODEC_NOPREFS); 08931 else if(!strcasecmp(v->value, "reqonly")) { 08932 ast_set_flag(user, IAX_CODEC_NOCAP); 08933 ast_set_flag(user, IAX_CODEC_NOPREFS); 08934 } 08935 } else if (!strcasecmp(v->name, "jitterbuffer")) { 08936 ast_set2_flag(user, ast_true(v->value), IAX_USEJITTERBUF); 08937 } else if (!strcasecmp(v->name, "forcejitterbuffer")) { 08938 ast_set2_flag(user, ast_true(v->value), IAX_FORCEJITTERBUF); 08939 } else if (!strcasecmp(v->name, "dbsecret")) { 08940 ast_string_field_set(user, dbsecret, v->value); 08941 } else if (!strcasecmp(v->name, "secret")) { 08942 if (!ast_strlen_zero(user->secret)) { 08943 char *old = ast_strdupa(user->secret); 08944 08945 ast_string_field_build(user, secret, "%s;%s", old, v->value); 08946 } else 08947 ast_string_field_set(user, secret, v->value); 08948 } else if (!strcasecmp(v->name, "callerid")) { 08949 if (!ast_strlen_zero(v->value) && strcasecmp(v->value, "asreceived")) { 08950 char name2[80]; 08951 char num2[80]; 08952 ast_callerid_split(v->value, name2, sizeof(name2), num2, sizeof(num2)); 08953 ast_string_field_set(user, cid_name, name2); 08954 ast_string_field_set(user, cid_num, num2); 08955 ast_set_flag(user, IAX_HASCALLERID); 08956 } else { 08957 ast_clear_flag(user, IAX_HASCALLERID); 08958 ast_string_field_set(user, cid_name, ""); 08959 ast_string_field_set(user, cid_num, ""); 08960 } 08961 } else if (!strcasecmp(v->name, "fullname")) { 08962 if (!ast_strlen_zero(v->value)) { 08963 ast_string_field_set(user, cid_name, v->value); 08964 ast_set_flag(user, IAX_HASCALLERID); 08965 } else { 08966 ast_string_field_set(user, cid_name, ""); 08967 if (ast_strlen_zero(user->cid_num)) 08968 ast_clear_flag(user, IAX_HASCALLERID); 08969 } 08970 } else if (!strcasecmp(v->name, "cid_number")) { 08971 if (!ast_strlen_zero(v->value)) { 08972 ast_string_field_set(user, cid_num, v->value); 08973 ast_set_flag(user, IAX_HASCALLERID); 08974 } else { 08975 ast_string_field_set(user, cid_num, ""); 08976 if (ast_strlen_zero(user->cid_name)) 08977 ast_clear_flag(user, IAX_HASCALLERID); 08978 } 08979 } else if (!strcasecmp(v->name, "accountcode")) { 08980 ast_string_field_set(user, accountcode, v->value); 08981 } else if (!strcasecmp(v->name, "mohinterpret")) { 08982 ast_string_field_set(user, mohinterpret, v->value); 08983 } else if (!strcasecmp(v->name, "mohsuggest")) { 08984 ast_string_field_set(user, mohsuggest, v->value); 08985 } else if (!strcasecmp(v->name, "language")) { 08986 ast_string_field_set(user, language, v->value); 08987 } else if (!strcasecmp(v->name, "amaflags")) { 08988 format = ast_cdr_amaflags2int(v->value); 08989 if (format < 0) { 08990 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 08991 } else { 08992 user->amaflags = format; 08993 } 08994 } else if (!strcasecmp(v->name, "inkeys")) { 08995 ast_string_field_set(user, inkeys, v->value); 08996 } else if (!strcasecmp(v->name, "maxauthreq")) { 08997 user->maxauthreq = atoi(v->value); 08998 if (user->maxauthreq < 0) 08999 user->maxauthreq = 0; 09000 } else if (!strcasecmp(v->name, "adsi")) { 09001 user->adsi = ast_true(v->value); 09002 }/* else if (strcasecmp(v->name,"type")) */ 09003 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09004 v = v->next; 09005 if (!v) { 09006 v = alt; 09007 alt = NULL; 09008 } 09009 } 09010 if (!user->authmethods) { 09011 if (!ast_strlen_zero(user->secret)) { 09012 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09013 if (!ast_strlen_zero(user->inkeys)) 09014 user->authmethods |= IAX_AUTH_RSA; 09015 } else if (!ast_strlen_zero(user->inkeys)) { 09016 user->authmethods = IAX_AUTH_RSA; 09017 } else { 09018 user->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT; 09019 } 09020 } 09021 ast_clear_flag(user, IAX_DELME); 09022 } 09023 if (oldha) 09024 ast_free_ha(oldha); 09025 if (oldcon) 09026 free_context(oldcon); 09027 return user; 09028 }
static int cache_get_callno_locked | ( | const char * | data | ) | [static] |
Definition at line 9552 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_strdupa, ast_string_field_set, iax_ie_data::buf, chan_iax2_pvt::capability, parsed_dial_string::context, create_addr(), parsed_dial_string::exten, find_callno(), 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_MAX_CALLS, IAX_PROTO_VERSION, iaxs, iaxsl, parsed_dial_string::key, LOG_DEBUG, LOG_WARNING, NEW_FORCE, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, iax_ie_data::pos, secret, send_command(), create_addr_info::sockfd, and parsed_dial_string::username.
Referenced by find_cache().
09553 { 09554 struct sockaddr_in sin; 09555 int x; 09556 int callno; 09557 struct iax_ie_data ied; 09558 struct create_addr_info cai; 09559 struct parsed_dial_string pds; 09560 char *tmpstr; 09561 09562 for (x=0; x<IAX_MAX_CALLS; x++) { 09563 /* Look for an *exact match* call. Once a call is negotiated, it can only 09564 look up entries for a single context */ 09565 if (!ast_mutex_trylock(&iaxsl[x])) { 09566 if (iaxs[x] && !strcasecmp(data, iaxs[x]->dproot)) 09567 return x; 09568 ast_mutex_unlock(&iaxsl[x]); 09569 } 09570 } 09571 09572 /* No match found, we need to create a new one */ 09573 09574 memset(&cai, 0, sizeof(cai)); 09575 memset(&ied, 0, sizeof(ied)); 09576 memset(&pds, 0, sizeof(pds)); 09577 09578 tmpstr = ast_strdupa(data); 09579 parse_dial_string(tmpstr, &pds); 09580 09581 /* Populate our address from the given */ 09582 if (create_addr(pds.peer, &sin, &cai)) 09583 return -1; 09584 09585 ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n", 09586 pds.peer, pds.username, pds.password, pds.context); 09587 09588 callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd); 09589 if (callno < 1) { 09590 ast_log(LOG_WARNING, "Unable to create call\n"); 09591 return -1; 09592 } 09593 09594 ast_mutex_lock(&iaxsl[callno]); 09595 ast_string_field_set(iaxs[callno], dproot, data); 09596 iaxs[callno]->capability = IAX_CAPABILITY_FULLBANDWIDTH; 09597 09598 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 09599 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, "TBD"); 09600 /* the string format is slightly different from a standard dial string, 09601 because the context appears in the 'exten' position 09602 */ 09603 if (pds.exten) 09604 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.exten); 09605 if (pds.username) 09606 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 09607 iax_ie_append_int(&ied, IAX_IE_FORMAT, IAX_CAPABILITY_FULLBANDWIDTH); 09608 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, IAX_CAPABILITY_FULLBANDWIDTH); 09609 /* Keep password handy */ 09610 if (pds.password) 09611 ast_string_field_set(iaxs[callno], secret, pds.password); 09612 if (pds.key) 09613 ast_string_field_set(iaxs[callno], outkey, pds.key); 09614 /* Start the call going */ 09615 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 09616 09617 return callno; 09618 }
static unsigned int calc_rxstamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | offset | |||
) | [static] |
Definition at line 3576 of file chan_iax2.c.
References ast_log(), ast_random(), ast_tvsub(), chan_iax2_pvt::callno, LOG_DEBUG, option_debug, and chan_iax2_pvt::rxcore.
03577 { 03578 /* Returns where in "receive time" we are. That is, how many ms 03579 since we received (or would have received) the frame with timestamp 0 */ 03580 int ms; 03581 #ifdef IAXTESTS 03582 int jit; 03583 #endif /* IAXTESTS */ 03584 /* Setup rxcore if necessary */ 03585 if (ast_tvzero(p->rxcore)) { 03586 p->rxcore = ast_tvnow(); 03587 if (option_debug && iaxdebug) 03588 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n", 03589 p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset); 03590 p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000)); 03591 #if 1 03592 if (option_debug && iaxdebug) 03593 ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n", 03594 p->callno, (int)(p->rxcore.tv_sec),(int)( p->rxcore.tv_usec)); 03595 #endif 03596 } 03597 03598 ms = ast_tvdiff_ms(ast_tvnow(), p->rxcore); 03599 #ifdef IAXTESTS 03600 if (test_jit) { 03601 if (!test_jitpct || ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_jitpct)) { 03602 jit = (int)((float)test_jit * ast_random() / (RAND_MAX + 1.0)); 03603 if ((int)(2.0 * ast_random() / (RAND_MAX + 1.0))) 03604 jit = -jit; 03605 ms += jit; 03606 } 03607 } 03608 if (test_late) { 03609 ms += test_late; 03610 test_late = 0; 03611 } 03612 #endif /* IAXTESTS */ 03613 return ms; 03614 }
static unsigned int calc_timestamp | ( | struct chan_iax2_pvt * | p, | |
unsigned int | ts, | |||
struct ast_frame * | f | |||
) | [static] |
Definition at line 3458 of file chan_iax2.c.
References AST_FRAME_CNG, AST_FRAME_IAX, AST_FRAME_VOICE, ast_log(), ast_tvadd(), ast_tvsub(), chan_iax2_pvt::callno, ast_frame::delivery, ast_frame::frametype, iaxs, chan_iax2_pvt::lastsent, LOG_DEBUG, MAX_TIMESTAMP_SKEW, chan_iax2_pvt::nextpred, chan_iax2_pvt::notsilenttx, chan_iax2_pvt::offset, option_debug, chan_iax2_pvt::peercallno, and ast_frame::samples.
Referenced by iax2_send(), and socket_process().
03459 { 03460 int ms; 03461 int voice = 0; 03462 int genuine = 0; 03463 int adjust; 03464 struct timeval *delivery = NULL; 03465 03466 03467 /* What sort of frame do we have?: voice is self-explanatory 03468 "genuine" means an IAX frame - things like LAGRQ/RP, PING/PONG, ACK 03469 non-genuine frames are CONTROL frames [ringing etc], DTMF 03470 The "genuine" distinction is needed because genuine frames must get a clock-based timestamp, 03471 the others need a timestamp slaved to the voice frames so that they go in sequence 03472 */ 03473 if (f) { 03474 if (f->frametype == AST_FRAME_VOICE) { 03475 voice = 1; 03476 delivery = &f->delivery; 03477 } else if (f->frametype == AST_FRAME_IAX) { 03478 genuine = 1; 03479 } else if (f->frametype == AST_FRAME_CNG) { 03480 p->notsilenttx = 0; 03481 } 03482 } 03483 if (ast_tvzero(p->offset)) { 03484 gettimeofday(&p->offset, NULL); 03485 /* Round to nearest 20ms for nice looking traces */ 03486 p->offset.tv_usec -= p->offset.tv_usec % 20000; 03487 } 03488 /* If the timestamp is specified, just send it as is */ 03489 if (ts) 03490 return ts; 03491 /* If we have a time that the frame arrived, always use it to make our timestamp */ 03492 if (delivery && !ast_tvzero(*delivery)) { 03493 ms = ast_tvdiff_ms(*delivery, p->offset); 03494 if (option_debug > 2 && iaxdebug) 03495 ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno); 03496 } else { 03497 ms = ast_tvdiff_ms(ast_tvnow(), p->offset); 03498 if (ms < 0) 03499 ms = 0; 03500 if (voice) { 03501 /* On a voice frame, use predicted values if appropriate */ 03502 if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) { 03503 /* Adjust our txcore, keeping voice and non-voice synchronized */ 03504 /* AN EXPLANATION: 03505 When we send voice, we usually send "calculated" timestamps worked out 03506 on the basis of the number of samples sent. When we send other frames, 03507 we usually send timestamps worked out from the real clock. 03508 The problem is that they can tend to drift out of step because the 03509 source channel's clock and our clock may not be exactly at the same rate. 03510 We fix this by continuously "tweaking" p->offset. p->offset is "time zero" 03511 for this call. Moving it adjusts timestamps for non-voice frames. 03512 We make the adjustment in the style of a moving average. Each time we 03513 adjust p->offset by 10% of the difference between our clock-derived 03514 timestamp and the predicted timestamp. That's why you see "10000" 03515 below even though IAX2 timestamps are in milliseconds. 03516 The use of a moving average avoids offset moving too radically. 03517 Generally, "adjust" roams back and forth around 0, with offset hardly 03518 changing at all. But if a consistent different starts to develop it 03519 will be eliminated over the course of 10 frames (200-300msecs) 03520 */ 03521 adjust = (ms - p->nextpred); 03522 if (adjust < 0) 03523 p->offset = ast_tvsub(p->offset, ast_samp2tv(abs(adjust), 10000)); 03524 else if (adjust > 0) 03525 p->offset = ast_tvadd(p->offset, ast_samp2tv(adjust, 10000)); 03526 03527 if (!p->nextpred) { 03528 p->nextpred = ms; /*f->samples / 8;*/ 03529 if (p->nextpred <= p->lastsent) 03530 p->nextpred = p->lastsent + 3; 03531 } 03532 ms = p->nextpred; 03533 } else { 03534 /* in this case, just use the actual 03535 * time, since we're either way off 03536 * (shouldn't happen), or we're ending a 03537 * silent period -- and seed the next 03538 * predicted time. Also, round ms to the 03539 * next multiple of frame size (so our 03540 * silent periods are multiples of 03541 * frame size too) */ 03542 03543 if (iaxdebug && abs(ms - p->nextpred) > MAX_TIMESTAMP_SKEW ) 03544 ast_log(LOG_DEBUG, "predicted timestamp skew (%u) > max (%u), using real ts instead.\n", 03545 abs(ms - p->nextpred), MAX_TIMESTAMP_SKEW); 03546 03547 if (f->samples >= 8) /* check to make sure we dont core dump */ 03548 { 03549 int diff = ms % (f->samples / 8); 03550 if (diff) 03551 ms += f->samples/8 - diff; 03552 } 03553 03554 p->nextpred = ms; 03555 p->notsilenttx = 1; 03556 } 03557 } else { 03558 /* On a dataframe, use last value + 3 (to accomodate jitter buffer shrinking) if appropriate unless 03559 it's a genuine frame */ 03560 if (genuine) { 03561 /* genuine (IAX LAGRQ etc) must keep their clock-based stamps */ 03562 if (ms <= p->lastsent) 03563 ms = p->lastsent + 3; 03564 } else if (abs(ms - p->lastsent) <= MAX_TIMESTAMP_SKEW) { 03565 /* non-genuine frames (!?) (DTMF, CONTROL) should be pulled into the predicted stream stamps */ 03566 ms = p->lastsent + 3; 03567 } 03568 } 03569 } 03570 p->lastsent = ms; 03571 if (voice) 03572 p->nextpred = p->nextpred + f->samples / 8; 03573 return ms; 03574 }
static unsigned int calc_txpeerstamp | ( | struct iax2_trunk_peer * | tpeer, | |
int | sampms, | |||
struct timeval * | tv | |||
) | [static] |
Definition at line 3414 of file chan_iax2.c.
References iax2_trunk_peer::lastsent, iax2_trunk_peer::lasttxtime, MAX_TIMESTAMP_SKEW, iax2_trunk_peer::trunkact, and iax2_trunk_peer::txtrunktime.
Referenced by send_trunk().
03415 { 03416 unsigned long int mssincetx; /* unsigned to handle overflows */ 03417 long int ms, pred; 03418 03419 tpeer->trunkact = *tv; 03420 mssincetx = ast_tvdiff_ms(*tv, tpeer->lasttxtime); 03421 if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) { 03422 /* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */ 03423 tpeer->txtrunktime = *tv; 03424 tpeer->lastsent = 999999; 03425 } 03426 /* Update last transmit time now */ 03427 tpeer->lasttxtime = *tv; 03428 03429 /* Calculate ms offset */ 03430 ms = ast_tvdiff_ms(*tv, tpeer->txtrunktime); 03431 /* Predict from last value */ 03432 pred = tpeer->lastsent + sampms; 03433 if (abs(ms - pred) < MAX_TIMESTAMP_SKEW) 03434 ms = pred; 03435 03436 /* We never send the same timestamp twice, so fudge a little if we must */ 03437 if (ms == tpeer->lastsent) 03438 ms = tpeer->lastsent + 1; 03439 tpeer->lastsent = ms; 03440 return ms; 03441 }
static int check_access | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Definition at line 4664 of file chan_iax2.c.
References iax2_user::adsi, chan_iax2_pvt::adsi, iax_ies::adsicpe, chan_iax2_pvt::amaflags, iax2_user::amaflags, apply_context(), ast_apply_ha(), ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, ast_set2_flag, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variable_new(), iax2_user::authmethods, chan_iax2_pvt::authmethods, iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, chan_iax2_pvt::calling_pres, iax_ies::calling_pres, chan_iax2_pvt::calling_tns, iax_ies::calling_tns, chan_iax2_pvt::calling_ton, iax_ies::calling_ton, iax2_user::capability, chan_iax2_pvt::capability, iax_ies::capability, cid_name, cid_num, iax_ies::codec_prefs, iax2_context::context, iax2_user::contexts, destroy_user(), iax_ies::dnid, iax2_user::encmethods, chan_iax2_pvt::encmethods, exten, iax_ies::format, iax2_user::ha, iax2_getpeertrunk(), IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_FORCEJITTERBUF, IAX_HASCALLERID, IAX_MAXAUTHREQ, IAX_NOTRANSFER, IAX_PROTO_VERSION, IAX_TEMPONLY, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, key(), iax_ies::language, LOG_WARNING, iax2_user::maxauthreq, ast_variable::name, ast_variable::next, chan_iax2_pvt::peeradsicpe, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, chan_iax2_pvt::prefs, iax2_user::prefs, iax_ies::rdnis, realtime_user(), secret, iax_ies::username, ast_variable::value, chan_iax2_pvt::vars, iax2_user::vars, and iax_ies::version.
Referenced by socket_process().
04665 { 04666 /* Start pessimistic */ 04667 int res = -1; 04668 int version = 2; 04669 struct iax2_user *user = NULL, *best = NULL; 04670 int bestscore = 0; 04671 int gotcapability = 0; 04672 struct ast_variable *v = NULL, *tmpvar = NULL; 04673 04674 if (!iaxs[callno]) 04675 return res; 04676 if (ies->called_number) 04677 ast_string_field_set(iaxs[callno], exten, ies->called_number); 04678 if (ies->calling_number) { 04679 ast_shrink_phone_number(ies->calling_number); 04680 ast_string_field_set(iaxs[callno], cid_num, ies->calling_number); 04681 } 04682 if (ies->calling_name) 04683 ast_string_field_set(iaxs[callno], cid_name, ies->calling_name); 04684 if (ies->calling_ani) 04685 ast_string_field_set(iaxs[callno], ani, ies->calling_ani); 04686 if (ies->dnid) 04687 ast_string_field_set(iaxs[callno], dnid, ies->dnid); 04688 if (ies->rdnis) 04689 ast_string_field_set(iaxs[callno], rdnis, ies->rdnis); 04690 if (ies->called_context) 04691 ast_string_field_set(iaxs[callno], context, ies->called_context); 04692 if (ies->language) 04693 ast_string_field_set(iaxs[callno], language, ies->language); 04694 if (ies->username) 04695 ast_string_field_set(iaxs[callno], username, ies->username); 04696 if (ies->calling_ton > -1) 04697 iaxs[callno]->calling_ton = ies->calling_ton; 04698 if (ies->calling_tns > -1) 04699 iaxs[callno]->calling_tns = ies->calling_tns; 04700 if (ies->calling_pres > -1) 04701 iaxs[callno]->calling_pres = ies->calling_pres; 04702 if (ies->format) 04703 iaxs[callno]->peerformat = ies->format; 04704 if (ies->adsicpe) 04705 iaxs[callno]->peeradsicpe = ies->adsicpe; 04706 if (ies->capability) { 04707 gotcapability = 1; 04708 iaxs[callno]->peercapability = ies->capability; 04709 } 04710 if (ies->version) 04711 version = ies->version; 04712 04713 /* Use provided preferences until told otherwise for actual preferences */ 04714 if(ies->codec_prefs) { 04715 ast_codec_pref_convert(&iaxs[callno]->rprefs, ies->codec_prefs, 32, 0); 04716 ast_codec_pref_convert(&iaxs[callno]->prefs, ies->codec_prefs, 32, 0); 04717 } 04718 04719 if (!gotcapability) 04720 iaxs[callno]->peercapability = iaxs[callno]->peerformat; 04721 if (version > IAX_PROTO_VERSION) { 04722 ast_log(LOG_WARNING, "Peer '%s' has too new a protocol version (%d) for me\n", 04723 ast_inet_ntoa(sin->sin_addr), version); 04724 return res; 04725 } 04726 /* Search the userlist for a compatible entry, and fill in the rest */ 04727 AST_LIST_LOCK(&users); 04728 AST_LIST_TRAVERSE(&users, user, entry) { 04729 if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */ 04730 !strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */ 04731 && ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */ 04732 && (ast_strlen_zero(iaxs[callno]->context) || /* No context specified */ 04733 apply_context(user->contexts, iaxs[callno]->context))) { /* Context is permitted */ 04734 if (!ast_strlen_zero(iaxs[callno]->username)) { 04735 /* Exact match, stop right now. */ 04736 best = user; 04737 break; 04738 } else if (ast_strlen_zero(user->secret) && ast_strlen_zero(user->inkeys)) { 04739 /* No required authentication */ 04740 if (user->ha) { 04741 /* There was host authentication and we passed, bonus! */ 04742 if (bestscore < 4) { 04743 bestscore = 4; 04744 best = user; 04745 } 04746 } else { 04747 /* No host access, but no secret, either, not bad */ 04748 if (bestscore < 3) { 04749 bestscore = 3; 04750 best = user; 04751 } 04752 } 04753 } else { 04754 if (user->ha) { 04755 /* Authentication, but host access too, eh, it's something.. */ 04756 if (bestscore < 2) { 04757 bestscore = 2; 04758 best = user; 04759 } 04760 } else { 04761 /* Authentication and no host access... This is our baseline */ 04762 if (bestscore < 1) { 04763 bestscore = 1; 04764 best = user; 04765 } 04766 } 04767 } 04768 } 04769 } 04770 AST_LIST_UNLOCK(&users); 04771 user = best; 04772 if (!user && !ast_strlen_zero(iaxs[callno]->username)) { 04773 user = realtime_user(iaxs[callno]->username); 04774 if (user && !ast_strlen_zero(iaxs[callno]->context) && /* No context specified */ 04775 !apply_context(user->contexts, iaxs[callno]->context)) { /* Context is permitted */ 04776 destroy_user(user); 04777 user = NULL; 04778 } 04779 } 04780 if (user) { 04781 /* We found our match (use the first) */ 04782 /* copy vars */ 04783 for (v = user->vars ; v ; v = v->next) { 04784 if((tmpvar = ast_variable_new(v->name, v->value))) { 04785 tmpvar->next = iaxs[callno]->vars; 04786 iaxs[callno]->vars = tmpvar; 04787 } 04788 } 04789 /* If a max AUTHREQ restriction is in place, activate it */ 04790 if (user->maxauthreq > 0) 04791 ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ); 04792 iaxs[callno]->prefs = user->prefs; 04793 ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST); 04794 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS); 04795 ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOCAP); 04796 iaxs[callno]->encmethods = user->encmethods; 04797 /* Store the requested username if not specified */ 04798 if (ast_strlen_zero(iaxs[callno]->username)) 04799 ast_string_field_set(iaxs[callno], username, user->name); 04800 /* Store whether this is a trunked call, too, of course, and move if appropriate */ 04801 ast_copy_flags(iaxs[callno], user, IAX_TRUNK); 04802 iaxs[callno]->capability = user->capability; 04803 /* And use the default context */ 04804 if (ast_strlen_zero(iaxs[callno]->context)) { 04805 if (user->contexts) 04806 ast_string_field_set(iaxs[callno], context, user->contexts->context); 04807 else 04808 ast_string_field_set(iaxs[callno], context, context); 04809 } 04810 /* And any input keys */ 04811 ast_string_field_set(iaxs[callno], inkeys, user->inkeys); 04812 /* And the permitted authentication methods */ 04813 iaxs[callno]->authmethods = user->authmethods; 04814 iaxs[callno]->adsi = user->adsi; 04815 /* If they have callerid, override the given caller id. Always store the ANI */ 04816 if (!ast_strlen_zero(iaxs[callno]->cid_num) || !ast_strlen_zero(iaxs[callno]->cid_name)) { 04817 if (ast_test_flag(user, IAX_HASCALLERID)) { 04818 iaxs[callno]->calling_tns = 0; 04819 iaxs[callno]->calling_ton = 0; 04820 ast_string_field_set(iaxs[callno], cid_num, user->cid_num); 04821 ast_string_field_set(iaxs[callno], cid_name, user->cid_name); 04822 iaxs[callno]->calling_pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 04823 } 04824 if (ast_strlen_zero(iaxs[callno]->ani)) 04825 ast_string_field_set(iaxs[callno], ani, user->cid_num); 04826 } else { 04827 iaxs[callno]->calling_pres = AST_PRES_NUMBER_NOT_AVAILABLE; 04828 } 04829 if (!ast_strlen_zero(user->accountcode)) 04830 ast_string_field_set(iaxs[callno], accountcode, user->accountcode); 04831 if (!ast_strlen_zero(user->mohinterpret)) 04832 ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret); 04833 if (!ast_strlen_zero(user->mohsuggest)) 04834 ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest); 04835 if (user->amaflags) 04836 iaxs[callno]->amaflags = user->amaflags; 04837 if (!ast_strlen_zero(user->language)) 04838 ast_string_field_set(iaxs[callno], language, user->language); 04839 ast_copy_flags(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 04840 /* Keep this check last */ 04841 if (!ast_strlen_zero(user->dbsecret)) { 04842 char *family, *key=NULL; 04843 char buf[80]; 04844 family = ast_strdupa(user->dbsecret); 04845 key = strchr(family, '/'); 04846 if (key) { 04847 *key = '\0'; 04848 key++; 04849 } 04850 if (!key || ast_db_get(family, key, buf, sizeof(buf))) 04851 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); 04852 else 04853 ast_string_field_set(iaxs[callno], secret, buf); 04854 } else 04855 ast_string_field_set(iaxs[callno], secret, user->secret); 04856 if (ast_test_flag(user, IAX_TEMPONLY)) 04857 destroy_user(user); 04858 res = 0; 04859 } 04860 ast_set2_flag(iaxs[callno], iax2_getpeertrunk(*sin), IAX_TRUNK); 04861 return res; 04862 }
static int check_provisioning | ( | struct sockaddr_in * | sin, | |
int | sockfd, | |||
char * | si, | |||
unsigned int | ver | |||
) | [static] |
Definition at line 6260 of file chan_iax2.c.
References ast_log(), iax2_provision(), iax_provision_version(), LOG_DEBUG, and option_debug.
Referenced by socket_process().
06261 { 06262 unsigned int ourver; 06263 char rsi[80]; 06264 snprintf(rsi, sizeof(rsi), "si-%s", si); 06265 if (iax_provision_version(&ourver, rsi, 1)) 06266 return 0; 06267 if (option_debug) 06268 ast_log(LOG_DEBUG, "Service identifier '%s', we think '%08x', they think '%08x'\n", si, ourver, ver); 06269 if (ourver != ver) 06270 iax2_provision(sin, sockfd, NULL, rsi, 1); 06271 return 0; 06272 }
static int check_srcaddr | ( | struct sockaddr * | sa, | |
socklen_t | salen | |||
) | [static] |
Check if address can be used as packet source.
Definition at line 8470 of file chan_iax2.c.
References ast_log(), LOG_DEBUG, and LOG_ERROR.
Referenced by peer_set_srcaddr().
08471 { 08472 int sd; 08473 int res; 08474 08475 sd = socket(AF_INET, SOCK_DGRAM, 0); 08476 if (sd < 0) { 08477 ast_log(LOG_ERROR, "Socket: %s\n", strerror(errno)); 08478 return -1; 08479 } 08480 08481 res = bind(sd, sa, salen); 08482 if (res < 0) { 08483 ast_log(LOG_DEBUG, "Can't bind: %s\n", strerror(errno)); 08484 close(sd); 08485 return 1; 08486 } 08487 08488 close(sd); 08489 return 0; 08490 }
static int complete_dpreply | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5329 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_UNKNOWN, iax_ies::called_number, iax2_dpcache::callno, chan_iax2_pvt::dpentries, iax_ies::dpstatus, iax2_dpcache::expiry, iax2_dpcache::exten, exten, iax2_dpcache::flags, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax2_dpcache::orig, iax2_dpcache::peer, iax_ies::refresh, and iax2_dpcache::waiters.
Referenced by socket_process().
05330 { 05331 char exten[256] = ""; 05332 int status = CACHE_FLAG_UNKNOWN; 05333 int expiry = iaxdefaultdpcache; 05334 int x; 05335 int matchmore = 0; 05336 struct iax2_dpcache *dp, *prev; 05337 05338 if (ies->called_number) 05339 ast_copy_string(exten, ies->called_number, sizeof(exten)); 05340 05341 if (ies->dpstatus & IAX_DPSTATUS_EXISTS) 05342 status = CACHE_FLAG_EXISTS; 05343 else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST) 05344 status = CACHE_FLAG_CANEXIST; 05345 else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT) 05346 status = CACHE_FLAG_NONEXISTENT; 05347 05348 if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) { 05349 /* Don't really do anything with this */ 05350 } 05351 if (ies->refresh) 05352 expiry = ies->refresh; 05353 if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE) 05354 matchmore = CACHE_FLAG_MATCHMORE; 05355 ast_mutex_lock(&dpcache_lock); 05356 prev = NULL; 05357 dp = pvt->dpentries; 05358 while(dp) { 05359 if (!strcmp(dp->exten, exten)) { 05360 /* Let them go */ 05361 if (prev) 05362 prev->peer = dp->peer; 05363 else 05364 pvt->dpentries = dp->peer; 05365 dp->peer = NULL; 05366 dp->callno = 0; 05367 dp->expiry.tv_sec = dp->orig.tv_sec + expiry; 05368 if (dp->flags & CACHE_FLAG_PENDING) { 05369 dp->flags &= ~CACHE_FLAG_PENDING; 05370 dp->flags |= status; 05371 dp->flags |= matchmore; 05372 } 05373 /* Wake up waiters */ 05374 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 05375 if (dp->waiters[x] > -1) 05376 write(dp->waiters[x], "asdf", 4); 05377 } 05378 prev = dp; 05379 dp = dp->peer; 05380 } 05381 ast_mutex_unlock(&dpcache_lock); 05382 return 0; 05383 }
static char* complete_iax2_show_peer | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 2117 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_strdup.
02118 { 02119 int which = 0; 02120 struct iax2_peer *p = NULL; 02121 char *res = NULL; 02122 int wordlen = strlen(word); 02123 02124 /* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */ 02125 if (pos == 3) { 02126 AST_LIST_LOCK(&peers); 02127 AST_LIST_TRAVERSE(&peers, p, entry) { 02128 if (!strncasecmp(p->name, word, wordlen) && ++which > state) { 02129 res = ast_strdup(p->name); 02130 break; 02131 } 02132 } 02133 AST_LIST_UNLOCK(&peers); 02134 } 02135 02136 return res; 02137 }
static int complete_transfer | ( | int | callno, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5385 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::aseqno, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), iax_frame::callno, iax_ies::callno, jb_frame::data, DEFAULT_RETRY_TIME, iax2_frame_free(), iaxq, iaxs, chan_iax2_pvt::iseqno, chan_iax2_pvt::jb, jb_getall(), JB_OK, jb_reset(), chan_iax2_pvt::lag, chan_iax2_pvt::last, chan_iax2_pvt::lastsent, LOG_WARNING, chan_iax2_pvt::nextpred, chan_iax2_pvt::offset, chan_iax2_pvt::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, chan_iax2_pvt::rseqno, chan_iax2_pvt::rxcore, 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().
05386 { 05387 int peercallno = 0; 05388 struct chan_iax2_pvt *pvt = iaxs[callno]; 05389 struct iax_frame *cur; 05390 jb_frame frame; 05391 05392 if (ies->callno) 05393 peercallno = ies->callno; 05394 05395 if (peercallno < 1) { 05396 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05397 return -1; 05398 } 05399 memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr)); 05400 memset(&pvt->transfer, 0, sizeof(pvt->transfer)); 05401 /* Reset sequence numbers */ 05402 pvt->oseqno = 0; 05403 pvt->rseqno = 0; 05404 pvt->iseqno = 0; 05405 pvt->aseqno = 0; 05406 pvt->peercallno = peercallno; 05407 pvt->transferring = TRANSFER_NONE; 05408 pvt->svoiceformat = -1; 05409 pvt->voiceformat = 0; 05410 pvt->svideoformat = -1; 05411 pvt->videoformat = 0; 05412 pvt->transfercallno = -1; 05413 memset(&pvt->rxcore, 0, sizeof(pvt->rxcore)); 05414 memset(&pvt->offset, 0, sizeof(pvt->offset)); 05415 /* reset jitterbuffer */ 05416 while(jb_getall(pvt->jb,&frame) == JB_OK) 05417 iax2_frame_free(frame.data); 05418 jb_reset(pvt->jb); 05419 pvt->lag = 0; 05420 pvt->last = 0; 05421 pvt->lastsent = 0; 05422 pvt->nextpred = 0; 05423 pvt->pingtime = DEFAULT_RETRY_TIME; 05424 AST_LIST_LOCK(&iaxq.queue); 05425 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 05426 /* We must cancel any packets that would have been transmitted 05427 because now we're talking to someone new. It's okay, they 05428 were transmitted to someone that didn't care anyway. */ 05429 if (callno == cur->callno) 05430 cur->retries = -1; 05431 } 05432 AST_LIST_UNLOCK(&iaxq.queue); 05433 return 0; 05434 }
static unsigned char compress_subclass | ( | int | subclass | ) | [static] |
Definition at line 1011 of file chan_iax2.c.
References ast_log(), IAX_FLAG_SC_LOG, IAX_MAX_SHIFT, and LOG_WARNING.
Referenced by iax2_send(), and raw_hangup().
01012 { 01013 int x; 01014 int power=-1; 01015 /* If it's 128 or smaller, just return it */ 01016 if (subclass < IAX_FLAG_SC_LOG) 01017 return subclass; 01018 /* Otherwise find its power */ 01019 for (x = 0; x < IAX_MAX_SHIFT; x++) { 01020 if (subclass & (1 << x)) { 01021 if (power > -1) { 01022 ast_log(LOG_WARNING, "Can't compress subclass %d\n", subclass); 01023 return 0; 01024 } else 01025 power = x; 01026 } 01027 } 01028 return power | IAX_FLAG_SC_LOG; 01029 }
static void construct_rr | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ie_data * | iep | |||
) | [static] |
Definition at line 6274 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().
06275 { 06276 jb_info stats; 06277 jb_getinfo(pvt->jb, &stats); 06278 06279 memset(iep, 0, sizeof(*iep)); 06280 06281 iax_ie_append_int(iep,IAX_IE_RR_JITTER, stats.jitter); 06282 if(stats.frames_in == 0) stats.frames_in = 1; 06283 iax_ie_append_int(iep,IAX_IE_RR_LOSS, ((0xff & (stats.losspct/1000)) << 24 | (stats.frames_lost & 0x00ffffff))); 06284 iax_ie_append_int(iep,IAX_IE_RR_PKTS, stats.frames_in); 06285 iax_ie_append_short(iep,IAX_IE_RR_DELAY, stats.current - stats.min); 06286 iax_ie_append_int(iep,IAX_IE_RR_DROPPED, stats.frames_dropped); 06287 iax_ie_append_int(iep,IAX_IE_RR_OOO, stats.frames_ooo); 06288 }
static int create_addr | ( | const char * | peername, | |
struct sockaddr_in * | sin, | |||
struct create_addr_info * | cai | |||
) | [static] |
Definition at line 2671 of file chan_iax2.c.
References iax2_peer::addr, iax2_peer::adsi, create_addr_info::adsi, ast_clear_flag, ast_codec_pref_convert(), ast_copy_flags, ast_db_get(), ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, iax2_peer::capability, create_addr_info::capability, create_addr_info::context, iax2_peer::defaddr, destroy_peer(), iax2_peer::encmethods, create_addr_info::encmethods, find_peer(), create_addr_info::found, hp, IAX_DEFAULT_PORTNO, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TEMPONLY, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, key(), iax2_peer::lastms, LOG_WARNING, iax2_peer::maxms, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, create_addr_info::outkey, create_addr_info::peercontext, iax2_peer::prefs, create_addr_info::prefs, iax2_user::prefs, create_addr_info::secret, iax2_peer::sockfd, create_addr_info::sockfd, create_addr_info::timezone, and create_addr_info::username.
02672 { 02673 struct ast_hostent ahp; 02674 struct hostent *hp; 02675 struct iax2_peer *peer; 02676 02677 ast_clear_flag(cai, IAX_SENDANI | IAX_TRUNK); 02678 cai->sockfd = defaultsockfd; 02679 cai->maxtime = 0; 02680 sin->sin_family = AF_INET; 02681 02682 if (!(peer = find_peer(peername, 1))) { 02683 cai->found = 0; 02684 02685 hp = ast_gethostbyname(peername, &ahp); 02686 if (hp) { 02687 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 02688 sin->sin_port = htons(IAX_DEFAULT_PORTNO); 02689 /* use global iax prefs for unknown peer/user */ 02690 ast_codec_pref_convert(&prefs, cai->prefs, sizeof(cai->prefs), 1); 02691 return 0; 02692 } else { 02693 ast_log(LOG_WARNING, "No such host: %s\n", peername); 02694 return -1; 02695 } 02696 } 02697 02698 cai->found = 1; 02699 02700 /* if the peer has no address (current or default), return failure */ 02701 if (!(peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr)) { 02702 if (ast_test_flag(peer, IAX_TEMPONLY)) 02703 destroy_peer(peer); 02704 return -1; 02705 } 02706 02707 /* if the peer is being monitored and is currently unreachable, return failure */ 02708 if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0))) { 02709 if (ast_test_flag(peer, IAX_TEMPONLY)) 02710 destroy_peer(peer); 02711 return -1; 02712 } 02713 02714 ast_copy_flags(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 02715 cai->maxtime = peer->maxms; 02716 cai->capability = peer->capability; 02717 cai->encmethods = peer->encmethods; 02718 cai->sockfd = peer->sockfd; 02719 cai->adsi = peer->adsi; 02720 ast_codec_pref_convert(&peer->prefs, cai->prefs, sizeof(cai->prefs), 1); 02721 ast_copy_string(cai->context, peer->context, sizeof(cai->context)); 02722 ast_copy_string(cai->peercontext, peer->peercontext, sizeof(cai->peercontext)); 02723 ast_copy_string(cai->username, peer->username, sizeof(cai->username)); 02724 ast_copy_string(cai->timezone, peer->zonetag, sizeof(cai->timezone)); 02725 ast_copy_string(cai->outkey, peer->outkey, sizeof(cai->outkey)); 02726 ast_copy_string(cai->mohinterpret, peer->mohinterpret, sizeof(cai->mohinterpret)); 02727 ast_copy_string(cai->mohsuggest, peer->mohsuggest, sizeof(cai->mohsuggest)); 02728 if (ast_strlen_zero(peer->dbsecret)) { 02729 ast_copy_string(cai->secret, peer->secret, sizeof(cai->secret)); 02730 } else { 02731 char *family; 02732 char *key = NULL; 02733 02734 family = ast_strdupa(peer->dbsecret); 02735 key = strchr(family, '/'); 02736 if (key) 02737 *key++ = '\0'; 02738 if (!key || ast_db_get(family, key, cai->secret, sizeof(cai->secret))) { 02739 ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", peer->dbsecret); 02740 if (ast_test_flag(peer, IAX_TEMPONLY)) 02741 destroy_peer(peer); 02742 return -1; 02743 } 02744 } 02745 02746 if (peer->addr.sin_addr.s_addr) { 02747 sin->sin_addr = peer->addr.sin_addr; 02748 sin->sin_port = peer->addr.sin_port; 02749 } else { 02750 sin->sin_addr = peer->defaddr.sin_addr; 02751 sin->sin_port = peer->defaddr.sin_port; 02752 } 02753 02754 if (ast_test_flag(peer, IAX_TEMPONLY)) 02755 destroy_peer(peer); 02756 02757 return 0; 02758 }
static int decode_frame | ( | aes_decrypt_ctx * | dcx, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 3760 of file chan_iax2.c.
References AST_FRAME_VIDEO, ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, ast_frame::frametype, IAX_FLAG_FULL, LOG_DEBUG, memcpy_decrypt(), option_debug, ast_iax2_full_hdr::scallno, ast_frame::subclass, ast_iax2_full_hdr::type, and uncompress_subclass().
Referenced by decrypt_frame().
03761 { 03762 int padding; 03763 unsigned char *workspace; 03764 03765 workspace = alloca(*datalen); 03766 memset(f, 0, sizeof(*f)); 03767 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 03768 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 03769 if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr)) 03770 return -1; 03771 /* Decrypt */ 03772 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx); 03773 03774 padding = 16 + (workspace[15] & 0xf); 03775 if (option_debug && iaxdebug) 03776 ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]); 03777 if (*datalen < padding + sizeof(struct ast_iax2_full_hdr)) 03778 return -1; 03779 03780 *datalen -= padding; 03781 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 03782 f->frametype = fh->type; 03783 if (f->frametype == AST_FRAME_VIDEO) { 03784 f->subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 03785 } else { 03786 f->subclass = uncompress_subclass(fh->csub); 03787 } 03788 } else { 03789 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 03790 if (option_debug && iaxdebug) 03791 ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen); 03792 if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr)) 03793 return -1; 03794 /* Decrypt */ 03795 memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx); 03796 padding = 16 + (workspace[15] & 0x0f); 03797 if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr)) 03798 return -1; 03799 *datalen -= padding; 03800 memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 03801 } 03802 return 0; 03803 }
static int decrypt_frame | ( | int | callno, | |
struct ast_iax2_full_hdr * | fh, | |||
struct ast_frame * | f, | |||
int * | datalen | |||
) | [static] |
Definition at line 3846 of file chan_iax2.c.
References ast_set_flag, ast_strdupa, ast_test_flag, build_enc_keys(), decode_frame(), IAX_KEYPOPULATED, iaxs, MD5Final(), MD5Init(), MD5Update(), secret, and strsep().
Referenced by socket_process().
03847 { 03848 int res=-1; 03849 if (!ast_test_flag(iaxs[callno], IAX_KEYPOPULATED)) { 03850 /* Search for possible keys, given secrets */ 03851 struct MD5Context md5; 03852 unsigned char digest[16]; 03853 char *tmppw, *stringp; 03854 03855 tmppw = ast_strdupa(iaxs[callno]->secret); 03856 stringp = tmppw; 03857 while ((tmppw = strsep(&stringp, ";"))) { 03858 MD5Init(&md5); 03859 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 03860 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 03861 MD5Final(digest, &md5); 03862 build_enc_keys(digest, &iaxs[callno]->ecx, &iaxs[callno]->dcx); 03863 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 03864 if (!res) { 03865 ast_set_flag(iaxs[callno], IAX_KEYPOPULATED); 03866 break; 03867 } 03868 } 03869 } else 03870 res = decode_frame(&iaxs[callno]->dcx, fh, f, datalen); 03871 return res; 03872 }
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 6336 of file chan_iax2.c.
References ast_calloc, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_mutex_lock(), ast_mutex_unlock(), and ast_iax2_full_hdr::oseqno.
Referenced by socket_read().
06337 { 06338 struct iax2_pkt_buf *pkt_buf, *cur_pkt_buf; 06339 struct ast_iax2_full_hdr *fh, *cur_fh; 06340 06341 if (!(pkt_buf = ast_calloc(1, sizeof(*pkt_buf) + from_here->buf_len))) 06342 return; 06343 06344 pkt_buf->len = from_here->buf_len; 06345 memcpy(pkt_buf->buf, from_here->buf, pkt_buf->len); 06346 06347 fh = (struct ast_iax2_full_hdr *) pkt_buf->buf; 06348 ast_mutex_lock(&to_here->lock); 06349 AST_LIST_TRAVERSE_SAFE_BEGIN(&to_here->full_frames, cur_pkt_buf, entry) { 06350 cur_fh = (struct ast_iax2_full_hdr *) cur_pkt_buf->buf; 06351 if (fh->oseqno < cur_fh->oseqno) { 06352 AST_LIST_INSERT_BEFORE_CURRENT(&to_here->full_frames, pkt_buf, entry); 06353 break; 06354 } 06355 } 06356 AST_LIST_TRAVERSE_SAFE_END 06357 06358 if (!cur_pkt_buf) 06359 AST_LIST_INSERT_TAIL(&to_here->full_frames, pkt_buf, entry); 06360 06361 ast_mutex_unlock(&to_here->lock); 06362 }
static void delete_users | ( | void | ) | [static] |
Definition at line 9030 of file chan_iax2.c.
References ast_dnsmgr_release(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_set_flag, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, free, iax2_destroy(), IAX_DELME, iaxs, iaxsl, and chan_iax2_pvt::reg.
09031 { 09032 struct iax2_user *user; 09033 struct iax2_peer *peer; 09034 struct iax2_registry *reg; 09035 09036 AST_LIST_LOCK(&users); 09037 AST_LIST_TRAVERSE(&users, user, entry) 09038 ast_set_flag(user, IAX_DELME); 09039 AST_LIST_UNLOCK(&users); 09040 09041 AST_LIST_LOCK(®istrations); 09042 while ((reg = AST_LIST_REMOVE_HEAD(®istrations, entry))) { 09043 if (reg->expire > -1) 09044 ast_sched_del(sched, reg->expire); 09045 if (reg->callno) { 09046 ast_mutex_lock(&iaxsl[reg->callno]); 09047 if (iaxs[reg->callno]) { 09048 iaxs[reg->callno]->reg = NULL; 09049 iax2_destroy(reg->callno); 09050 } 09051 ast_mutex_unlock(&iaxsl[reg->callno]); 09052 } 09053 if (reg->dnsmgr) 09054 ast_dnsmgr_release(reg->dnsmgr); 09055 free(reg); 09056 } 09057 AST_LIST_UNLOCK(®istrations); 09058 09059 AST_LIST_LOCK(&peers); 09060 AST_LIST_TRAVERSE(&peers, peer, entry) 09061 ast_set_flag(peer, IAX_DELME); 09062 AST_LIST_UNLOCK(&peers); 09063 }
static void destroy_firmware | ( | struct iax_firmware * | cur | ) | [static] |
Definition at line 1368 of file chan_iax2.c.
References ast_iax2_firmware_header::datalen, iax_firmware::fd, free, and iax_firmware::fwh.
Referenced by reload_firmware().
01369 { 01370 /* Close firmware */ 01371 if (cur->fwh) { 01372 munmap((void*)cur->fwh, ntohl(cur->fwh->datalen) + sizeof(*(cur->fwh))); 01373 } 01374 close(cur->fd); 01375 free(cur); 01376 }
static void destroy_peer | ( | struct iax2_peer * | peer | ) | [static] |
Definition at line 9093 of file chan_iax2.c.
References ast_dnsmgr_release(), ast_free_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_del(), ast_string_field_free_pools, iax2_peer::callno, iax2_peer::dnsmgr, iax2_peer::expire, free, iax2_peer::ha, iax2_destroy(), iaxsl, iax2_peer::pokeexpire, and register_peer_exten().
Referenced by authenticate_reply(), create_addr(), iax2_devicestate(), iax2_getpeername(), iax2_show_peer(), prune_peers(), realtime_peer(), register_verify(), registry_authrequest(), and update_registry().
09094 { 09095 ast_free_ha(peer->ha); 09096 09097 /* Delete it, it needs to disappear */ 09098 if (peer->expire > -1) 09099 ast_sched_del(sched, peer->expire); 09100 if (peer->pokeexpire > -1) 09101 ast_sched_del(sched, peer->pokeexpire); 09102 if (peer->callno > 0) { 09103 ast_mutex_lock(&iaxsl[peer->callno]); 09104 iax2_destroy(peer->callno); 09105 ast_mutex_unlock(&iaxsl[peer->callno]); 09106 } 09107 09108 register_peer_exten(peer, 0); 09109 09110 if (peer->dnsmgr) 09111 ast_dnsmgr_release(peer->dnsmgr); 09112 09113 ast_string_field_free_pools(peer); 09114 09115 free(peer); 09116 }
static void destroy_user | ( | struct iax2_user * | user | ) | [static] |
Definition at line 9065 of file chan_iax2.c.
References ast_free_ha(), ast_string_field_free_pools, ast_variables_destroy(), iax2_user::contexts, free, free_context(), iax2_user::ha, and iax2_user::vars.
Referenced by check_access(), and prune_users().
09066 { 09067 ast_free_ha(user->ha); 09068 free_context(user->contexts); 09069 if(user->vars) { 09070 ast_variables_destroy(user->vars); 09071 user->vars = NULL; 09072 } 09073 ast_string_field_free_pools(user); 09074 free(user); 09075 }
static void dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid, | |||
int | skiplock | |||
) | [static] |
Definition at line 6108 of file chan_iax2.c.
References ast_canmatch_extension(), ast_exists_extension(), AST_FRAME_IAX, ast_ignore_pattern(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), iax_ie_data::buf, IAX_COMMAND_DPREP, IAX_DPSTATUS_CANEXIST, IAX_DPSTATUS_EXISTS, IAX_DPSTATUS_IGNOREPAT, IAX_DPSTATUS_MATCHMORE, IAX_DPSTATUS_NONEXISTENT, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLED_NUMBER, IAX_IE_DPSTATUS, IAX_IE_REFRESH, iaxs, iaxsl, iax_ie_data::pos, and send_command().
Referenced by dp_lookup_thread(), and socket_process().
06109 { 06110 unsigned short dpstatus = 0; 06111 struct iax_ie_data ied1; 06112 int mm; 06113 06114 memset(&ied1, 0, sizeof(ied1)); 06115 mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); 06116 /* Must be started */ 06117 if (!strcmp(callednum, ast_parking_ext()) || ast_exists_extension(NULL, context, callednum, 1, callerid)) { 06118 dpstatus = IAX_DPSTATUS_EXISTS; 06119 } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { 06120 dpstatus = IAX_DPSTATUS_CANEXIST; 06121 } else { 06122 dpstatus = IAX_DPSTATUS_NONEXISTENT; 06123 } 06124 if (ast_ignore_pattern(context, callednum)) 06125 dpstatus |= IAX_DPSTATUS_IGNOREPAT; 06126 if (mm) 06127 dpstatus |= IAX_DPSTATUS_MATCHMORE; 06128 if (!skiplock) 06129 ast_mutex_lock(&iaxsl[callno]); 06130 if (iaxs[callno]) { 06131 iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); 06132 iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); 06133 iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); 06134 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); 06135 } 06136 if (!skiplock) 06137 ast_mutex_unlock(&iaxsl[callno]); 06138 }
static void* dp_lookup_thread | ( | void * | data | ) | [static] |
Definition at line 6140 of file chan_iax2.c.
References dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup(), and free.
Referenced by spawn_dp_lookup().
06141 { 06142 /* Look up for dpreq */ 06143 struct dpreq_data *dpr = data; 06144 dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0); 06145 if (dpr->callerid) 06146 free(dpr->callerid); 06147 free(dpr); 06148 return NULL; 06149 }
static int encrypt_frame | ( | aes_encrypt_ctx * | ecx, | |
struct ast_iax2_full_hdr * | fh, | |||
unsigned char * | poo, | |||
int * | datalen | |||
) | [static] |
Definition at line 3805 of file chan_iax2.c.
References ast_log(), ast_iax2_full_hdr::csub, ast_iax2_mini_enc_hdr::encdata, ast_iax2_full_enc_hdr::encdata, IAX_FLAG_FULL, LOG_DEBUG, memcpy_encrypt(), option_debug, ast_iax2_full_hdr::scallno, and ast_iax2_full_hdr::type.
Referenced by iax2_send().
03806 { 03807 int padding; 03808 unsigned char *workspace; 03809 workspace = alloca(*datalen + 32); 03810 if (!workspace) 03811 return -1; 03812 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 03813 struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh; 03814 if (option_debug && iaxdebug) 03815 ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen); 03816 padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16); 03817 padding = 16 + (padding & 0xf); 03818 memcpy(workspace, poo, padding); 03819 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr)); 03820 workspace[15] &= 0xf0; 03821 workspace[15] |= (padding & 0xf); 03822 if (option_debug && iaxdebug) 03823 ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]); 03824 *datalen += padding; 03825 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx); 03826 if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr)) 03827 memcpy(poo, workspace + *datalen - 32, 32); 03828 } else { 03829 struct ast_iax2_mini_enc_hdr *efh = (struct ast_iax2_mini_enc_hdr *)fh; 03830 if (option_debug && iaxdebug) 03831 ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen); 03832 padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16); 03833 padding = 16 + (padding & 0xf); 03834 memcpy(workspace, poo, padding); 03835 memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr)); 03836 workspace[15] &= 0xf0; 03837 workspace[15] |= (padding & 0x0f); 03838 *datalen += padding; 03839 memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx); 03840 if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr)) 03841 memcpy(poo, workspace + *datalen - 32, 32); 03842 } 03843 return 0; 03844 }
static int expire_registry | ( | void * | data | ) | [static] |
Definition at line 5608 of file chan_iax2.c.
References __expire_registry(), and schedule_action.
Referenced by iax2_prune_realtime(), realtime_peer(), reg_source_db(), and update_registry().
05609 { 05610 #ifdef SCHED_MULTITHREADED 05611 if (schedule_action(__expire_registry, data)) 05612 #endif 05613 __expire_registry(data); 05614 return 0; 05615 }
static struct iax2_dpcache* find_cache | ( | struct ast_channel * | chan, | |
const char * | data, | |||
const char * | context, | |||
const char * | exten, | |||
int | priority | |||
) | [static, read] |
Definition at line 9620 of file chan_iax2.c.
References ast_calloc, ast_channel_defer_dtmf(), ast_channel_undefer_dtmf(), ast_frfree(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_test_flag, ast_waitfor_nandfds(), CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, cache_get_callno_locked(), iax2_dpcache::callno, dpcache, chan_iax2_pvt::dpentries, iax2_dpcache::expiry, iax2_dpcache::exten, f, iax2_dpcache::flags, free, iax2_dprequest(), IAX_STATE_STARTED, iaxs, iaxsl, LOG_WARNING, iax2_dpcache::next, iax2_dpcache::orig, iax2_dpcache::peer, iax2_dpcache::peercontext, and iax2_dpcache::waiters.
Referenced by iax2_canmatch(), iax2_exec(), iax2_exists(), and iax2_matchmore().
09621 { 09622 struct iax2_dpcache *dp, *prev = NULL, *next; 09623 struct timeval tv; 09624 int x; 09625 int com[2]; 09626 int timeout; 09627 int old=0; 09628 int outfd; 09629 int abort; 09630 int callno; 09631 struct ast_channel *c; 09632 struct ast_frame *f; 09633 gettimeofday(&tv, NULL); 09634 dp = dpcache; 09635 while(dp) { 09636 next = dp->next; 09637 /* Expire old caches */ 09638 if (ast_tvcmp(tv, dp->expiry) > 0) { 09639 /* It's expired, let it disappear */ 09640 if (prev) 09641 prev->next = dp->next; 09642 else 09643 dpcache = dp->next; 09644 if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) { 09645 /* Free memory and go again */ 09646 free(dp); 09647 } else { 09648 ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = %p callno = %d)\n", dp->flags, dp->peer, dp->callno); 09649 } 09650 dp = next; 09651 continue; 09652 } 09653 /* We found an entry that matches us! */ 09654 if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten)) 09655 break; 09656 prev = dp; 09657 dp = next; 09658 } 09659 if (!dp) { 09660 /* No matching entry. Create a new one. */ 09661 /* First, can we make a callno? */ 09662 callno = cache_get_callno_locked(data); 09663 if (callno < 0) { 09664 ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data); 09665 return NULL; 09666 } 09667 if (!(dp = ast_calloc(1, sizeof(*dp)))) { 09668 ast_mutex_unlock(&iaxsl[callno]); 09669 return NULL; 09670 } 09671 ast_copy_string(dp->peercontext, data, sizeof(dp->peercontext)); 09672 ast_copy_string(dp->exten, exten, sizeof(dp->exten)); 09673 gettimeofday(&dp->expiry, NULL); 09674 dp->orig = dp->expiry; 09675 /* Expires in 30 mins by default */ 09676 dp->expiry.tv_sec += iaxdefaultdpcache; 09677 dp->next = dpcache; 09678 dp->flags = CACHE_FLAG_PENDING; 09679 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 09680 dp->waiters[x] = -1; 09681 dpcache = dp; 09682 dp->peer = iaxs[callno]->dpentries; 09683 iaxs[callno]->dpentries = dp; 09684 /* Send the request if we're already up */ 09685 if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 09686 iax2_dprequest(dp, callno); 09687 ast_mutex_unlock(&iaxsl[callno]); 09688 } 09689 /* By here we must have a dp */ 09690 if (dp->flags & CACHE_FLAG_PENDING) { 09691 /* Okay, here it starts to get nasty. We need a pipe now to wait 09692 for a reply to come back so long as it's pending */ 09693 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) { 09694 /* Find an empty slot */ 09695 if (dp->waiters[x] < 0) 09696 break; 09697 } 09698 if (x >= sizeof(dp->waiters) / sizeof(dp->waiters[0])) { 09699 ast_log(LOG_WARNING, "No more waiter positions available\n"); 09700 return NULL; 09701 } 09702 if (pipe(com)) { 09703 ast_log(LOG_WARNING, "Unable to create pipe for comm\n"); 09704 return NULL; 09705 } 09706 dp->waiters[x] = com[1]; 09707 /* Okay, now we wait */ 09708 timeout = iaxdefaulttimeout * 1000; 09709 /* Temporarily unlock */ 09710 ast_mutex_unlock(&dpcache_lock); 09711 /* Defer any dtmf */ 09712 if (chan) 09713 old = ast_channel_defer_dtmf(chan); 09714 abort = 0; 09715 while(timeout) { 09716 c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout); 09717 if (outfd > -1) { 09718 break; 09719 } 09720 if (c) { 09721 f = ast_read(c); 09722 if (f) 09723 ast_frfree(f); 09724 else { 09725 /* Got hung up on, abort! */ 09726 break; 09727 abort = 1; 09728 } 09729 } 09730 } 09731 if (!timeout) { 09732 ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten); 09733 } 09734 ast_mutex_lock(&dpcache_lock); 09735 dp->waiters[x] = -1; 09736 close(com[1]); 09737 close(com[0]); 09738 if (abort) { 09739 /* Don't interpret anything, just abort. Not sure what th epoint 09740 of undeferring dtmf on a hung up channel is but hey whatever */ 09741 if (!old && chan) 09742 ast_channel_undefer_dtmf(chan); 09743 return NULL; 09744 } 09745 if (!(dp->flags & CACHE_FLAG_TIMEOUT)) { 09746 /* Now to do non-independent analysis the results of our wait */ 09747 if (dp->flags & CACHE_FLAG_PENDING) { 09748 /* Still pending... It's a timeout. Wake everybody up. Consider it no longer 09749 pending. Don't let it take as long to timeout. */ 09750 dp->flags &= ~CACHE_FLAG_PENDING; 09751 dp->flags |= CACHE_FLAG_TIMEOUT; 09752 /* Expire after only 60 seconds now. This is designed to help reduce backlog in heavily loaded 09753 systems without leaving it unavailable once the server comes back online */ 09754 dp->expiry.tv_sec = dp->orig.tv_sec + 60; 09755 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 09756 if (dp->waiters[x] > -1) 09757 write(dp->waiters[x], "asdf", 4); 09758 } 09759 } 09760 /* Our caller will obtain the rest */ 09761 if (!old && chan) 09762 ast_channel_undefer_dtmf(chan); 09763 } 09764 return dp; 09765 }
static int find_callno | ( | unsigned short | callno, | |
unsigned short | dcallno, | |||
struct sockaddr_in * | sin, | |||
int | new, | |||
int | lockpeer, | |||
int | sockfd | |||
) | [static] |
Definition at line 1247 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::amaflags, ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_string_field_set, chan_iax2_pvt::callno, DEFAULT_RETRY_TIME, chan_iax2_pvt::expiry, iax2_getpeername(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, match(), MIN_REUSE_TIME, NEW_ALLOW, new_iax(), option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, chan_iax2_pvt::pingtime, send_lagrq(), send_ping(), chan_iax2_pvt::sockfd, TRUNK_CALL_START, and update_max_nontrunk().
Referenced by cache_get_callno_locked(), iax2_do_register(), iax2_poke_peer(), iax2_provision(), iax2_request(), and socket_process().
01248 { 01249 int res = 0; 01250 int x; 01251 struct timeval now; 01252 char host[80]; 01253 01254 if (new <= NEW_ALLOW) { 01255 /* Look for an existing connection first */ 01256 for (x=1;(res < 1) && (x<maxnontrunkcall);x++) { 01257 ast_mutex_lock(&iaxsl[x]); 01258 if (iaxs[x]) { 01259 /* Look for an exact match */ 01260 if (match(sin, callno, dcallno, iaxs[x])) { 01261 res = x; 01262 } 01263 } 01264 ast_mutex_unlock(&iaxsl[x]); 01265 } 01266 for (x=TRUNK_CALL_START;(res < 1) && (x<maxtrunkcall);x++) { 01267 ast_mutex_lock(&iaxsl[x]); 01268 if (iaxs[x]) { 01269 /* Look for an exact match */ 01270 if (match(sin, callno, dcallno, iaxs[x])) { 01271 res = x; 01272 } 01273 } 01274 ast_mutex_unlock(&iaxsl[x]); 01275 } 01276 } 01277 if ((res < 1) && (new >= NEW_ALLOW)) { 01278 /* It may seem odd that we look through the peer list for a name for 01279 * this *incoming* call. Well, it is weird. However, users don't 01280 * have an IP address/port number that we can match against. So, 01281 * this is just checking for a peer that has that IP/port and 01282 * assuming that we have a user of the same name. This isn't always 01283 * correct, but it will be changed if needed after authentication. */ 01284 if (!iax2_getpeername(*sin, host, sizeof(host), lockpeer)) 01285 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 01286 gettimeofday(&now, NULL); 01287 for (x=1;x<TRUNK_CALL_START;x++) { 01288 /* Find first unused call number that hasn't been used in a while */ 01289 ast_mutex_lock(&iaxsl[x]); 01290 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) break; 01291 ast_mutex_unlock(&iaxsl[x]); 01292 } 01293 /* We've still got lock held if we found a spot */ 01294 if (x >= TRUNK_CALL_START) { 01295 ast_log(LOG_WARNING, "No more space\n"); 01296 return 0; 01297 } 01298 iaxs[x] = new_iax(sin, lockpeer, host); 01299 update_max_nontrunk(); 01300 if (iaxs[x]) { 01301 if (option_debug && iaxdebug) 01302 ast_log(LOG_DEBUG, "Creating new call structure %d\n", x); 01303 iaxs[x]->sockfd = sockfd; 01304 iaxs[x]->addr.sin_port = sin->sin_port; 01305 iaxs[x]->addr.sin_family = sin->sin_family; 01306 iaxs[x]->addr.sin_addr.s_addr = sin->sin_addr.s_addr; 01307 iaxs[x]->peercallno = callno; 01308 iaxs[x]->callno = x; 01309 iaxs[x]->pingtime = DEFAULT_RETRY_TIME; 01310 iaxs[x]->expiry = min_reg_expire; 01311 iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01312 iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01313 iaxs[x]->amaflags = amaflags; 01314 ast_copy_flags(iaxs[x], (&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 01315 01316 ast_string_field_set(iaxs[x], accountcode, accountcode); 01317 ast_string_field_set(iaxs[x], mohinterpret, mohinterpret); 01318 ast_string_field_set(iaxs[x], mohsuggest, mohsuggest); 01319 } else { 01320 ast_log(LOG_WARNING, "Out of resources\n"); 01321 ast_mutex_unlock(&iaxsl[x]); 01322 return 0; 01323 } 01324 ast_mutex_unlock(&iaxsl[x]); 01325 res = x; 01326 } 01327 return res; 01328 }
static struct iax2_thread* find_idle_thread | ( | void | ) | [static, read] |
Definition at line 877 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_init(), ast_pthread_create, iax2_thread::ffinfo, free, iax2_process_thread(), IAX_TYPE_DYNAMIC, iaxdynamicthreadcount, iaxmaxthreadcount, and thread.
Referenced by __schedule_action(), and socket_read().
00878 { 00879 pthread_attr_t attr; 00880 struct iax2_thread *thread = NULL; 00881 00882 /* Pop the head of the list off */ 00883 AST_LIST_LOCK(&idle_list); 00884 thread = AST_LIST_REMOVE_HEAD(&idle_list, list); 00885 AST_LIST_UNLOCK(&idle_list); 00886 00887 /* If no idle thread is available from the regular list, try dynamic */ 00888 if (thread == NULL) { 00889 AST_LIST_LOCK(&dynamic_list); 00890 thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list); 00891 /* Make sure we absolutely have a thread... if not, try to make one if allowed */ 00892 if (thread == NULL && iaxmaxthreadcount > iaxdynamicthreadcount) { 00893 /* We need to MAKE a thread! */ 00894 if ((thread = ast_calloc(1, sizeof(*thread)))) { 00895 thread->threadnum = iaxdynamicthreadcount; 00896 thread->type = IAX_TYPE_DYNAMIC; 00897 ast_mutex_init(&thread->lock); 00898 ast_cond_init(&thread->cond, NULL); 00899 pthread_attr_init(&attr); 00900 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00901 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 00902 free(thread); 00903 thread = NULL; 00904 } else { 00905 /* All went well and the thread is up, so increment our count */ 00906 iaxdynamicthreadcount++; 00907 00908 /* Wait for the thread to be ready before returning it to the caller */ 00909 while (!thread->ready_for_signal) 00910 usleep(1); 00911 } 00912 } 00913 } 00914 AST_LIST_UNLOCK(&dynamic_list); 00915 } 00916 00917 /* this thread is not processing a full frame (since it is idle), 00918 so ensure that the field for the full frame call number is empty */ 00919 if (thread) 00920 memset(&thread->ffinfo, 0, sizeof(thread->ffinfo)); 00921 00922 return thread; 00923 }
static struct iax2_peer* find_peer | ( | const char * | name, | |
int | realtime | |||
) | [static, read] |
Definition at line 1045 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and realtime_peer().
01046 { 01047 struct iax2_peer *peer = NULL; 01048 01049 /* Grab peer from linked list */ 01050 AST_LIST_LOCK(&peers); 01051 AST_LIST_TRAVERSE(&peers, peer, entry) { 01052 if (!strcasecmp(peer->name, name)) { 01053 break; 01054 } 01055 } 01056 AST_LIST_UNLOCK(&peers); 01057 01058 /* Now go for realtime if applicable */ 01059 if(!peer && realtime) 01060 peer = realtime_peer(name, NULL); 01061 return peer; 01062 }
static struct iax2_trunk_peer* find_tpeer | ( | struct sockaddr_in * | sin, | |
int | fd | |||
) | [static, read] |
Definition at line 3616 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_calloc, ast_inet_ntoa(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), inaddrcmp(), iax2_trunk_peer::lastsent, iax2_trunk_peer::lock, LOG_DEBUG, iax2_trunk_peer::next, iax2_trunk_peer::sockfd, tpeers, and iax2_trunk_peer::trunkact.
Referenced by iax2_trunk_queue(), and socket_process().
03617 { 03618 struct iax2_trunk_peer *tpeer; 03619 03620 /* Finds and locks trunk peer */ 03621 ast_mutex_lock(&tpeerlock); 03622 for (tpeer = tpeers; tpeer; tpeer = tpeer->next) { 03623 /* We don't lock here because tpeer->addr *never* changes */ 03624 if (!inaddrcmp(&tpeer->addr, sin)) { 03625 ast_mutex_lock(&tpeer->lock); 03626 break; 03627 } 03628 } 03629 if (!tpeer) { 03630 if ((tpeer = ast_calloc(1, sizeof(*tpeer)))) { 03631 ast_mutex_init(&tpeer->lock); 03632 tpeer->lastsent = 9999; 03633 memcpy(&tpeer->addr, sin, sizeof(tpeer->addr)); 03634 tpeer->trunkact = ast_tvnow(); 03635 ast_mutex_lock(&tpeer->lock); 03636 tpeer->next = tpeers; 03637 tpeer->sockfd = fd; 03638 tpeers = tpeer; 03639 #ifdef SO_NO_CHECK 03640 setsockopt(tpeer->sockfd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); 03641 #endif 03642 ast_log(LOG_DEBUG, "Created trunk peer for '%s:%d'\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port)); 03643 } 03644 } 03645 ast_mutex_unlock(&tpeerlock); 03646 return tpeer; 03647 }
static unsigned int fix_peerts | ( | struct timeval * | tv, | |
int | callno, | |||
unsigned int | ts | |||
) | [static] |
Definition at line 3443 of file chan_iax2.c.
References iaxs, and chan_iax2_pvt::rxcore.
Referenced by socket_process().
03444 { 03445 long ms; /* NOT unsigned */ 03446 if (ast_tvzero(iaxs[callno]->rxcore)) { 03447 /* Initialize rxcore time if appropriate */ 03448 gettimeofday(&iaxs[callno]->rxcore, NULL); 03449 /* Round to nearest 20ms so traces look pretty */ 03450 iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000; 03451 } 03452 /* Calculate difference between trunk and channel */ 03453 ms = ast_tvdiff_ms(*tv, iaxs[callno]->rxcore); 03454 /* Return as the sum of trunk time and the difference between trunk and real time */ 03455 return ms + ts; 03456 }
static void free_context | ( | struct iax2_context * | con | ) | [static] |
Definition at line 8225 of file chan_iax2.c.
References free, and iax2_context::next.
Referenced by build_user(), and destroy_user().
08226 { 08227 struct iax2_context *conl; 08228 while(con) { 08229 conl = con; 08230 con = con->next; 08231 free(conl); 08232 } 08233 }
static int function_iaxpeer | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 9889 of file chan_iax2.c.
References iax2_peer::addr, ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strdupa, ast_test_flag, iax2_peer::capability, iax2_peer::expire, find_peer(), iax2_tech, IAX_DYNAMIC, iaxs, peer_status(), iax2_peer::prefs, PTR_TO_CALLNO, ast_channel::tech, and ast_channel::tech_pvt.
09890 { 09891 struct iax2_peer *peer; 09892 char *peername, *colname; 09893 09894 peername = ast_strdupa(data); 09895 09896 /* if our channel, return the IP address of the endpoint of current channel */ 09897 if (!strcmp(peername,"CURRENTCHANNEL")) { 09898 unsigned short callno; 09899 if (chan->tech != &iax2_tech) 09900 return -1; 09901 callno = PTR_TO_CALLNO(chan->tech_pvt); 09902 ast_copy_string(buf, iaxs[callno]->addr.sin_addr.s_addr ? ast_inet_ntoa(iaxs[callno]->addr.sin_addr) : "", len); 09903 return 0; 09904 } 09905 09906 if ((colname = strchr(peername, ':'))) /*! \todo : will be removed after the 1.4 relese */ 09907 *colname++ = '\0'; 09908 else if ((colname = strchr(peername, '|'))) 09909 *colname++ = '\0'; 09910 else 09911 colname = "ip"; 09912 09913 if (!(peer = find_peer(peername, 1))) 09914 return -1; 09915 09916 if (!strcasecmp(colname, "ip")) { 09917 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 09918 } else if (!strcasecmp(colname, "status")) { 09919 peer_status(peer, buf, len); 09920 } else if (!strcasecmp(colname, "mailbox")) { 09921 ast_copy_string(buf, peer->mailbox, len); 09922 } else if (!strcasecmp(colname, "context")) { 09923 ast_copy_string(buf, peer->context, len); 09924 } else if (!strcasecmp(colname, "expire")) { 09925 snprintf(buf, len, "%d", peer->expire); 09926 } else if (!strcasecmp(colname, "dynamic")) { 09927 ast_copy_string(buf, (ast_test_flag(peer, IAX_DYNAMIC) ? "yes" : "no"), len); 09928 } else if (!strcasecmp(colname, "callerid_name")) { 09929 ast_copy_string(buf, peer->cid_name, len); 09930 } else if (!strcasecmp(colname, "callerid_num")) { 09931 ast_copy_string(buf, peer->cid_num, len); 09932 } else if (!strcasecmp(colname, "codecs")) { 09933 ast_getformatname_multiple(buf, len -1, peer->capability); 09934 } else if (!strncasecmp(colname, "codec[", 6)) { 09935 char *codecnum, *ptr; 09936 int index = 0, codec = 0; 09937 09938 codecnum = strchr(colname, '['); 09939 *codecnum = '\0'; 09940 codecnum++; 09941 if ((ptr = strchr(codecnum, ']'))) { 09942 *ptr = '\0'; 09943 } 09944 index = atoi(codecnum); 09945 if((codec = ast_codec_pref_index(&peer->prefs, index))) { 09946 ast_copy_string(buf, ast_getformatname(codec), len); 09947 } 09948 } 09949 09950 return 0; 09951 }
static int get_auth_methods | ( | char * | value | ) | [static] |
Definition at line 8454 of file chan_iax2.c.
References IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, and IAX_AUTH_RSA.
Referenced by build_peer(), and build_user().
08455 { 08456 int methods = 0; 08457 if (strstr(value, "rsa")) 08458 methods |= IAX_AUTH_RSA; 08459 if (strstr(value, "md5")) 08460 methods |= IAX_AUTH_MD5; 08461 if (strstr(value, "plaintext")) 08462 methods |= IAX_AUTH_PLAINTEXT; 08463 return methods; 08464 }
static int get_encrypt_methods | ( | const char * | s | ) | [static] |
Definition at line 976 of file chan_iax2.c.
References ast_true(), and IAX_ENCRYPT_AES128.
Referenced by build_peer(), build_user(), and set_config().
00977 { 00978 int e; 00979 if (!strcasecmp(s, "aes128")) 00980 e = IAX_ENCRYPT_AES128; 00981 else if (ast_true(s)) 00982 e = IAX_ENCRYPT_AES128; 00983 else 00984 e = 0; 00985 return e; 00986 }
static int get_from_jb | ( | void * | p | ) | [static] |
Definition at line 2348 of file chan_iax2.c.
References __get_from_jb(), and schedule_action.
Referenced by update_jbsched().
02349 { 02350 #ifdef SCHED_MULTITHREADED 02351 if (schedule_action(__get_from_jb, data)) 02352 #endif 02353 __get_from_jb(data); 02354 return 0; 02355 }
static void handle_deferred_full_frames | ( | struct iax2_thread * | thread | ) | [static] |
Handle any deferred full frames for this thread.
Definition at line 6306 of file chan_iax2.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), and socket_process().
Referenced by iax2_process_thread().
06307 { 06308 struct iax2_pkt_buf *pkt_buf; 06309 06310 ast_mutex_lock(&thread->lock); 06311 06312 while ((pkt_buf = AST_LIST_REMOVE_HEAD(&thread->full_frames, entry))) { 06313 ast_mutex_unlock(&thread->lock); 06314 06315 thread->buf = pkt_buf->buf; 06316 thread->buf_len = pkt_buf->len; 06317 thread->buf_size = pkt_buf->len + 1; 06318 06319 socket_process(thread); 06320 06321 thread->buf = NULL; 06322 ast_free(pkt_buf); 06323 06324 ast_mutex_lock(&thread->lock); 06325 } 06326 06327 ast_mutex_unlock(&thread->lock); 06328 }
static int handle_error | ( | void | ) | [static] |
Definition at line 1653 of file chan_iax2.c.
References ast_inet_ntoa(), ast_log(), LOG_WARNING, and netsocket.
Referenced by send_packet(), socket_read(), and transmit_trunk().
01654 { 01655 /* XXX Ideally we should figure out why an error occured and then abort those 01656 rather than continuing to try. Unfortunately, the published interface does 01657 not seem to work XXX */ 01658 #if 0 01659 struct sockaddr_in *sin; 01660 int res; 01661 struct msghdr m; 01662 struct sock_extended_err e; 01663 m.msg_name = NULL; 01664 m.msg_namelen = 0; 01665 m.msg_iov = NULL; 01666 m.msg_control = &e; 01667 m.msg_controllen = sizeof(e); 01668 m.msg_flags = 0; 01669 res = recvmsg(netsocket, &m, MSG_ERRQUEUE); 01670 if (res < 0) 01671 ast_log(LOG_WARNING, "Error detected, but unable to read error: %s\n", strerror(errno)); 01672 else { 01673 if (m.msg_controllen) { 01674 sin = (struct sockaddr_in *)SO_EE_OFFENDER(&e); 01675 if (sin) 01676 ast_log(LOG_WARNING, "Receive error from %s\n", ast_inet_ntoa(sin->sin_addr)); 01677 else 01678 ast_log(LOG_WARNING, "No address detected??\n"); 01679 } else { 01680 ast_log(LOG_WARNING, "Local error: %s\n", strerror(e.ee_errno)); 01681 } 01682 } 01683 #endif 01684 return 0; 01685 }
static int iax2_ack_registry | ( | struct iax_ies * | ies, | |
struct sockaddr_in * | sin, | |||
int | callno | |||
) | [static] |
Acknowledgment received for OUR registration.
Definition at line 5437 of file chan_iax2.c.
References iax2_registry::addr, iax_ies::apparent_addr, ast_inet_ntoa(), ast_log(), ast_sched_add(), ast_sched_del(), ast_verbose(), iax_ies::calling_number, EVENT_FLAG_SYSTEM, iax2_registry::expire, iax2_do_register_s(), iaxs, inaddrcmp(), LOG_WARNING, manager_event(), iax2_registry::messages, iax_ies::msgcount, option_verbose, iax_ies::refresh, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGISTERED, iax2_registry::regstate, iax2_registry::us, iax_ies::username, and VERBOSE_PREFIX_3.
Referenced by socket_process().
05438 { 05439 struct iax2_registry *reg; 05440 /* Start pessimistic */ 05441 char peer[256] = ""; 05442 char msgstatus[60]; 05443 int refresh = 60; 05444 char ourip[256] = "<Unspecified>"; 05445 struct sockaddr_in oldus; 05446 struct sockaddr_in us; 05447 int oldmsgs; 05448 05449 memset(&us, 0, sizeof(us)); 05450 if (ies->apparent_addr) 05451 bcopy(ies->apparent_addr, &us, sizeof(us)); 05452 if (ies->username) 05453 ast_copy_string(peer, ies->username, sizeof(peer)); 05454 if (ies->refresh) 05455 refresh = ies->refresh; 05456 if (ies->calling_number) { 05457 /* We don't do anything with it really, but maybe we should */ 05458 } 05459 reg = iaxs[callno]->reg; 05460 if (!reg) { 05461 ast_log(LOG_WARNING, "Registry acknowledge on unknown registry '%s'\n", peer); 05462 return -1; 05463 } 05464 memcpy(&oldus, ®->us, sizeof(oldus)); 05465 oldmsgs = reg->messages; 05466 if (inaddrcmp(®->addr, sin)) { 05467 ast_log(LOG_WARNING, "Received unsolicited registry ack from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 05468 return -1; 05469 } 05470 memcpy(®->us, &us, sizeof(reg->us)); 05471 if (ies->msgcount >= 0) 05472 reg->messages = ies->msgcount & 0xffff; /* only low 16 bits are used in the transmission of the IE */ 05473 /* always refresh the registration at the interval requested by the server 05474 we are registering to 05475 */ 05476 reg->refresh = refresh; 05477 if (reg->expire > -1) 05478 ast_sched_del(sched, reg->expire); 05479 reg->expire = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 05480 if (inaddrcmp(&oldus, ®->us) || (reg->messages != oldmsgs)) { 05481 if (option_verbose > 2) { 05482 if (reg->messages > 255) 05483 snprintf(msgstatus, sizeof(msgstatus), " with %d new and %d old messages waiting", reg->messages & 0xff, reg->messages >> 8); 05484 else if (reg->messages > 1) 05485 snprintf(msgstatus, sizeof(msgstatus), " with %d new messages waiting\n", reg->messages); 05486 else if (reg->messages > 0) 05487 snprintf(msgstatus, sizeof(msgstatus), " with 1 new message waiting\n"); 05488 else 05489 snprintf(msgstatus, sizeof(msgstatus), " with no messages waiting\n"); 05490 snprintf(ourip, sizeof(ourip), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 05491 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 to '%s', who sees us as %s%s\n", ast_inet_ntoa(sin->sin_addr), ourip, msgstatus); 05492 } 05493 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nDomain: %s\r\nStatus: Registered\r\n", ast_inet_ntoa(sin->sin_addr)); 05494 } 05495 reg->regstate = REG_STATE_REGISTERED; 05496 return 0; 05497 }
static int iax2_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3264 of file chan_iax2.c.
References AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_log(), LOG_DEBUG, option_debug, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03265 { 03266 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03267 if (option_debug) 03268 ast_log(LOG_DEBUG, "Answering IAX2 call\n"); 03269 return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); 03270 }
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 3114 of file chan_iax2.c.
References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), AST_SOFTHANGUP_DEV, ast_test_flag, ast_verbose(), ast_waitfor_n(), ast_write(), chan_iax2_pvt::bridgecallno, f, ast_frame::frametype, iax2_start_transfer(), iax2_tech, IAX_LINGER_TIMEOUT, IAX_NOTRANSFER, IAX_TRANSFERMEDIA, iaxs, iaxsl, lock_both(), LOG_WARNING, ast_channel::nativeformats, option_verbose, PTR_TO_CALLNO, ast_channel::tech, ast_channel::tech_pvt, TRANSFER_RELEASED, tv, unlock_both(), and VERBOSE_PREFIX_3.
03115 { 03116 struct ast_channel *cs[3]; 03117 struct ast_channel *who, *other; 03118 int to = -1; 03119 int res = -1; 03120 int transferstarted=0; 03121 struct ast_frame *f; 03122 unsigned short callno0 = PTR_TO_CALLNO(c0->tech_pvt); 03123 unsigned short callno1 = PTR_TO_CALLNO(c1->tech_pvt); 03124 struct timeval waittimer = {0, 0}, tv; 03125 03126 lock_both(callno0, callno1); 03127 if (!iaxs[callno0] || !iaxs[callno1]) { 03128 unlock_both(callno0, callno1); 03129 return AST_BRIDGE_FAILED; 03130 } 03131 /* Put them in native bridge mode */ 03132 if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) { 03133 iaxs[callno0]->bridgecallno = callno1; 03134 iaxs[callno1]->bridgecallno = callno0; 03135 } 03136 unlock_both(callno0, callno1); 03137 03138 /* If not, try to bridge until we can execute a transfer, if we can */ 03139 cs[0] = c0; 03140 cs[1] = c1; 03141 for (/* ever */;;) { 03142 /* Check in case we got masqueraded into */ 03143 if ((c0->tech != &iax2_tech) || (c1->tech != &iax2_tech)) { 03144 if (option_verbose > 2) 03145 ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n"); 03146 /* Remove from native mode */ 03147 if (c0->tech == &iax2_tech) { 03148 ast_mutex_lock(&iaxsl[callno0]); 03149 iaxs[callno0]->bridgecallno = 0; 03150 ast_mutex_unlock(&iaxsl[callno0]); 03151 } 03152 if (c1->tech == &iax2_tech) { 03153 ast_mutex_lock(&iaxsl[callno1]); 03154 iaxs[callno1]->bridgecallno = 0; 03155 ast_mutex_unlock(&iaxsl[callno1]); 03156 } 03157 return AST_BRIDGE_FAILED_NOWARN; 03158 } 03159 if (c0->nativeformats != c1->nativeformats) { 03160 if (option_verbose > 2) { 03161 char buf0[255]; 03162 char buf1[255]; 03163 ast_getformatname_multiple(buf0, sizeof(buf0) -1, c0->nativeformats); 03164 ast_getformatname_multiple(buf1, sizeof(buf1) -1, c1->nativeformats); 03165 ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs %d[%s] %d[%s] , can't native bridge...\n", c0->nativeformats, buf0, c1->nativeformats, buf1); 03166 } 03167 /* Remove from native mode */ 03168 lock_both(callno0, callno1); 03169 if (iaxs[callno0]) 03170 iaxs[callno0]->bridgecallno = 0; 03171 if (iaxs[callno1]) 03172 iaxs[callno1]->bridgecallno = 0; 03173 unlock_both(callno0, callno1); 03174 return AST_BRIDGE_FAILED_NOWARN; 03175 } 03176 /* check if transfered and if we really want native bridging */ 03177 if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER)) { 03178 /* Try the transfer */ 03179 if (iax2_start_transfer(callno0, callno1, (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) || 03180 ast_test_flag(iaxs[callno0], IAX_TRANSFERMEDIA) | ast_test_flag(iaxs[callno1], IAX_TRANSFERMEDIA))) 03181 ast_log(LOG_WARNING, "Unable to start the transfer\n"); 03182 transferstarted = 1; 03183 } 03184 if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) { 03185 /* Call has been transferred. We're no longer involved */ 03186 gettimeofday(&tv, NULL); 03187 if (ast_tvzero(waittimer)) { 03188 waittimer = tv; 03189 } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { 03190 c0->_softhangup |= AST_SOFTHANGUP_DEV; 03191 c1->_softhangup |= AST_SOFTHANGUP_DEV; 03192 *fo = NULL; 03193 *rc = c0; 03194 res = AST_BRIDGE_COMPLETE; 03195 break; 03196 } 03197 } 03198 to = 1000; 03199 who = ast_waitfor_n(cs, 2, &to); 03200 if (timeoutms > -1) { 03201 timeoutms -= (1000 - to); 03202 if (timeoutms < 0) 03203 timeoutms = 0; 03204 } 03205 if (!who) { 03206 if (!timeoutms) { 03207 res = AST_BRIDGE_RETRY; 03208 break; 03209 } 03210 if (ast_check_hangup(c0) || ast_check_hangup(c1)) { 03211 res = AST_BRIDGE_FAILED; 03212 break; 03213 } 03214 continue; 03215 } 03216 f = ast_read(who); 03217 if (!f) { 03218 *fo = NULL; 03219 *rc = who; 03220 res = AST_BRIDGE_COMPLETE; 03221 break; 03222 } 03223 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { 03224 *fo = f; 03225 *rc = who; 03226 res = AST_BRIDGE_COMPLETE; 03227 break; 03228 } 03229 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 03230 if ((f->frametype == AST_FRAME_VOICE) || 03231 (f->frametype == AST_FRAME_TEXT) || 03232 (f->frametype == AST_FRAME_VIDEO) || 03233 (f->frametype == AST_FRAME_IMAGE) || 03234 (f->frametype == AST_FRAME_DTMF)) { 03235 /* monitored dtmf take out of the bridge. 03236 * check if we monitor the specific source. 03237 */ 03238 int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1; 03239 if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) { 03240 *rc = who; 03241 *fo = f; 03242 res = AST_BRIDGE_COMPLETE; 03243 /* Remove from native mode */ 03244 break; 03245 } 03246 /* everything else goes to the other side */ 03247 ast_write(other, f); 03248 } 03249 ast_frfree(f); 03250 /* Swap who gets priority */ 03251 cs[2] = cs[0]; 03252 cs[0] = cs[1]; 03253 cs[1] = cs[2]; 03254 } 03255 lock_both(callno0, callno1); 03256 if(iaxs[callno0]) 03257 iaxs[callno0]->bridgecallno = 0; 03258 if(iaxs[callno1]) 03259 iaxs[callno1]->bridgecallno = 0; 03260 unlock_both(callno0, callno1); 03261 return res; 03262 }
static int iax2_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 2870 of file chan_iax2.c.
References ast_channel::_state, create_addr_info::adsi, chan_iax2_pvt::adsi, ast_channel::adsicpe, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PRES_NUMBER_NOT_AVAILABLE, ast_sched_add(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, auto_congest(), iax_ie_data::buf, CALLNO_TO_PTR, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, create_addr_info::context, ast_channel::context, parsed_dial_string::context, create_addr(), chan_iax2_pvt::encmethods, create_addr_info::encmethods, parsed_dial_string::exten, iax2_datetime(), IAX_COMMAND_NEW, IAX_IE_ADSICPE, iax_ie_append(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CAPABILITY, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DNID, IAX_IE_ENCRYPTION, IAX_IE_FORMAT, IAX_IE_LANGUAGE, IAX_IE_RDNIS, IAX_IE_USERNAME, IAX_IE_VERSION, IAX_PROTO_VERSION, IAX_SENDANI, iaxs, iaxsl, chan_iax2_pvt::initid, parsed_dial_string::key, LOG_WARNING, chan_iax2_pvt::maxtime, create_addr_info::maxtime, create_addr_info::mohinterpret, create_addr_info::mohsuggest, ast_channel::nativeformats, parsed_dial_string::options, create_addr_info::outkey, parse_dial_string(), parsed_dial_string::password, parsed_dial_string::peer, create_addr_info::peercontext, chan_iax2_pvt::pingtime, parsed_dial_string::port, iax_ie_data::pos, create_addr_info::prefs, PTR_TO_CALLNO, secret, create_addr_info::secret, send_command(), create_addr_info::sockfd, chan_iax2_pvt::sockfd, ast_channel::tech_pvt, create_addr_info::timezone, create_addr_info::username, and parsed_dial_string::username.
02871 { 02872 struct sockaddr_in sin; 02873 char *l=NULL, *n=NULL, *tmpstr; 02874 struct iax_ie_data ied; 02875 char *defaultrdest = "s"; 02876 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 02877 struct parsed_dial_string pds; 02878 struct create_addr_info cai; 02879 02880 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 02881 ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); 02882 return -1; 02883 } 02884 02885 memset(&cai, 0, sizeof(cai)); 02886 cai.encmethods = iax2_encryption; 02887 02888 memset(&pds, 0, sizeof(pds)); 02889 tmpstr = ast_strdupa(dest); 02890 parse_dial_string(tmpstr, &pds); 02891 02892 if (!pds.exten) 02893 pds.exten = defaultrdest; 02894 02895 if (create_addr(pds.peer, &sin, &cai)) { 02896 ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); 02897 return -1; 02898 } 02899 02900 if (!pds.username && !ast_strlen_zero(cai.username)) 02901 pds.username = cai.username; 02902 if (!pds.password && !ast_strlen_zero(cai.secret)) 02903 pds.password = cai.secret; 02904 if (!pds.key && !ast_strlen_zero(cai.outkey)) 02905 pds.key = cai.outkey; 02906 if (!pds.context && !ast_strlen_zero(cai.peercontext)) 02907 pds.context = cai.peercontext; 02908 02909 /* Keep track of the context for outgoing calls too */ 02910 ast_copy_string(c->context, cai.context, sizeof(c->context)); 02911 02912 if (pds.port) 02913 sin.sin_port = htons(atoi(pds.port)); 02914 02915 l = c->cid.cid_num; 02916 n = c->cid.cid_name; 02917 02918 /* Now build request */ 02919 memset(&ied, 0, sizeof(ied)); 02920 02921 /* On new call, first IE MUST be IAX version of caller */ 02922 iax_ie_append_short(&ied, IAX_IE_VERSION, IAX_PROTO_VERSION); 02923 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, pds.exten); 02924 if (pds.options && strchr(pds.options, 'a')) { 02925 /* Request auto answer */ 02926 iax_ie_append(&ied, IAX_IE_AUTOANSWER); 02927 } 02928 02929 iax_ie_append_str(&ied, IAX_IE_CODEC_PREFS, cai.prefs); 02930 02931 if (l) { 02932 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); 02933 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 02934 } else { 02935 if (n) 02936 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->cid.cid_pres); 02937 else 02938 iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE); 02939 } 02940 02941 iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->cid.cid_ton); 02942 iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns); 02943 02944 if (n) 02945 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); 02946 if (ast_test_flag(iaxs[callno], IAX_SENDANI) && c->cid.cid_ani) 02947 iax_ie_append_str(&ied, IAX_IE_CALLING_ANI, c->cid.cid_ani); 02948 02949 if (!ast_strlen_zero(c->language)) 02950 iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language); 02951 if (!ast_strlen_zero(c->cid.cid_dnid)) 02952 iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid); 02953 if (!ast_strlen_zero(c->cid.cid_rdnis)) 02954 iax_ie_append_str(&ied, IAX_IE_RDNIS, c->cid.cid_rdnis); 02955 02956 if (pds.context) 02957 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context); 02958 02959 if (pds.username) 02960 iax_ie_append_str(&ied, IAX_IE_USERNAME, pds.username); 02961 02962 if (cai.encmethods) 02963 iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, cai.encmethods); 02964 02965 ast_mutex_lock(&iaxsl[callno]); 02966 02967 if (!ast_strlen_zero(c->context)) 02968 ast_string_field_set(iaxs[callno], context, c->context); 02969 02970 if (pds.username) 02971 ast_string_field_set(iaxs[callno], username, pds.username); 02972 02973 iaxs[callno]->encmethods = cai.encmethods; 02974 02975 iaxs[callno]->adsi = cai.adsi; 02976 02977 ast_string_field_set(iaxs[callno], mohinterpret, cai.mohinterpret); 02978 ast_string_field_set(iaxs[callno], mohsuggest, cai.mohsuggest); 02979 02980 if (pds.key) 02981 ast_string_field_set(iaxs[callno], outkey, pds.key); 02982 if (pds.password) 02983 ast_string_field_set(iaxs[callno], secret, pds.password); 02984 02985 iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); 02986 iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability); 02987 iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); 02988 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(cai.timezone)); 02989 02990 if (iaxs[callno]->maxtime) { 02991 /* Initialize pingtime and auto-congest time */ 02992 iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2; 02993 iaxs[callno]->initid = ast_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno)); 02994 } else if (autokill) { 02995 iaxs[callno]->pingtime = autokill / 2; 02996 iaxs[callno]->initid = ast_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); 02997 } 02998 02999 /* send the command using the appropriate socket for this peer */ 03000 iaxs[callno]->sockfd = cai.sockfd; 03001 03002 /* Transmit the string in a "NEW" request */ 03003 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); 03004 03005 ast_mutex_unlock(&iaxsl[callno]); 03006 ast_setstate(c, AST_STATE_RINGING); 03007 03008 return 0; 03009 }
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 9791 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_CANEXIST, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
09792 { 09793 int res = 0; 09794 struct iax2_dpcache *dp; 09795 #if 0 09796 ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 09797 #endif 09798 if ((priority != 1) && (priority != 2)) 09799 return 0; 09800 ast_mutex_lock(&dpcache_lock); 09801 dp = find_cache(chan, data, context, exten, priority); 09802 if (dp) { 09803 if (dp->flags & CACHE_FLAG_CANEXIST) 09804 res= 1; 09805 } 09806 ast_mutex_unlock(&dpcache_lock); 09807 if (!dp) { 09808 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 09809 } 09810 return res; 09811 }
static unsigned int iax2_datetime | ( | const char * | tz | ) | [static] |
Definition at line 2782 of file chan_iax2.c.
References ast_localtime(), ast_strlen_zero(), and t.
Referenced by iax2_call(), and update_registry().
02783 { 02784 time_t t; 02785 struct tm tm; 02786 unsigned int tmp; 02787 time(&t); 02788 if (!ast_strlen_zero(tz)) 02789 ast_localtime(&t, &tm, tz); 02790 else 02791 ast_localtime(&t, &tm, NULL); 02792 tmp = (tm.tm_sec >> 1) & 0x1f; /* 5 bits of seconds */ 02793 tmp |= (tm.tm_min & 0x3f) << 5; /* 6 bits of minutes */ 02794 tmp |= (tm.tm_hour & 0x1f) << 11; /* 5 bits of hours */ 02795 tmp |= (tm.tm_mday & 0x1f) << 16; /* 5 bits of day of month */ 02796 tmp |= ((tm.tm_mon + 1) & 0xf) << 21; /* 4 bits of month */ 02797 tmp |= ((tm.tm_year - 100) & 0x7f) << 25; /* 7 bits of year */ 02798 return tmp; 02799 }
static void iax2_destroy | ( | int | callno | ) | [static] |
Definition at line 1792 of file chan_iax2.c.
References ast_channel::_softhangup, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), ast_set_flag, AST_SOFTHANGUP_DEV, ast_string_field_free_pools, ast_variables_destroy(), iax2_registry::callno, chan_iax2_pvt::callno, iax_frame::callno, jb_frame::data, free, iax2_destroy_helper(), iax2_frame_free(), IAX_ALREADYGONE, iaxq, iaxs, iaxsl, chan_iax2_pvt::jb, jb_destroy(), jb_getall(), JB_OK, lastused, ast_channel::lock, LOG_NOTICE, chan_iax2_pvt::owner, chan_iax2_pvt::reg, iax_frame::retries, update_max_trunk(), and chan_iax2_pvt::vars.
Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __unload_module(), delete_users(), destroy_peer(), iax2_do_register(), iax2_hangup(), iax2_poke_peer(), and socket_process().
01793 { 01794 struct chan_iax2_pvt *pvt; 01795 struct iax_frame *cur; 01796 struct ast_channel *owner; 01797 01798 retry: 01799 pvt = iaxs[callno]; 01800 gettimeofday(&lastused[callno], NULL); 01801 01802 owner = pvt ? pvt->owner : NULL; 01803 01804 if (owner) { 01805 if (ast_mutex_trylock(&owner->lock)) { 01806 ast_log(LOG_NOTICE, "Avoiding IAX destroy deadlock\n"); 01807 ast_mutex_unlock(&iaxsl[callno]); 01808 usleep(1); 01809 ast_mutex_lock(&iaxsl[callno]); 01810 goto retry; 01811 } 01812 } 01813 if (!owner) 01814 iaxs[callno] = NULL; 01815 if (pvt) { 01816 if (!owner) 01817 pvt->owner = NULL; 01818 iax2_destroy_helper(pvt); 01819 01820 /* Already gone */ 01821 ast_set_flag(pvt, IAX_ALREADYGONE); 01822 01823 if (owner) { 01824 /* If there's an owner, prod it to give up */ 01825 owner->_softhangup |= AST_SOFTHANGUP_DEV; 01826 ast_queue_hangup(owner); 01827 } 01828 01829 AST_LIST_LOCK(&iaxq.queue); 01830 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 01831 /* Cancel any pending transmissions */ 01832 if (cur->callno == pvt->callno) 01833 cur->retries = -1; 01834 } 01835 AST_LIST_UNLOCK(&iaxq.queue); 01836 01837 if (pvt->reg) 01838 pvt->reg->callno = 0; 01839 if (!owner) { 01840 jb_frame frame; 01841 if (pvt->vars) { 01842 ast_variables_destroy(pvt->vars); 01843 pvt->vars = NULL; 01844 } 01845 01846 while (jb_getall(pvt->jb, &frame) == JB_OK) 01847 iax2_frame_free(frame.data); 01848 jb_destroy(pvt->jb); 01849 /* gotta free up the stringfields */ 01850 ast_string_field_free_pools(pvt); 01851 free(pvt); 01852 } 01853 } 01854 if (owner) { 01855 ast_mutex_unlock(&owner->lock); 01856 } 01857 if (callno & 0x4000) 01858 update_max_trunk(); 01859 }
static void iax2_destroy_helper | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 1733 of file chan_iax2.c.
References ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sched_del(), ast_test_flag, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, iax2_user::curauthreq, IAX_MAXAUTHREQ, chan_iax2_pvt::initid, chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, and chan_iax2_pvt::pingid.
Referenced by iax2_destroy(), iax2_predestroy(), and stop_stuff().
01734 { 01735 struct iax2_user *user = NULL; 01736 01737 /* Decrement AUTHREQ count if needed */ 01738 if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) { 01739 AST_LIST_LOCK(&users); 01740 AST_LIST_TRAVERSE(&users, user, entry) { 01741 if (!strcmp(user->name, pvt->username)) { 01742 user->curauthreq--; 01743 break; 01744 } 01745 } 01746 AST_LIST_UNLOCK(&users); 01747 ast_clear_flag(pvt, IAX_MAXAUTHREQ); 01748 } 01749 /* No more pings or lagrq's */ 01750 if (pvt->pingid > -1) 01751 ast_sched_del(sched, pvt->pingid); 01752 pvt->pingid = -1; 01753 if (pvt->lagid > -1) 01754 ast_sched_del(sched, pvt->lagid); 01755 pvt->lagid = -1; 01756 if (pvt->autoid > -1) 01757 ast_sched_del(sched, pvt->autoid); 01758 pvt->autoid = -1; 01759 if (pvt->authid > -1) 01760 ast_sched_del(sched, pvt->authid); 01761 pvt->authid = -1; 01762 if (pvt->initid > -1) 01763 ast_sched_del(sched, pvt->initid); 01764 pvt->initid = -1; 01765 if (pvt->jbid > -1) 01766 ast_sched_del(sched, pvt->jbid); 01767 pvt->jbid = -1; 01768 }
static int iax2_devicestate | ( | void * | data | ) | [static] |
Part of the device state notification system ---.
Definition at line 9976 of file chan_iax2.c.
References iax2_peer::addr, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, iax2_peer::defaddr, destroy_peer(), find_peer(), iax2_peer::historicms, IAX_TEMPONLY, iax2_peer::lastms, LOG_DEBUG, iax2_peer::maxms, option_debug, parse_dial_string(), and parsed_dial_string::peer.
09977 { 09978 struct parsed_dial_string pds; 09979 char *tmp = ast_strdupa(data); 09980 struct iax2_peer *p; 09981 int res = AST_DEVICE_INVALID; 09982 09983 memset(&pds, 0, sizeof(pds)); 09984 parse_dial_string(tmp, &pds); 09985 if (ast_strlen_zero(pds.peer)) 09986 return res; 09987 09988 if (option_debug > 2) 09989 ast_log(LOG_DEBUG, "Checking device state for device %s\n", pds.peer); 09990 09991 /* SLD: FIXME: second call to find_peer during registration */ 09992 if (!(p = find_peer(pds.peer, 1))) 09993 return res; 09994 09995 res = AST_DEVICE_UNAVAILABLE; 09996 if (option_debug > 2) 09997 ast_log(LOG_DEBUG, "iax2_devicestate: Found peer. What's device state of %s? addr=%d, defaddr=%d maxms=%d, lastms=%d\n", 09998 pds.peer, p->addr.sin_addr.s_addr, p->defaddr.sin_addr.s_addr, p->maxms, p->lastms); 09999 10000 if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) && 10001 (!p->maxms || ((p->lastms > -1) && (p->historicms <= p->maxms)))) { 10002 /* Peer is registered, or have default IP address 10003 and a valid registration */ 10004 if (p->historicms == 0 || p->historicms <= p->maxms) 10005 /* let the core figure out whether it is in use or not */ 10006 res = AST_DEVICE_UNKNOWN; 10007 } 10008 10009 if (ast_test_flag(p, IAX_TEMPONLY)) 10010 destroy_peer(p); 10011 10012 return res; 10013 }
static int iax2_digit_begin | ( | struct ast_channel * | c, | |
char | digit | |||
) | [static] |
Definition at line 2466 of file chan_iax2.c.
References AST_FRAME_DTMF_BEGIN, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02467 { 02468 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1); 02469 }
static int iax2_digit_end | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 2471 of file chan_iax2.c.
References AST_FRAME_DTMF_END, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02472 { 02473 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1); 02474 }
static int iax2_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4524 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04525 { 04526 if (argc < 2 || argc > 3) 04527 return RESULT_SHOWUSAGE; 04528 iaxdebug = 1; 04529 ast_cli(fd, "IAX2 Debugging Enabled\n"); 04530 return RESULT_SUCCESS; 04531 }
static int iax2_do_jb_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4542 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04543 { 04544 if (argc < 3 || argc > 4) 04545 return RESULT_SHOWUSAGE; 04546 jb_setoutput(jb_error_output, jb_warning_output, jb_debug_output); 04547 ast_cli(fd, "IAX2 Jitterbuffer Debugging Enabled\n"); 04548 return RESULT_SUCCESS; 04549 }
static int iax2_do_register | ( | struct iax2_registry * | reg | ) | [static] |
Definition at line 7970 of file chan_iax2.c.
References iax2_registry::addr, ast_dnsmgr_changed(), ast_dnsmgr_refresh(), AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), iax_ie_data::buf, iax2_registry::callno, iax2_registry::dnsmgr, iax2_registry::expire, find_callno(), iax2_destroy(), iax2_do_register_s(), IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, iaxsl, LOG_DEBUG, LOG_WARNING, NEW_FORCE, option_debug, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_REGSENT, REG_STATE_TIMEOUT, iax2_registry::regstate, send_command(), and iax2_registry::username.
Referenced by __iax2_do_register_s(), load_module(), and reload_config().
07971 { 07972 struct iax_ie_data ied; 07973 if (option_debug && iaxdebug) 07974 ast_log(LOG_DEBUG, "Sending registration request for '%s'\n", reg->username); 07975 07976 if (reg->dnsmgr && 07977 ((reg->regstate == REG_STATE_TIMEOUT) || !reg->addr.sin_addr.s_addr)) { 07978 /* Maybe the IP has changed, force DNS refresh */ 07979 ast_dnsmgr_refresh(reg->dnsmgr); 07980 } 07981 07982 /* 07983 * if IP has Changed, free allocated call to create a new one with new IP 07984 * call has the pointer to IP and must be updated to the new one 07985 */ 07986 if (reg->dnsmgr && ast_dnsmgr_changed(reg->dnsmgr) && (reg->callno > 0)) { 07987 ast_mutex_lock(&iaxsl[reg->callno]); 07988 iax2_destroy(reg->callno); 07989 ast_mutex_unlock(&iaxsl[reg->callno]); 07990 reg->callno = 0; 07991 } 07992 if (!reg->addr.sin_addr.s_addr) { 07993 if (option_debug && iaxdebug) 07994 ast_log(LOG_DEBUG, "Unable to send registration request for '%s' without IP address\n", reg->username); 07995 /* Setup the next registration attempt */ 07996 if (reg->expire > -1) 07997 ast_sched_del(sched, reg->expire); 07998 reg->expire = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 07999 return -1; 08000 } 08001 08002 if (!reg->callno) { 08003 if (option_debug) 08004 ast_log(LOG_DEBUG, "Allocate call number\n"); 08005 reg->callno = find_callno(0, 0, ®->addr, NEW_FORCE, 1, defaultsockfd); 08006 if (reg->callno < 1) { 08007 ast_log(LOG_WARNING, "Unable to create call for registration\n"); 08008 return -1; 08009 } else if (option_debug) 08010 ast_log(LOG_DEBUG, "Registration created on call %d\n", reg->callno); 08011 iaxs[reg->callno]->reg = reg; 08012 } 08013 /* Schedule the next registration attempt */ 08014 if (reg->expire > -1) 08015 ast_sched_del(sched, reg->expire); 08016 /* Setup the next registration a little early */ 08017 reg->expire = ast_sched_add(sched, (5 * reg->refresh / 6) * 1000, iax2_do_register_s, reg); 08018 /* Send the request */ 08019 memset(&ied, 0, sizeof(ied)); 08020 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 08021 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 08022 send_command(iaxs[reg->callno],AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 08023 reg->regstate = REG_STATE_REGSENT; 08024 return 0; 08025 }
static int iax2_do_register_s | ( | void * | data | ) | [static] |
Definition at line 5291 of file chan_iax2.c.
References __iax2_do_register_s(), and schedule_action.
Referenced by iax2_ack_registry(), and iax2_do_register().
05292 { 05293 #ifdef SCHED_MULTITHREADED 05294 if (schedule_action(__iax2_do_register_s, data)) 05295 #endif 05296 __iax2_do_register_s(data); 05297 return 0; 05298 }
static int iax2_do_trunk_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4533 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04534 { 04535 if (argc < 3 || argc > 4) 04536 return RESULT_SHOWUSAGE; 04537 iaxtrunkdebug = 1; 04538 ast_cli(fd, "IAX2 Trunk Debug Requested\n"); 04539 return RESULT_SUCCESS; 04540 }
static void iax2_dprequest | ( | struct iax2_dpcache * | dp, | |
int | callno | |||
) | [static] |
Definition at line 5924 of file chan_iax2.c.
References AST_FRAME_IAX, ast_sched_add(), ast_sched_del(), auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, iax2_dpcache::exten, iax2_dpcache::flags, IAX_COMMAND_DPREQ, iax_ie_append_str(), IAX_IE_CALLED_NUMBER, iaxs, iax_ie_data::pos, and send_command().
Referenced by find_cache(), and socket_process().
05925 { 05926 struct iax_ie_data ied; 05927 /* Auto-hangup with 30 seconds of inactivity */ 05928 if (iaxs[callno]->autoid > -1) 05929 ast_sched_del(sched, iaxs[callno]->autoid); 05930 iaxs[callno]->autoid = ast_sched_add(sched, 30000, auto_hangup, (void *)(long)callno); 05931 memset(&ied, 0, sizeof(ied)); 05932 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, dp->exten); 05933 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREQ, 0, ied.buf, ied.pos, -1); 05934 dp->flags |= CACHE_FLAG_TRANSMITTED; 05935 }
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 9837 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_3.
09838 { 09839 char odata[256]; 09840 char req[256]; 09841 char *ncontext; 09842 struct iax2_dpcache *dp; 09843 struct ast_app *dial; 09844 #if 0 09845 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); 09846 #endif 09847 if (priority == 2) { 09848 /* Indicate status, can be overridden in dialplan */ 09849 const char *dialstatus = pbx_builtin_getvar_helper(chan, "DIALSTATUS"); 09850 if (dialstatus) { 09851 dial = pbx_findapp(dialstatus); 09852 if (dial) 09853 pbx_exec(chan, dial, ""); 09854 } 09855 return -1; 09856 } else if (priority != 1) 09857 return -1; 09858 ast_mutex_lock(&dpcache_lock); 09859 dp = find_cache(chan, data, context, exten, priority); 09860 if (dp) { 09861 if (dp->flags & CACHE_FLAG_EXISTS) { 09862 ast_copy_string(odata, data, sizeof(odata)); 09863 ncontext = strchr(odata, '/'); 09864 if (ncontext) { 09865 *ncontext = '\0'; 09866 ncontext++; 09867 snprintf(req, sizeof(req), "IAX2/%s/%s@%s", odata, exten, ncontext); 09868 } else { 09869 snprintf(req, sizeof(req), "IAX2/%s/%s", odata, exten); 09870 } 09871 if (option_verbose > 2) 09872 ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req); 09873 } else { 09874 ast_mutex_unlock(&dpcache_lock); 09875 ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data); 09876 return -1; 09877 } 09878 } 09879 ast_mutex_unlock(&dpcache_lock); 09880 dial = pbx_findapp("Dial"); 09881 if (dial) { 09882 return pbx_exec(chan, dial, req); 09883 } else { 09884 ast_log(LOG_WARNING, "No dial application registered\n"); 09885 } 09886 return -1; 09887 }
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 9768 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_EXISTS, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
09769 { 09770 struct iax2_dpcache *dp; 09771 int res = 0; 09772 #if 0 09773 ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 09774 #endif 09775 if ((priority != 1) && (priority != 2)) 09776 return 0; 09777 ast_mutex_lock(&dpcache_lock); 09778 dp = find_cache(chan, data, context, exten, priority); 09779 if (dp) { 09780 if (dp->flags & CACHE_FLAG_EXISTS) 09781 res= 1; 09782 } 09783 ast_mutex_unlock(&dpcache_lock); 09784 if (!dp) { 09785 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 09786 } 09787 return res; 09788 }
static int iax2_fixup | ( | struct ast_channel * | oldchannel, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 2493 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, LOG_WARNING, chan_iax2_pvt::owner, PTR_TO_CALLNO, and ast_channel::tech_pvt.
02494 { 02495 unsigned short callno = PTR_TO_CALLNO(newchan->tech_pvt); 02496 ast_mutex_lock(&iaxsl[callno]); 02497 if (iaxs[callno]) 02498 iaxs[callno]->owner = newchan; 02499 else 02500 ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n"); 02501 ast_mutex_unlock(&iaxsl[callno]); 02502 return 0; 02503 }
static void iax2_frame_free | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 1330 of file chan_iax2.c.
References ast_sched_del(), iax_frame_free(), and iax_frame::retrans.
Referenced by __attempt_transmit(), __do_deliver(), __get_from_jb(), complete_transfer(), iax2_destroy(), and schedule_delivery().
01331 { 01332 if (fr->retrans > -1) 01333 ast_sched_del(sched, fr->retrans); 01334 iax_frame_free(fr); 01335 }
static int iax2_getpeername | ( | struct sockaddr_in | sin, | |
char * | host, | |||
int | len, | |||
int | lockpeer | |||
) | [static] |
Definition at line 1064 of file chan_iax2.c.
References iax2_peer::addr, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_test_flag, destroy_peer(), IAX_TEMPONLY, and realtime_peer().
Referenced by find_callno().
01065 { 01066 struct iax2_peer *peer = NULL; 01067 int res = 0; 01068 01069 if (lockpeer) 01070 AST_LIST_LOCK(&peers); 01071 AST_LIST_TRAVERSE(&peers, peer, entry) { 01072 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 01073 (peer->addr.sin_port == sin.sin_port)) { 01074 ast_copy_string(host, peer->name, len); 01075 res = 1; 01076 break; 01077 } 01078 } 01079 if (lockpeer) 01080 AST_LIST_UNLOCK(&peers); 01081 if (!peer) { 01082 peer = realtime_peer(NULL, &sin); 01083 if (peer) { 01084 ast_copy_string(host, peer->name, len); 01085 if (ast_test_flag(peer, IAX_TEMPONLY)) 01086 destroy_peer(peer); 01087 res = 1; 01088 } 01089 } 01090 01091 return res; 01092 }
static int iax2_getpeertrunk | ( | struct sockaddr_in | sin | ) | [static] |
Definition at line 3326 of file chan_iax2.c.
References iax2_peer::addr, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_test_flag, and IAX_TRUNK.
Referenced by check_access().
03327 { 03328 struct iax2_peer *peer = NULL; 03329 int res = 0; 03330 03331 AST_LIST_LOCK(&peers); 03332 AST_LIST_TRAVERSE(&peers, peer, entry) { 03333 if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) && 03334 (peer->addr.sin_port == sin.sin_port)) { 03335 res = ast_test_flag(peer, IAX_TRUNK); 03336 break; 03337 } 03338 } 03339 AST_LIST_UNLOCK(&peers); 03340 03341 return res; 03342 }
static int iax2_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 3011 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, ast_verbose(), iax_ie_data::buf, error(), ast_channel::hangupcause, iax2_destroy(), iax2_predestroy(), IAX_ALREADYGONE, IAX_COMMAND_HANGUP, iax_ie_append_byte(), IAX_IE_CAUSECODE, iaxs, iaxsl, LOG_DEBUG, option_verbose, iax_ie_data::pos, PTR_TO_CALLNO, send_command_final(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
03012 { 03013 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03014 int alreadygone; 03015 struct iax_ie_data ied; 03016 memset(&ied, 0, sizeof(ied)); 03017 ast_mutex_lock(&iaxsl[callno]); 03018 if (callno && iaxs[callno]) { 03019 ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name); 03020 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE); 03021 /* Send the hangup unless we have had a transmission error or are already gone */ 03022 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); 03023 if (!iaxs[callno]->error && !alreadygone) 03024 send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); 03025 /* Explicitly predestroy it */ 03026 iax2_predestroy(callno); 03027 /* If we were already gone to begin with, destroy us now */ 03028 if (alreadygone) { 03029 ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name); 03030 iax2_destroy(callno); 03031 } 03032 } 03033 ast_mutex_unlock(&iaxsl[callno]); 03034 if (option_verbose > 2) 03035 ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name); 03036 return 0; 03037 }
static int iax2_indicate | ( | struct ast_channel * | c, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 3272 of file chan_iax2.c.
References AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_CONTROL, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, LOG_DEBUG, option_debug, PTR_TO_CALLNO, send_command(), and ast_channel::tech_pvt.
03273 { 03274 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03275 struct chan_iax2_pvt *pvt; 03276 int res = 0; 03277 03278 if (option_debug && iaxdebug) 03279 ast_log(LOG_DEBUG, "Indicating condition %d\n", condition); 03280 03281 ast_mutex_lock(&iaxsl[callno]); 03282 pvt = iaxs[callno]; 03283 03284 switch (condition) { 03285 case AST_CONTROL_HOLD: 03286 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03287 ast_moh_start(c, data, pvt->mohinterpret); 03288 goto done; 03289 } 03290 break; 03291 case AST_CONTROL_UNHOLD: 03292 if (strcasecmp(pvt->mohinterpret, "passthrough")) { 03293 ast_moh_stop(c); 03294 goto done; 03295 } 03296 } 03297 03298 res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); 03299 03300 done: 03301 ast_mutex_unlock(&iaxsl[callno]); 03302 03303 return res; 03304 }
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 9814 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), CACHE_FLAG_MATCHMORE, find_cache(), iax2_dpcache::flags, LOG_NOTICE, and LOG_WARNING.
09815 { 09816 int res = 0; 09817 struct iax2_dpcache *dp; 09818 #if 0 09819 ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data); 09820 #endif 09821 if ((priority != 1) && (priority != 2)) 09822 return 0; 09823 ast_mutex_lock(&dpcache_lock); 09824 dp = find_cache(chan, data, context, exten, priority); 09825 if (dp) { 09826 if (dp->flags & CACHE_FLAG_MATCHMORE) 09827 res= 1; 09828 } 09829 ast_mutex_unlock(&dpcache_lock); 09830 if (!dp) { 09831 ast_log(LOG_WARNING, "Unable to make DP cache\n"); 09832 } 09833 return res; 09834 }
static int iax2_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4551 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04552 { 04553 if (argc < 3 || argc > 4) 04554 return RESULT_SHOWUSAGE; 04555 iaxdebug = 0; 04556 ast_cli(fd, "IAX2 Debugging Disabled\n"); 04557 return RESULT_SUCCESS; 04558 }
static int iax2_no_jb_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4569 of file chan_iax2.c.
References ast_cli(), jb_debug_output(), jb_error_output(), jb_setoutput(), jb_warning_output(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04570 { 04571 if (argc < 4 || argc > 5) 04572 return RESULT_SHOWUSAGE; 04573 jb_setoutput(jb_error_output, jb_warning_output, NULL); 04574 jb_debug_output("\n"); 04575 ast_cli(fd, "IAX2 Jitterbuffer Debugging Disabled\n"); 04576 return RESULT_SUCCESS; 04577 }
static int iax2_no_trunk_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4560 of file chan_iax2.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04561 { 04562 if (argc < 4 || argc > 5) 04563 return RESULT_SHOWUSAGE; 04564 iaxtrunkdebug = 0; 04565 ast_cli(fd, "IAX2 Trunk Debugging Disabled\n"); 04566 return RESULT_SUCCESS; 04567 }
static int iax2_poke_noanswer | ( | void * | data | ) | [static] |
Definition at line 8166 of file chan_iax2.c.
References __iax2_poke_noanswer(), iax2_peer::pokeexpire, and schedule_action.
Referenced by iax2_poke_peer().
08167 { 08168 struct iax2_peer *peer = data; 08169 peer->pokeexpire = -1; 08170 #ifdef SCHED_MULTITHREADED 08171 if (schedule_action(__iax2_poke_noanswer, data)) 08172 #endif 08173 __iax2_poke_noanswer(data); 08174 return 0; 08175 }
static int iax2_poke_peer | ( | struct iax2_peer * | peer, | |
int | heldcall | |||
) | [static] |
Definition at line 8177 of file chan_iax2.c.
References iax2_peer::addr, AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), iax2_peer::callno, DEFAULT_MAXMS, find_callno(), iax2_peer::historicms, iax2_destroy(), iax2_poke_noanswer(), IAX_COMMAND_POKE, iaxs, iaxsl, iax2_peer::lastms, LOG_NOTICE, LOG_WARNING, iax2_peer::maxms, NEW_FORCE, chan_iax2_pvt::peerpoke, chan_iax2_pvt::pingtime, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, send_command(), and iax2_peer::sockfd.
Referenced by __iax2_poke_peer_s(), load_module(), reg_source_db(), reload_config(), and update_registry().
08178 { 08179 if (!peer->maxms || !peer->addr.sin_addr.s_addr) { 08180 /* IF we have no IP, or this isn't to be monitored, return 08181 immediately after clearing things out */ 08182 peer->lastms = 0; 08183 peer->historicms = 0; 08184 peer->pokeexpire = -1; 08185 peer->callno = 0; 08186 return 0; 08187 } 08188 if (peer->callno > 0) { 08189 ast_log(LOG_NOTICE, "Still have a callno...\n"); 08190 ast_mutex_lock(&iaxsl[peer->callno]); 08191 iax2_destroy(peer->callno); 08192 ast_mutex_unlock(&iaxsl[peer->callno]); 08193 } 08194 if (heldcall) 08195 ast_mutex_unlock(&iaxsl[heldcall]); 08196 peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, 0, peer->sockfd); 08197 if (heldcall) 08198 ast_mutex_lock(&iaxsl[heldcall]); 08199 if (peer->callno < 1) { 08200 ast_log(LOG_WARNING, "Unable to allocate call for poking peer '%s'\n", peer->name); 08201 return -1; 08202 } 08203 08204 /* Speed up retransmission times for this qualify call */ 08205 iaxs[peer->callno]->pingtime = peer->maxms / 4 + 1; 08206 iaxs[peer->callno]->peerpoke = peer; 08207 08208 /* Remove any pending pokeexpire task */ 08209 if (peer->pokeexpire > -1) 08210 ast_sched_del(sched, peer->pokeexpire); 08211 08212 /* Queue up a new task to handle no reply */ 08213 /* If the host is already unreachable then use the unreachable interval instead */ 08214 if (peer->lastms < 0) { 08215 peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_noanswer, peer); 08216 } else 08217 peer->pokeexpire = ast_sched_add(sched, DEFAULT_MAXMS * 2, iax2_poke_noanswer, peer); 08218 08219 /* And send the poke */ 08220 send_command(iaxs[peer->callno], AST_FRAME_IAX, IAX_COMMAND_POKE, 0, NULL, 0, -1); 08221 08222 return 0; 08223 }
static int iax2_poke_peer_s | ( | void * | data | ) | [static] |
Definition at line 5964 of file chan_iax2.c.
References __iax2_poke_peer_s(), iax2_peer::pokeexpire, and schedule_action.
Referenced by __iax2_poke_noanswer(), and socket_process().
05965 { 05966 struct iax2_peer *peer = data; 05967 peer->pokeexpire = -1; 05968 #ifdef SCHED_MULTITHREADED 05969 if (schedule_action(__iax2_poke_peer_s, data)) 05970 #endif 05971 __iax2_poke_peer_s(data); 05972 return 0; 05973 }
static int iax2_predestroy | ( | int | callno | ) | [static] |
Definition at line 1770 of file chan_iax2.c.
References ast_channel::_softhangup, ast_module_unref(), ast_queue_hangup(), ast_set_flag, AST_SOFTHANGUP_DEV, ast_test_flag, iax2_destroy_helper(), IAX_ALREADYGONE, iaxs, chan_iax2_pvt::owner, and ast_channel::tech_pvt.
Referenced by iax2_hangup(), and send_command_final().
01771 { 01772 struct ast_channel *c; 01773 struct chan_iax2_pvt *pvt = iaxs[callno]; 01774 01775 if (!pvt) 01776 return -1; 01777 if (!ast_test_flag(pvt, IAX_ALREADYGONE)) { 01778 iax2_destroy_helper(pvt); 01779 ast_set_flag(pvt, IAX_ALREADYGONE); 01780 } 01781 c = pvt->owner; 01782 if (c) { 01783 c->_softhangup |= AST_SOFTHANGUP_DEV; 01784 c->tech_pvt = NULL; 01785 ast_queue_hangup(c); 01786 pvt->owner = NULL; 01787 ast_module_unref(ast_module_info->self); 01788 } 01789 return 0; 01790 }
static void * iax2_process_thread | ( | void * | data | ) | [static] |
Definition at line 7857 of file chan_iax2.c.
References ast_cond_timedwait(), ast_cond_wait(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_tvadd(), handle_deferred_full_frames(), iax2_process_thread_cleanup(), IAX_IOSTATE_IDLE, IAX_IOSTATE_PROCESSING, IAX_IOSTATE_READY, IAX_IOSTATE_SCHEDREADY, IAX_TYPE_DYNAMIC, iaxactivethreadcount, iaxdynamicthreadcount, insert_idle_thread(), socket_process(), t, and thread.
Referenced by find_idle_thread(), and start_network_thread().
07858 { 07859 struct iax2_thread *thread = data; 07860 struct timeval tv; 07861 struct timespec ts; 07862 int put_into_idle = 0; 07863 07864 ast_atomic_fetchadd_int(&iaxactivethreadcount,1); 07865 pthread_cleanup_push(iax2_process_thread_cleanup, data); 07866 for(;;) { 07867 /* Wait for something to signal us to be awake */ 07868 ast_mutex_lock(&thread->lock); 07869 07870 /* Flag that we're ready to accept signals */ 07871 thread->ready_for_signal = 1; 07872 07873 /* Put into idle list if applicable */ 07874 if (put_into_idle) 07875 insert_idle_thread(thread); 07876 07877 if (thread->type == IAX_TYPE_DYNAMIC) { 07878 struct iax2_thread *t = NULL; 07879 /* Wait to be signalled or time out */ 07880 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 07881 ts.tv_sec = tv.tv_sec; 07882 ts.tv_nsec = tv.tv_usec * 1000; 07883 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) { 07884 /* This thread was never put back into the available dynamic 07885 * thread list, so just go away. */ 07886 if (!put_into_idle) { 07887 ast_mutex_unlock(&thread->lock); 07888 break; 07889 } 07890 AST_LIST_LOCK(&dynamic_list); 07891 /* Account for the case where this thread is acquired *right* after a timeout */ 07892 if ((t = AST_LIST_REMOVE(&dynamic_list, thread, list))) 07893 iaxdynamicthreadcount--; 07894 AST_LIST_UNLOCK(&dynamic_list); 07895 if (t) { 07896 /* This dynamic thread timed out waiting for a task and was 07897 * not acquired immediately after the timeout, 07898 * so it's time to go away. */ 07899 ast_mutex_unlock(&thread->lock); 07900 break; 07901 } 07902 /* Someone grabbed our thread *right* after we timed out. 07903 * Wait for them to set us up with something to do and signal 07904 * us to continue. */ 07905 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000)); 07906 ts.tv_sec = tv.tv_sec; 07907 ts.tv_nsec = tv.tv_usec * 1000; 07908 if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) 07909 { 07910 ast_mutex_unlock(&thread->lock); 07911 break; 07912 } 07913 } 07914 } else { 07915 ast_cond_wait(&thread->cond, &thread->lock); 07916 } 07917 07918 /* Go back into our respective list */ 07919 put_into_idle = 1; 07920 07921 ast_mutex_unlock(&thread->lock); 07922 07923 if (thread->iostate == IAX_IOSTATE_IDLE) 07924 continue; 07925 07926 /* Add ourselves to the active list now */ 07927 AST_LIST_LOCK(&active_list); 07928 AST_LIST_INSERT_HEAD(&active_list, thread, list); 07929 AST_LIST_UNLOCK(&active_list); 07930 07931 /* See what we need to do */ 07932 switch(thread->iostate) { 07933 case IAX_IOSTATE_READY: 07934 thread->actions++; 07935 thread->iostate = IAX_IOSTATE_PROCESSING; 07936 socket_process(thread); 07937 handle_deferred_full_frames(thread); 07938 break; 07939 case IAX_IOSTATE_SCHEDREADY: 07940 thread->actions++; 07941 thread->iostate = IAX_IOSTATE_PROCESSING; 07942 #ifdef SCHED_MULTITHREADED 07943 thread->schedfunc(thread->scheddata); 07944 #endif 07945 break; 07946 } 07947 time(&thread->checktime); 07948 thread->iostate = IAX_IOSTATE_IDLE; 07949 #ifdef DEBUG_SCHED_MULTITHREAD 07950 thread->curfunc[0]='\0'; 07951 #endif 07952 07953 /* Now... remove ourselves from the active list, and return to the idle list */ 07954 AST_LIST_LOCK(&active_list); 07955 AST_LIST_REMOVE(&active_list, thread, list); 07956 AST_LIST_UNLOCK(&active_list); 07957 07958 /* Make sure another frame didn't sneak in there after we thought we were done. */ 07959 handle_deferred_full_frames(thread); 07960 } 07961 07962 /* I am exiting here on my own volition, I need to clean up my own data structures 07963 * Assume that I am no longer in any of the lists (idle, active, or dynamic) 07964 */ 07965 pthread_cleanup_pop(1); 07966 07967 return NULL; 07968 }
static void iax2_process_thread_cleanup | ( | void * | data | ) | [static] |
Definition at line 7848 of file chan_iax2.c.
References ast_cond_destroy(), ast_mutex_destroy(), free, iaxactivethreadcount, and thread.
Referenced by iax2_process_thread().
07849 { 07850 struct iax2_thread *thread = data; 07851 ast_mutex_destroy(&thread->lock); 07852 ast_cond_destroy(&thread->cond); 07853 free(thread); 07854 ast_atomic_dec_and_test(&iaxactivethreadcount); 07855 }
static int iax2_prov_cmd | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 8125 of file chan_iax2.c.
References ast_cli(), iax2_provision(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
08126 { 08127 int force = 0; 08128 int res; 08129 if (argc < 4) 08130 return RESULT_SHOWUSAGE; 08131 if ((argc > 4)) { 08132 if (!strcasecmp(argv[4], "forced")) 08133 force = 1; 08134 else 08135 return RESULT_SHOWUSAGE; 08136 } 08137 res = iax2_provision(NULL, -1, argv[2], argv[3], force); 08138 if (res < 0) 08139 ast_cli(fd, "Unable to find peer/address '%s'\n", argv[2]); 08140 else if (res < 1) 08141 ast_cli(fd, "No template (including wildcard) matching '%s'\n", argv[3]); 08142 else 08143 ast_cli(fd, "Provisioning '%s' with template '%s'%s\n", argv[2], argv[3], force ? ", forced" : ""); 08144 return RESULT_SUCCESS; 08145 }
static char* iax2_prov_complete_template_3rd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 8027 of file chan_iax2.c.
References iax_prov_complete_template().
08028 { 08029 if (pos != 3) 08030 return NULL; 08031 return iax_prov_complete_template(line, word, pos, state); 08032 }
static int iax2_provision | ( | struct sockaddr_in * | end, | |
int | sockfd, | |||
char * | dest, | |||
const char * | template, | |||
int | force | |||
) | [static] |
Definition at line 8034 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), ast_set_flag, auto_hangup(), chan_iax2_pvt::autoid, iax_ie_data::buf, create_addr(), find_callno(), IAX_COMMAND_PROVISION, iax_ie_append_raw(), IAX_IE_PROVISIONING, IAX_PROVISION, iax_provision_build(), iaxs, iaxsl, LOG_DEBUG, NEW_FORCE, option_debug, iax_ie_data::pos, send_command(), and create_addr_info::sockfd.
Referenced by check_provisioning(), iax2_prov_app(), and iax2_prov_cmd().
08035 { 08036 /* Returns 1 if provisioned, -1 if not able to find destination, or 0 if no provisioning 08037 is found for template */ 08038 struct iax_ie_data provdata; 08039 struct iax_ie_data ied; 08040 unsigned int sig; 08041 struct sockaddr_in sin; 08042 int callno; 08043 struct create_addr_info cai; 08044 08045 memset(&cai, 0, sizeof(cai)); 08046 08047 if (option_debug) 08048 ast_log(LOG_DEBUG, "Provisioning '%s' from template '%s'\n", dest, template); 08049 08050 if (iax_provision_build(&provdata, &sig, template, force)) { 08051 ast_log(LOG_DEBUG, "No provisioning found for template '%s'\n", template); 08052 return 0; 08053 } 08054 08055 if (end) { 08056 memcpy(&sin, end, sizeof(sin)); 08057 cai.sockfd = sockfd; 08058 } else if (create_addr(dest, &sin, &cai)) 08059 return -1; 08060 08061 /* Build the rest of the message */ 08062 memset(&ied, 0, sizeof(ied)); 08063 iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos); 08064 08065 callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd); 08066 if (!callno) 08067 return -1; 08068 08069 ast_mutex_lock(&iaxsl[callno]); 08070 if (iaxs[callno]) { 08071 /* Schedule autodestruct in case they don't ever give us anything back */ 08072 if (iaxs[callno]->autoid > -1) 08073 ast_sched_del(sched, iaxs[callno]->autoid); 08074 iaxs[callno]->autoid = ast_sched_add(sched, 15000, auto_hangup, (void *)(long)callno); 08075 ast_set_flag(iaxs[callno], IAX_PROVISION); 08076 /* Got a call number now, so go ahead and send the provisioning information */ 08077 send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_PROVISION, 0, ied.buf, ied.pos, -1); 08078 } 08079 ast_mutex_unlock(&iaxsl[callno]); 08080 08081 return 1; 08082 }
static int iax2_prune_realtime | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1964 of file chan_iax2.c.
References ast_cli(), ast_set_flag, ast_test_flag, expire_registry(), find_peer(), IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, reload_config(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01965 { 01966 struct iax2_peer *peer; 01967 01968 if (argc != 4) 01969 return RESULT_SHOWUSAGE; 01970 if (!strcmp(argv[3],"all")) { 01971 reload_config(); 01972 ast_cli(fd, "OK cache is flushed.\n"); 01973 } else if ((peer = find_peer(argv[3], 0))) { 01974 if(ast_test_flag(peer, IAX_RTCACHEFRIENDS)) { 01975 ast_set_flag(peer, IAX_RTAUTOCLEAR); 01976 expire_registry((void *)peer->name); 01977 ast_cli(fd, "OK peer %s was removed from the cache.\n", argv[3]); 01978 } else { 01979 ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]); 01980 } 01981 } else { 01982 ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]); 01983 } 01984 01985 return RESULT_SUCCESS; 01986 }
static int iax2_queue_frame | ( | int | callno, | |
struct ast_frame * | f | |||
) | [static] |
Queue a frame to a call's owning asterisk channel.
IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] was valid before calling it, it may no longer be valid after calling it. This function may unlock and lock the mutex associated with this callno, meaning that another thread may grab it and destroy the call.
Definition at line 1347 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), iaxs, and iaxsl.
Referenced by __attempt_transmit(), __auto_congest(), __do_deliver(), and __get_from_jb().
01348 { 01349 /* Assumes lock for callno is already held... */ 01350 for (;;) { 01351 if (iaxs[callno] && iaxs[callno]->owner) { 01352 if (ast_mutex_trylock(&iaxs[callno]->owner->lock)) { 01353 /* Avoid deadlock by pausing and trying again */ 01354 ast_mutex_unlock(&iaxsl[callno]); 01355 usleep(1); 01356 ast_mutex_lock(&iaxsl[callno]); 01357 } else { 01358 ast_queue_frame(iaxs[callno]->owner, f); 01359 ast_mutex_unlock(&iaxs[callno]->owner->lock); 01360 break; 01361 } 01362 } else 01363 break; 01364 } 01365 return 0; 01366 }
static struct ast_frame * iax2_read | ( | struct ast_channel * | c | ) | [static, read] |
Definition at line 3065 of file chan_iax2.c.
References ast_log(), ast_null_frame, and LOG_NOTICE.
03066 { 03067 ast_log(LOG_NOTICE, "I should never be called!\n"); 03068 return &ast_null_frame; 03069 }
static int iax2_register | ( | char * | value, | |
int | lineno | |||
) | [static] |
Definition at line 5499 of file chan_iax2.c.
References iax2_registry::addr, ast_calloc, ast_dnsmgr_lookup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), copy(), iax2_registry::dnsmgr, iax2_registry::expire, free, hostname, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, LOG_WARNING, iax2_registry::refresh, iax2_registry::secret, secret, strsep(), and iax2_registry::username.
Referenced by set_config().
05500 { 05501 struct iax2_registry *reg; 05502 char copy[256]; 05503 char *username, *hostname, *secret; 05504 char *porta; 05505 char *stringp=NULL; 05506 05507 if (!value) 05508 return -1; 05509 ast_copy_string(copy, value, sizeof(copy)); 05510 stringp=copy; 05511 username = strsep(&stringp, "@"); 05512 hostname = strsep(&stringp, "@"); 05513 if (!hostname) { 05514 ast_log(LOG_WARNING, "Format for registration is user[:secret]@host[:port] at line %d\n", lineno); 05515 return -1; 05516 } 05517 stringp=username; 05518 username = strsep(&stringp, ":"); 05519 secret = strsep(&stringp, ":"); 05520 stringp=hostname; 05521 hostname = strsep(&stringp, ":"); 05522 porta = strsep(&stringp, ":"); 05523 05524 if (porta && !atoi(porta)) { 05525 ast_log(LOG_WARNING, "%s is not a valid port number at line %d\n", porta, lineno); 05526 return -1; 05527 } 05528 if (!(reg = ast_calloc(1, sizeof(*reg)))) 05529 return -1; 05530 if (ast_dnsmgr_lookup(hostname, ®->addr.sin_addr, ®->dnsmgr) < 0) { 05531 free(reg); 05532 return -1; 05533 } 05534 ast_copy_string(reg->username, username, sizeof(reg->username)); 05535 if (secret) 05536 ast_copy_string(reg->secret, secret, sizeof(reg->secret)); 05537 reg->expire = -1; 05538 reg->refresh = IAX_DEFAULT_REG_EXPIRE; 05539 reg->addr.sin_family = AF_INET; 05540 reg->addr.sin_port = porta ? htons(atoi(porta)) : htons(IAX_DEFAULT_PORTNO); 05541 AST_LIST_LOCK(®istrations); 05542 AST_LIST_INSERT_HEAD(®istrations, reg, entry); 05543 AST_LIST_UNLOCK(®istrations); 05544 05545 return 0; 05546 }
static int iax2_reload | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 9542 of file chan_iax2.c.
References reload_config().
09543 { 09544 return reload_config(); 09545 }
static struct ast_channel * iax2_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static, read] |
Definition at line 8235 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_lock(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strdupa, ast_string_field_set, ast_test_flag, ast_translator_best_choice(), create_addr_info::capability, create_addr(), find_callno(), fmt, create_addr_info::found, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_SENDANI, IAX_TRANSFERMEDIA, IAX_TRUNK, IAX_USEJITTERBUF, iaxs, iaxsl, LOG_WARNING, make_trunk(), create_addr_info::maxtime, chan_iax2_pvt::maxtime, ast_channel::nativeformats, NEW_FORCE, parse_dial_string(), parsed_dial_string::peer, parsed_dial_string::port, ast_channel::readformat, create_addr_info::sockfd, and ast_channel::writeformat.
08236 { 08237 int callno; 08238 int res; 08239 int fmt, native; 08240 struct sockaddr_in sin; 08241 struct ast_channel *c; 08242 struct parsed_dial_string pds; 08243 struct create_addr_info cai; 08244 char *tmpstr; 08245 08246 memset(&pds, 0, sizeof(pds)); 08247 tmpstr = ast_strdupa(data); 08248 parse_dial_string(tmpstr, &pds); 08249 08250 memset(&cai, 0, sizeof(cai)); 08251 cai.capability = iax2_capability; 08252 08253 ast_copy_flags(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 08254 08255 if (!pds.peer) { 08256 ast_log(LOG_WARNING, "No peer given\n"); 08257 return NULL; 08258 } 08259 08260 08261 /* Populate our address from the given */ 08262 if (create_addr(pds.peer, &sin, &cai)) { 08263 *cause = AST_CAUSE_UNREGISTERED; 08264 return NULL; 08265 } 08266 08267 if (pds.port) 08268 sin.sin_port = htons(atoi(pds.port)); 08269 08270 callno = find_callno(0, 0, &sin, NEW_FORCE, 1, cai.sockfd); 08271 if (callno < 1) { 08272 ast_log(LOG_WARNING, "Unable to create call\n"); 08273 *cause = AST_CAUSE_CONGESTION; 08274 return NULL; 08275 } 08276 08277 ast_mutex_lock(&iaxsl[callno]); 08278 08279 /* If this is a trunk, update it now */ 08280 ast_copy_flags(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF); 08281 if (ast_test_flag(&cai, IAX_TRUNK)) { 08282 int new_callno; 08283 if ((new_callno = make_trunk(callno, 1)) != -1) 08284 callno = new_callno; 08285 } 08286 iaxs[callno]->maxtime = cai.maxtime; 08287 if (cai.found) 08288 ast_string_field_set(iaxs[callno], host, pds.peer); 08289 08290 c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability); 08291 08292 ast_mutex_unlock(&iaxsl[callno]); 08293 08294 if (c) { 08295 /* Choose a format we can live with */ 08296 if (c->nativeformats & format) 08297 c->nativeformats &= format; 08298 else { 08299 native = c->nativeformats; 08300 fmt = format; 08301 res = ast_translator_best_choice(&fmt, &native); 08302 if (res < 0) { 08303 ast_log(LOG_WARNING, "Unable to create translator path for %s to %s on %s\n", 08304 ast_getformatname(c->nativeformats), ast_getformatname(fmt), c->name); 08305 ast_hangup(c); 08306 return NULL; 08307 } 08308 c->nativeformats = native; 08309 } 08310 c->readformat = ast_best_codec(c->nativeformats); 08311 c->writeformat = c->readformat; 08312 } 08313 08314 return c; 08315 }
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 3874 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, AST_FRAME_IAX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_test_flag, calc_timestamp(), ast_iax2_mini_hdr::callno, ast_iax2_video_hdr::callno, chan_iax2_pvt::callno, iax_frame::callno, compress_subclass(), ast_iax2_full_hdr::csub, iax_frame::data, ast_frame::data, iax_frame::datalen, ast_frame::datalen, ast_iax2_full_hdr::dcallno, iax_frame::dcallno, DIRECTION_OUTGRESS, chan_iax2_pvt::ecx, encrypt_frame(), iax_frame::final, ast_frame::frametype, iax2_transmit(), iax2_trunk_queue(), IAX_COMMAND_ACK, IAX_ENCRYPTED, IAX_FLAG_FULL, iax_frame_new(), iax_frame_wrap(), IAX_KEYPOPULATED, iax_showframe(), IAX_TRUNK, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, iax_frame::iseqno, chan_iax2_pvt::lastsent, LOG_WARNING, MAX_RETRY_TIME, MIN_RETRY_TIME, ast_iax2_full_hdr::oseqno, chan_iax2_pvt::oseqno, iax_frame::oseqno, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingtime, iax_frame::retries, iax_frame::retrytime, ast_iax2_full_hdr::scallno, chan_iax2_pvt::semirand, send_packet(), ast_frame::subclass, chan_iax2_pvt::svideoformat, chan_iax2_pvt::svoiceformat, chan_iax2_pvt::transfer, iax_frame::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, chan_iax2_pvt::transferring, ast_iax2_mini_hdr::ts, ast_iax2_video_hdr::ts, ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_full_hdr::type, and ast_iax2_video_hdr::zeros.
Referenced by __send_command(), iax2_write(), and socket_process().
03875 { 03876 /* Queue a packet for delivery on a given private structure. Use "ts" for 03877 timestamp, or calculate if ts is 0. Send immediately without retransmission 03878 or delayed, with retransmission */ 03879 struct ast_iax2_full_hdr *fh; 03880 struct ast_iax2_mini_hdr *mh; 03881 struct ast_iax2_video_hdr *vh; 03882 struct { 03883 struct iax_frame fr2; 03884 unsigned char buffer[4096]; 03885 } frb; 03886 struct iax_frame *fr; 03887 int res; 03888 int sendmini=0; 03889 unsigned int lastsent; 03890 unsigned int fts; 03891 03892 frb.fr2.afdatalen = sizeof(frb.buffer); 03893 03894 if (!pvt) { 03895 ast_log(LOG_WARNING, "No private structure for packet?\n"); 03896 return -1; 03897 } 03898 03899 lastsent = pvt->lastsent; 03900 03901 /* Calculate actual timestamp */ 03902 fts = calc_timestamp(pvt, ts, f); 03903 03904 /* Bail here if this is an "interp" frame; we don't want or need to send these placeholders out 03905 * (the endpoint should detect the lost packet itself). But, we want to do this here, so that we 03906 * increment the "predicted timestamps" for voice, if we're predecting */ 03907 if(f->frametype == AST_FRAME_VOICE && f->datalen == 0) 03908 return 0; 03909 03910 03911 if ((ast_test_flag(pvt, IAX_TRUNK) || 03912 (((fts & 0xFFFF0000L) == (lastsent & 0xFFFF0000L)) || 03913 ((fts & 0xFFFF0000L) == ((lastsent + 0x10000) & 0xFFFF0000L)))) 03914 /* High two bytes are the same on timestamp, or sending on a trunk */ && 03915 (f->frametype == AST_FRAME_VOICE) 03916 /* is a voice frame */ && 03917 (f->subclass == pvt->svoiceformat) 03918 /* is the same type */ ) { 03919 /* Force immediate rather than delayed transmission */ 03920 now = 1; 03921 /* Mark that mini-style frame is appropriate */ 03922 sendmini = 1; 03923 } 03924 if (((fts & 0xFFFF8000L) == (lastsent & 0xFFFF8000L)) && 03925 (f->frametype == AST_FRAME_VIDEO) && 03926 ((f->subclass & ~0x1) == pvt->svideoformat)) { 03927 now = 1; 03928 sendmini = 1; 03929 } 03930 /* Allocate an iax_frame */ 03931 if (now) { 03932 fr = &frb.fr2; 03933 } else 03934 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)); 03935 if (!fr) { 03936 ast_log(LOG_WARNING, "Out of memory\n"); 03937 return -1; 03938 } 03939 /* Copy our prospective frame into our immediate or retransmitted wrapper */ 03940 iax_frame_wrap(fr, f); 03941 03942 fr->ts = fts; 03943 fr->callno = pvt->callno; 03944 fr->transfer = transfer; 03945 fr->final = final; 03946 if (!sendmini) { 03947 /* We need a full frame */ 03948 if (seqno > -1) 03949 fr->oseqno = seqno; 03950 else 03951 fr->oseqno = pvt->oseqno++; 03952 fr->iseqno = pvt->iseqno; 03953 fh = (struct ast_iax2_full_hdr *)(fr->af.data - sizeof(struct ast_iax2_full_hdr)); 03954 fh->scallno = htons(fr->callno | IAX_FLAG_FULL); 03955 fh->ts = htonl(fr->ts); 03956 fh->oseqno = fr->oseqno; 03957 if (transfer) { 03958 fh->iseqno = 0; 03959 } else 03960 fh->iseqno = fr->iseqno; 03961 /* Keep track of the last thing we've acknowledged */ 03962 if (!transfer) 03963 pvt->aseqno = fr->iseqno; 03964 fh->type = fr->af.frametype & 0xFF; 03965 if (fr->af.frametype == AST_FRAME_VIDEO) 03966 fh->csub = compress_subclass(fr->af.subclass & ~0x1) | ((fr->af.subclass & 0x1) << 6); 03967 else 03968 fh->csub = compress_subclass(fr->af.subclass); 03969 if (transfer) { 03970 fr->dcallno = pvt->transfercallno; 03971 } else 03972 fr->dcallno = pvt->peercallno; 03973 fh->dcallno = htons(fr->dcallno); 03974 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_full_hdr); 03975 fr->data = fh; 03976 fr->retries = 0; 03977 /* Retry after 2x the ping time has passed */ 03978 fr->retrytime = pvt->pingtime * 2; 03979 if (fr->retrytime < MIN_RETRY_TIME) 03980 fr->retrytime = MIN_RETRY_TIME; 03981 if (fr->retrytime > MAX_RETRY_TIME) 03982 fr->retrytime = MAX_RETRY_TIME; 03983 /* Acks' don't get retried */ 03984 if ((f->frametype == AST_FRAME_IAX) && (f->subclass == IAX_COMMAND_ACK)) 03985 fr->retries = -1; 03986 else if (f->frametype == AST_FRAME_VOICE) 03987 pvt->svoiceformat = f->subclass; 03988 else if (f->frametype == AST_FRAME_VIDEO) 03989 pvt->svideoformat = f->subclass & ~0x1; 03990 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 03991 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 03992 if (iaxdebug) { 03993 if (fr->transfer) 03994 iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 03995 else 03996 iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr)); 03997 } 03998 encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen); 03999 } else 04000 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04001 } 04002 04003 if (now) { 04004 res = send_packet(fr); 04005 } else 04006 res = iax2_transmit(fr); 04007 } else { 04008 if (ast_test_flag(pvt, IAX_TRUNK)) { 04009 iax2_trunk_queue(pvt, fr); 04010 res = 0; 04011 } else if (fr->af.frametype == AST_FRAME_VIDEO) { 04012 /* Video frame have no sequence number */ 04013 fr->oseqno = -1; 04014 fr->iseqno = -1; 04015 vh = (struct ast_iax2_video_hdr *)(fr->af.data - sizeof(struct ast_iax2_video_hdr)); 04016 vh->zeros = 0; 04017 vh->callno = htons(0x8000 | fr->callno); 04018 vh->ts = htons((fr->ts & 0x7FFF) | (fr->af.subclass & 0x1 ? 0x8000 : 0)); 04019 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_video_hdr); 04020 fr->data = vh; 04021 fr->retries = -1; 04022 res = send_packet(fr); 04023 } else { 04024 /* Mini-frames have no sequence number */ 04025 fr->oseqno = -1; 04026 fr->iseqno = -1; 04027 /* Mini frame will do */ 04028 mh = (struct ast_iax2_mini_hdr *)(fr->af.data - sizeof(struct ast_iax2_mini_hdr)); 04029 mh->callno = htons(fr->callno); 04030 mh->ts = htons(fr->ts & 0xFFFF); 04031 fr->datalen = fr->af.datalen + sizeof(struct ast_iax2_mini_hdr); 04032 fr->data = mh; 04033 fr->retries = -1; 04034 if (pvt->transferring == TRANSFER_MEDIAPASS) 04035 fr->transfer = 1; 04036 if (ast_test_flag(pvt, IAX_ENCRYPTED)) { 04037 if (ast_test_flag(pvt, IAX_KEYPOPULATED)) { 04038 encrypt_frame(&pvt->ecx, (struct ast_iax2_full_hdr *)mh, pvt->semirand, &fr->datalen); 04039 } else 04040 ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n"); 04041 } 04042 res = send_packet(fr); 04043 } 04044 } 04045 return res; 04046 }
static int iax2_sendhtml | ( | struct ast_channel * | c, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 2488 of file chan_iax2.c.
References AST_FRAME_HTML, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02489 { 02490 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_HTML, subclass, 0, (unsigned char *)data, datalen, -1); 02491 }
static int iax2_sendimage | ( | struct ast_channel * | c, | |
struct ast_frame * | img | |||
) | [static] |
Definition at line 2483 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.
02484 { 02485 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1); 02486 }
static int iax2_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 2476 of file chan_iax2.c.
References AST_FRAME_TEXT, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
02477 { 02478 02479 return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_TEXT, 02480 0, 0, (unsigned char *)text, strlen(text) + 1, -1); 02481 }
static int iax2_setoption | ( | struct ast_channel * | c, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 3039 of file chan_iax2.c.
References AST_CONTROL_OPTION, AST_FRAME_CONTROL, ast_malloc, AST_OPTION_FLAG_REQUEST, AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, ast_option_header::data, ast_option_header::flag, free, ast_option_header::option, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03040 { 03041 struct ast_option_header *h; 03042 int res; 03043 03044 switch (option) { 03045 case AST_OPTION_TXGAIN: 03046 case AST_OPTION_RXGAIN: 03047 /* these two cannot be sent, because they require a result */ 03048 errno = ENOSYS; 03049 return -1; 03050 default: 03051 if (!(h = ast_malloc(datalen + sizeof(*h)))) 03052 return -1; 03053 03054 h->flag = AST_OPTION_FLAG_REQUEST; 03055 h->option = htons(option); 03056 memcpy(h->data, data, datalen); 03057 res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL, 03058 AST_CONTROL_OPTION, 0, (unsigned char *) h, 03059 datalen + sizeof(*h), -1); 03060 free(h); 03061 return res; 03062 } 03063 }
static int iax2_show_cache | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2165 of file chan_iax2.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), CACHE_FLAG_CANEXIST, CACHE_FLAG_EXISTS, CACHE_FLAG_MATCHMORE, CACHE_FLAG_NONEXISTENT, CACHE_FLAG_PENDING, CACHE_FLAG_TIMEOUT, CACHE_FLAG_TRANSMITTED, CACHE_FLAG_UNKNOWN, dpcache, iax2_dpcache::expiry, iax2_dpcache::exten, iax2_dpcache::flags, iax2_dpcache::next, iax2_dpcache::peercontext, RESULT_SUCCESS, s, and iax2_dpcache::waiters.
02166 { 02167 struct iax2_dpcache *dp; 02168 char tmp[1024], *pc; 02169 int s; 02170 int x,y; 02171 struct timeval tv; 02172 gettimeofday(&tv, NULL); 02173 ast_mutex_lock(&dpcache_lock); 02174 dp = dpcache; 02175 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags"); 02176 while(dp) { 02177 s = dp->expiry.tv_sec - tv.tv_sec; 02178 tmp[0] = '\0'; 02179 if (dp->flags & CACHE_FLAG_EXISTS) 02180 strncat(tmp, "EXISTS|", sizeof(tmp) - strlen(tmp) - 1); 02181 if (dp->flags & CACHE_FLAG_NONEXISTENT) 02182 strncat(tmp, "NONEXISTENT|", sizeof(tmp) - strlen(tmp) - 1); 02183 if (dp->flags & CACHE_FLAG_CANEXIST) 02184 strncat(tmp, "CANEXIST|", sizeof(tmp) - strlen(tmp) - 1); 02185 if (dp->flags & CACHE_FLAG_PENDING) 02186 strncat(tmp, "PENDING|", sizeof(tmp) - strlen(tmp) - 1); 02187 if (dp->flags & CACHE_FLAG_TIMEOUT) 02188 strncat(tmp, "TIMEOUT|", sizeof(tmp) - strlen(tmp) - 1); 02189 if (dp->flags & CACHE_FLAG_TRANSMITTED) 02190 strncat(tmp, "TRANSMITTED|", sizeof(tmp) - strlen(tmp) - 1); 02191 if (dp->flags & CACHE_FLAG_MATCHMORE) 02192 strncat(tmp, "MATCHMORE|", sizeof(tmp) - strlen(tmp) - 1); 02193 if (dp->flags & CACHE_FLAG_UNKNOWN) 02194 strncat(tmp, "UNKNOWN|", sizeof(tmp) - strlen(tmp) - 1); 02195 /* Trim trailing pipe */ 02196 if (!ast_strlen_zero(tmp)) 02197 tmp[strlen(tmp) - 1] = '\0'; 02198 else 02199 ast_copy_string(tmp, "(none)", sizeof(tmp)); 02200 y=0; 02201 pc = strchr(dp->peercontext, '@'); 02202 if (!pc) 02203 pc = dp->peercontext; 02204 else 02205 pc++; 02206 for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++) 02207 if (dp->waiters[x] > -1) 02208 y++; 02209 if (s > 0) 02210 ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp); 02211 else 02212 ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp); 02213 dp = dp->next; 02214 } 02215 ast_mutex_unlock(&dpcache_lock); 02216 return RESULT_SUCCESS; 02217 }
static int iax2_show_channels | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4389 of file chan_iax2.c.
References iax2_registry::addr, ast_cli(), ast_getformatname(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, jb_info::current, iax_rr::delay, FORMAT, FORMAT2, IAX_MAX_CALLS, IAX_USEJITTERBUF, iaxs, iaxsl, jb_getinfo(), jb_info::jitter, jb_info::min, chan_iax2_pvt::remote_rr, RESULT_SHOWUSAGE, RESULT_SUCCESS, and S_OR.
04390 { 04391 #define FORMAT2 "%-20.20s %-15.15s %-10.10s %-11.11s %-11.11s %-7.7s %-6.6s %-6.6s %s\n" 04392 #define FORMAT "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d %-5.5dms %-4.4dms %-4.4dms %-6.6s\n" 04393 #define FORMATB "%-20.20s %-15.15s %-10.10s %5.5d/%5.5d %5.5d/%5.5d [Native Bridged to ID=%5.5d]\n" 04394 int x; 04395 int numchans = 0; 04396 04397 if (argc != 3) 04398 return RESULT_SHOWUSAGE; 04399 ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format"); 04400 for (x=0;x<IAX_MAX_CALLS;x++) { 04401 ast_mutex_lock(&iaxsl[x]); 04402 if (iaxs[x]) { 04403 int lag, jitter, localdelay; 04404 jb_info jbinfo; 04405 04406 if(ast_test_flag(iaxs[x], IAX_USEJITTERBUF)) { 04407 jb_getinfo(iaxs[x]->jb, &jbinfo); 04408 jitter = jbinfo.jitter; 04409 localdelay = jbinfo.current - jbinfo.min; 04410 } else { 04411 jitter = -1; 04412 localdelay = 0; 04413 } 04414 lag = iaxs[x]->remote_rr.delay; 04415 ast_cli(fd, FORMAT, 04416 iaxs[x]->owner ? iaxs[x]->owner->name : "(None)", 04417 ast_inet_ntoa(iaxs[x]->addr.sin_addr), 04418 S_OR(iaxs[x]->username, "(None)"), 04419 iaxs[x]->callno, iaxs[x]->peercallno, 04420 iaxs[x]->oseqno, iaxs[x]->iseqno, 04421 lag, 04422 jitter, 04423 localdelay, 04424 ast_getformatname(iaxs[x]->voiceformat) ); 04425 numchans++; 04426 } 04427 ast_mutex_unlock(&iaxsl[x]); 04428 } 04429 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04430 return RESULT_SUCCESS; 04431 #undef FORMAT 04432 #undef FORMAT2 04433 #undef FORMATB 04434 }
static int iax2_show_firmware | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4300 of file chan_iax2.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, FORMAT, FORMAT2, iax_firmware::fwh, ast_firmware_list::lock, iax_firmware::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
04301 { 04302 #define FORMAT2 "%-15.15s %-15.15s %-15.15s\n" 04303 #if !defined(__FreeBSD__) 04304 #define FORMAT "%-15.15s %-15d %-15d\n" 04305 #else /* __FreeBSD__ */ 04306 #define FORMAT "%-15.15s %-15d %-15d\n" /* XXX 2.95 ? */ 04307 #endif /* __FreeBSD__ */ 04308 struct iax_firmware *cur; 04309 if ((argc != 3) && (argc != 4)) 04310 return RESULT_SHOWUSAGE; 04311 ast_mutex_lock(&waresl.lock); 04312 04313 ast_cli(fd, FORMAT2, "Device", "Version", "Size"); 04314 for (cur = waresl.wares;cur;cur = cur->next) { 04315 if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname))) 04316 ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version), 04317 (int)ntohl(cur->fwh->datalen)); 04318 } 04319 ast_mutex_unlock(&waresl.lock); 04320 return RESULT_SUCCESS; 04321 #undef FORMAT 04322 #undef FORMAT2 04323 }
static int iax2_show_netstats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4512 of file chan_iax2.c.
References ast_cli(), ast_cli_netstats(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04513 { 04514 int numchans = 0; 04515 if (argc != 3) 04516 return RESULT_SHOWUSAGE; 04517 ast_cli(fd, " -------- LOCAL --------------------- -------- REMOTE --------------------\n"); 04518 ast_cli(fd, "Channel RTT Jit Del Lost %% Drop OOO Kpkts Jit Del Lost %% Drop OOO Kpkts\n"); 04519 numchans = ast_cli_netstats(NULL, fd, 1); 04520 ast_cli(fd, "%d active IAX channel%s\n", numchans, (numchans != 1) ? "s" : ""); 04521 return RESULT_SUCCESS; 04522 }
static int iax2_show_peer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Show one peer in detail.
Definition at line 2057 of file chan_iax2.c.
References iax2_peer::addr, ast_callerid_merge(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, iax2_peer::capability, iax2_peer::defaddr, destroy_peer(), iax2_peer::expire, find_peer(), iax2_peer::ha, IAX_DYNAMIC, IAX_TEMPONLY, peer_status(), iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax2_peer::prefs, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax2_peer::smoothing.
02058 { 02059 char status[30]; 02060 char cbuf[256]; 02061 struct iax2_peer *peer; 02062 char codec_buf[512]; 02063 int x = 0, codec = 0, load_realtime = 0; 02064 02065 if (argc < 4) 02066 return RESULT_SHOWUSAGE; 02067 02068 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? 1 : 0; 02069 02070 peer = find_peer(argv[3], load_realtime); 02071 if (peer) { 02072 ast_cli(fd,"\n\n"); 02073 ast_cli(fd, " * Name : %s\n", peer->name); 02074 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 02075 ast_cli(fd, " Context : %s\n", peer->context); 02076 ast_cli(fd, " Mailbox : %s\n", peer->mailbox); 02077 ast_cli(fd, " Dynamic : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes":"No"); 02078 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 02079 ast_cli(fd, " Expire : %d\n", peer->expire); 02080 ast_cli(fd, " ACL : %s\n", (peer->ha?"Yes":"No")); 02081 ast_cli(fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port)); 02082 ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 02083 ast_cli(fd, " Username : %s\n", peer->username); 02084 ast_cli(fd, " Codecs : "); 02085 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 02086 ast_cli(fd, "%s\n", codec_buf); 02087 02088 ast_cli(fd, " Codec Order : ("); 02089 for(x = 0; x < 32 ; x++) { 02090 codec = ast_codec_pref_index(&peer->prefs,x); 02091 if(!codec) 02092 break; 02093 ast_cli(fd, "%s", ast_getformatname(codec)); 02094 if(x < 31 && ast_codec_pref_index(&peer->prefs,x+1)) 02095 ast_cli(fd, "|"); 02096 } 02097 02098 if (!x) 02099 ast_cli(fd, "none"); 02100 ast_cli(fd, ")\n"); 02101 02102 ast_cli(fd, " Status : "); 02103 peer_status(peer, status, sizeof(status)); 02104 ast_cli(fd, "%s\n",status); 02105 ast_cli(fd, " Qualify : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off"); 02106 ast_cli(fd,"\n"); 02107 if (ast_test_flag(peer, IAX_TEMPONLY)) 02108 destroy_peer(peer); 02109 } else { 02110 ast_cli(fd,"Peer %s not found.\n", argv[3]); 02111 ast_cli(fd,"\n"); 02112 } 02113 02114 return RESULT_SUCCESS; 02115 }
static int iax2_show_peers | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4289 of file chan_iax2.c.
References __iax2_show_peers().
04290 { 04291 return __iax2_show_peers(0, fd, NULL, argc, argv); 04292 }
static int iax2_show_registry | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4361 of file chan_iax2.c.
References iax2_registry::addr, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax2_registry::dnsmgr, FORMAT, FORMAT2, iax2_registry::refresh, iax2_registry::regstate, regstate2str(), RESULT_SHOWUSAGE, RESULT_SUCCESS, iax2_registry::us, and iax2_registry::username.
04362 { 04363 #define FORMAT2 "%-20.20s %-6.6s %-10.10s %-20.20s %8.8s %s\n" 04364 #define FORMAT "%-20.20s %-6.6s %-10.10s %-20.20s %8d %s\n" 04365 struct iax2_registry *reg = NULL; 04366 04367 char host[80]; 04368 char perceived[80]; 04369 if (argc != 3) 04370 return RESULT_SHOWUSAGE; 04371 ast_cli(fd, FORMAT2, "Host", "dnsmgr", "Username", "Perceived", "Refresh", "State"); 04372 AST_LIST_LOCK(®istrations); 04373 AST_LIST_TRAVERSE(®istrations, reg, entry) { 04374 snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(reg->addr.sin_addr), ntohs(reg->addr.sin_port)); 04375 if (reg->us.sin_addr.s_addr) 04376 snprintf(perceived, sizeof(perceived), "%s:%d", ast_inet_ntoa(reg->us.sin_addr), ntohs(reg->us.sin_port)); 04377 else 04378 ast_copy_string(perceived, "<Unregistered>", sizeof(perceived)); 04379 ast_cli(fd, FORMAT, host, 04380 (reg->dnsmgr) ? "Y" : "N", 04381 reg->username, perceived, reg->refresh, regstate2str(reg->regstate)); 04382 } 04383 AST_LIST_UNLOCK(®istrations); 04384 return RESULT_SUCCESS; 04385 #undef FORMAT 04386 #undef FORMAT2 04387 }
static int iax2_show_stats | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2139 of file chan_iax2.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::final, iax_get_frames(), iax_get_iframes(), iax_get_oframes(), iaxq, RESULT_SHOWUSAGE, RESULT_SUCCESS, and iax_frame::retries.
02140 { 02141 struct iax_frame *cur; 02142 int cnt = 0, dead=0, final=0; 02143 02144 if (argc != 3) 02145 return RESULT_SHOWUSAGE; 02146 02147 AST_LIST_LOCK(&iaxq.queue); 02148 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 02149 if (cur->retries < 0) 02150 dead++; 02151 if (cur->final) 02152 final++; 02153 cnt++; 02154 } 02155 AST_LIST_UNLOCK(&iaxq.queue); 02156 02157 ast_cli(fd, " IAX Statistics\n"); 02158 ast_cli(fd, "---------------------\n"); 02159 ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); 02160 ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); 02161 02162 return RESULT_SUCCESS; 02163 }
static int iax2_show_threads | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4230 of file chan_iax2.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, IAX_TYPE_DYNAMIC, iaxthreadcount, RESULT_SHOWUSAGE, RESULT_SUCCESS, t, and thread.
04231 { 04232 struct iax2_thread *thread = NULL; 04233 time_t t; 04234 int threadcount = 0, dynamiccount = 0; 04235 char type; 04236 04237 if (argc != 3) 04238 return RESULT_SHOWUSAGE; 04239 04240 ast_cli(fd, "IAX2 Thread Information\n"); 04241 time(&t); 04242 ast_cli(fd, "Idle Threads:\n"); 04243 AST_LIST_LOCK(&idle_list); 04244 AST_LIST_TRAVERSE(&idle_list, thread, list) { 04245 #ifdef DEBUG_SCHED_MULTITHREAD 04246 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04247 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04248 #else 04249 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04250 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04251 #endif 04252 threadcount++; 04253 } 04254 AST_LIST_UNLOCK(&idle_list); 04255 ast_cli(fd, "Active Threads:\n"); 04256 AST_LIST_LOCK(&active_list); 04257 AST_LIST_TRAVERSE(&active_list, thread, list) { 04258 if (thread->type == IAX_TYPE_DYNAMIC) 04259 type = 'D'; 04260 else 04261 type = 'P'; 04262 #ifdef DEBUG_SCHED_MULTITHREAD 04263 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d, func ='%s'\n", 04264 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04265 #else 04266 ast_cli(fd, "Thread %c%d: state=%d, update=%d, actions=%d\n", 04267 type, thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04268 #endif 04269 threadcount++; 04270 } 04271 AST_LIST_UNLOCK(&active_list); 04272 ast_cli(fd, "Dynamic Threads:\n"); 04273 AST_LIST_LOCK(&dynamic_list); 04274 AST_LIST_TRAVERSE(&dynamic_list, thread, list) { 04275 #ifdef DEBUG_SCHED_MULTITHREAD 04276 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d, func ='%s'\n", 04277 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions, thread->curfunc); 04278 #else 04279 ast_cli(fd, "Thread %d: state=%d, update=%d, actions=%d\n", 04280 thread->threadnum, thread->iostate, (int)(t - thread->checktime), thread->actions); 04281 #endif 04282 dynamiccount++; 04283 } 04284 AST_LIST_UNLOCK(&dynamic_list); 04285 ast_cli(fd, "%d of %d threads accounted for with %d dynamic threads\n", threadcount, iaxthreadcount, dynamiccount); 04286 return RESULT_SUCCESS; 04287 }
static int iax2_show_users | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 4048 of file chan_iax2.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_test_flag, iax2_user::authmethods, iax2_context::context, iax2_user::contexts, FORMAT, FORMAT2, iax2_user::ha, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
04049 { 04050 regex_t regexbuf; 04051 int havepattern = 0; 04052 04053 #define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n" 04054 #define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n" 04055 04056 struct iax2_user *user = NULL; 04057 char auth[90]; 04058 char *pstr = ""; 04059 04060 switch (argc) { 04061 case 5: 04062 if (!strcasecmp(argv[3], "like")) { 04063 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 04064 return RESULT_SHOWUSAGE; 04065 havepattern = 1; 04066 } else 04067 return RESULT_SHOWUSAGE; 04068 case 3: 04069 break; 04070 default: 04071 return RESULT_SHOWUSAGE; 04072 } 04073 04074 ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref"); 04075 AST_LIST_LOCK(&users); 04076 AST_LIST_TRAVERSE(&users, user, entry) { 04077 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) 04078 continue; 04079 04080 if (!ast_strlen_zero(user->secret)) { 04081 ast_copy_string(auth,user->secret,sizeof(auth)); 04082 } else if (!ast_strlen_zero(user->inkeys)) { 04083 snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys); 04084 } else 04085 ast_copy_string(auth, "-no secret-", sizeof(auth)); 04086 04087 if(ast_test_flag(user,IAX_CODEC_NOCAP)) 04088 pstr = "REQ Only"; 04089 else if(ast_test_flag(user,IAX_CODEC_NOPREFS)) 04090 pstr = "Disabled"; 04091 else 04092 pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host"; 04093 04094 ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 04095 user->contexts ? user->contexts->context : context, 04096 user->ha ? "Yes" : "No", pstr); 04097 04098 } 04099 AST_LIST_UNLOCK(&users); 04100 04101 if (havepattern) 04102 regfree(®exbuf); 04103 04104 return RESULT_SUCCESS; 04105 #undef FORMAT 04106 #undef FORMAT2 04107 }
static int iax2_start_transfer | ( | unsigned short | callno0, | |
unsigned short | callno1, | |||
int | mediaonly | |||
) | [static] |
Definition at line 3071 of file chan_iax2.c.
References AST_FRAME_IAX, ast_random(), iax_ie_data::buf, IAX_COMMAND_TXREQ, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), IAX_IE_CALLNO, IAX_IE_TRANSFERID, iaxs, iax_ie_data::pos, send_command(), TRANSFER_BEGIN, TRANSFER_MBEGIN, and chan_iax2_pvt::transferring.
Referenced by iax2_bridge().
03072 { 03073 int res; 03074 struct iax_ie_data ied0; 03075 struct iax_ie_data ied1; 03076 unsigned int transferid = (unsigned int)ast_random(); 03077 memset(&ied0, 0, sizeof(ied0)); 03078 iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr); 03079 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno); 03080 iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); 03081 03082 memset(&ied1, 0, sizeof(ied1)); 03083 iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr); 03084 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno); 03085 iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); 03086 03087 res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); 03088 if (res) 03089 return -1; 03090 res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); 03091 if (res) 03092 return -1; 03093 iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03094 iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN; 03095 return 0; 03096 }
static int iax2_test_losspct | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1988 of file chan_iax2.c.
References RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01989 { 01990 if (argc != 4) 01991 return RESULT_SHOWUSAGE; 01992 01993 test_losspct = atoi(argv[3]); 01994 01995 return RESULT_SUCCESS; 01996 }
static int iax2_transfer | ( | struct ast_channel * | c, | |
const char * | dest | |||
) | [static] |
Definition at line 3306 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), iax_ie_data::buf, IAX_COMMAND_TRANSFER, iax_ie_append_str(), IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, LOG_DEBUG, option_debug, iax_ie_data::pos, PTR_TO_CALLNO, send_command_locked(), and ast_channel::tech_pvt.
03307 { 03308 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 03309 struct iax_ie_data ied; 03310 char tmp[256], *context; 03311 ast_copy_string(tmp, dest, sizeof(tmp)); 03312 context = strchr(tmp, '@'); 03313 if (context) { 03314 *context = '\0'; 03315 context++; 03316 } 03317 memset(&ied, 0, sizeof(ied)); 03318 iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp); 03319 if (context) 03320 iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); 03321 if (option_debug) 03322 ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest); 03323 return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); 03324 }
static int iax2_transmit | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2447 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, iaxq, iax_frame::sentyet, and signal_condition().
Referenced by iax2_send().
02448 { 02449 /* Lock the queue and place this packet at the end */ 02450 /* By setting this to 0, the network thread will send it for us, and 02451 queue retransmission if necessary */ 02452 fr->sentyet = 0; 02453 AST_LIST_LOCK(&iaxq.queue); 02454 AST_LIST_INSERT_TAIL(&iaxq.queue, fr, list); 02455 iaxq.count++; 02456 AST_LIST_UNLOCK(&iaxq.queue); 02457 /* Wake up the network and scheduler thread */ 02458 if (netthreadid != AST_PTHREADT_NULL) 02459 pthread_kill(netthreadid, SIGURG); 02460 signal_condition(&sched_lock, &sched_cond); 02461 return 0; 02462 }
static int iax2_trunk_expired | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [inline, static] |
Definition at line 6018 of file chan_iax2.c.
References iax2_trunk_peer::trunkact.
Referenced by timing_read().
06019 { 06020 /* Drop when trunk is about 5 seconds idle */ 06021 if (now->tv_sec > tpeer->trunkact.tv_sec + 5) 06022 return 1; 06023 return 0; 06024 }
static int iax2_trunk_queue | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_frame * | fr | |||
) | [static] |
Definition at line 3649 of file chan_iax2.c.
References iax2_trunk_peer::addr, chan_iax2_pvt::addr, iax_frame::af, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_realloc, ast_test_flag, ast_iax2_meta_trunk_entry::callno, chan_iax2_pvt::callno, ast_iax2_mini_hdr::callno, iax2_trunk_peer::calls, ast_frame::data, ast_frame::datalen, DEFAULT_TRUNKDATA, f, find_tpeer(), IAX2_TRUNK_PREFACE, IAX_TRUNKTIMESTAMPS, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, iax2_trunk_peer::lock, LOG_DEBUG, LOG_WARNING, MAX_TRUNKDATA, ast_iax2_meta_trunk_mini::mini, 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().
03650 { 03651 struct ast_frame *f; 03652 struct iax2_trunk_peer *tpeer; 03653 void *tmp, *ptr; 03654 struct ast_iax2_meta_trunk_entry *met; 03655 struct ast_iax2_meta_trunk_mini *mtm; 03656 03657 f = &fr->af; 03658 tpeer = find_tpeer(&pvt->addr, pvt->sockfd); 03659 if (tpeer) { 03660 if (tpeer->trunkdatalen + f->datalen + 4 >= tpeer->trunkdataalloc) { 03661 /* Need to reallocate space */ 03662 if (tpeer->trunkdataalloc < MAX_TRUNKDATA) { 03663 if (!(tmp = ast_realloc(tpeer->trunkdata, tpeer->trunkdataalloc + DEFAULT_TRUNKDATA + IAX2_TRUNK_PREFACE))) { 03664 ast_mutex_unlock(&tpeer->lock); 03665 return -1; 03666 } 03667 03668 tpeer->trunkdataalloc += DEFAULT_TRUNKDATA; 03669 tpeer->trunkdata = tmp; 03670 ast_log(LOG_DEBUG, "Expanded trunk '%s:%d' to %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), tpeer->trunkdataalloc); 03671 } else { 03672 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)); 03673 ast_mutex_unlock(&tpeer->lock); 03674 return -1; 03675 } 03676 } 03677 03678 /* Append to meta frame */ 03679 ptr = tpeer->trunkdata + IAX2_TRUNK_PREFACE + tpeer->trunkdatalen; 03680 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) { 03681 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 03682 mtm->len = htons(f->datalen); 03683 mtm->mini.callno = htons(pvt->callno); 03684 mtm->mini.ts = htons(0xffff & fr->ts); 03685 ptr += sizeof(struct ast_iax2_meta_trunk_mini); 03686 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_mini); 03687 } else { 03688 met = (struct ast_iax2_meta_trunk_entry *)ptr; 03689 /* Store call number and length in meta header */ 03690 met->callno = htons(pvt->callno); 03691 met->len = htons(f->datalen); 03692 /* Advance pointers/decrease length past trunk entry header */ 03693 ptr += sizeof(struct ast_iax2_meta_trunk_entry); 03694 tpeer->trunkdatalen += sizeof(struct ast_iax2_meta_trunk_entry); 03695 } 03696 /* Copy actual trunk data */ 03697 memcpy(ptr, f->data, f->datalen); 03698 tpeer->trunkdatalen += f->datalen; 03699 03700 tpeer->calls++; 03701 ast_mutex_unlock(&tpeer->lock); 03702 } 03703 return 0; 03704 }
static int iax2_vnak | ( | int | callno | ) | [static] |
Definition at line 5937 of file chan_iax2.c.
References AST_FRAME_IAX, IAX_COMMAND_VNAK, iaxs, and send_command_immediate().
Referenced by socket_process().
05938 { 05939 return send_command_immediate(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_VNAK, 0, NULL, 0, iaxs[callno]->iseqno); 05940 }
static int iax2_write | ( | struct ast_channel * | c, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 4579 of file chan_iax2.c.
References AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, error(), ast_frame::frametype, iax2_send(), IAX_ALREADYGONE, IAX_QUELCH, IAX_STATE_STARTED, iaxs, iaxsl, LOG_DEBUG, PTR_TO_CALLNO, and ast_channel::tech_pvt.
04580 { 04581 unsigned short callno = PTR_TO_CALLNO(c->tech_pvt); 04582 int res = -1; 04583 ast_mutex_lock(&iaxsl[callno]); 04584 if (iaxs[callno]) { 04585 /* If there's an outstanding error, return failure now */ 04586 if (!iaxs[callno]->error) { 04587 if (ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) 04588 res = 0; 04589 /* Don't waste bandwidth sending null frames */ 04590 else if (f->frametype == AST_FRAME_NULL) 04591 res = 0; 04592 else if ((f->frametype == AST_FRAME_VOICE) && ast_test_flag(iaxs[callno], IAX_QUELCH)) 04593 res = 0; 04594 else if (!ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED)) 04595 res = 0; 04596 else 04597 /* Simple, just queue for transmission */ 04598 res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0); 04599 } else { 04600 ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno)); 04601 } 04602 } 04603 /* If it's already gone, just return */ 04604 ast_mutex_unlock(&iaxsl[callno]); 04605 return res; 04606 }
static int iax_check_version | ( | char * | dev | ) | [static] |
Definition at line 1523 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_iax2_firmware_header::devname, iax_firmware::fwh, ast_firmware_list::lock, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
Referenced by update_registry().
01524 { 01525 int res = 0; 01526 struct iax_firmware *cur; 01527 if (!ast_strlen_zero(dev)) { 01528 ast_mutex_lock(&waresl.lock); 01529 cur = waresl.wares; 01530 while(cur) { 01531 if (!strcmp(dev, (char *)cur->fwh->devname)) { 01532 res = ntohs(cur->fwh->version); 01533 break; 01534 } 01535 cur = cur->next; 01536 } 01537 ast_mutex_unlock(&waresl.lock); 01538 } 01539 return res; 01540 }
static void iax_debug_output | ( | const char * | data | ) | [static] |
Definition at line 749 of file chan_iax2.c.
References ast_verbose().
Referenced by load_module().
00750 { 00751 if (iaxdebug) 00752 ast_verbose("%s", data); 00753 }
static void iax_error_output | ( | const char * | data | ) | [static] |
Definition at line 755 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by load_module().
00756 { 00757 ast_log(LOG_WARNING, "%s", data); 00758 }
static int iax_firmware_append | ( | struct iax_ie_data * | ied, | |
const unsigned char * | dev, | |||
unsigned int | desc | |||
) | [static] |
Definition at line 1542 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, ast_iax2_firmware_header::devname, iax_firmware::fwh, iax_ie_append(), iax_ie_append_int(), iax_ie_append_raw(), IAX_IE_FWBLOCKDATA, IAX_IE_FWBLOCKDESC, ast_firmware_list::lock, iax_firmware::next, ast_firmware_list::wares, and waresl.
Referenced by socket_process().
01543 { 01544 int res = -1; 01545 unsigned int bs = desc & 0xff; 01546 unsigned int start = (desc >> 8) & 0xffffff; 01547 unsigned int bytes; 01548 struct iax_firmware *cur; 01549 if (!ast_strlen_zero((char *)dev) && bs) { 01550 start *= bs; 01551 ast_mutex_lock(&waresl.lock); 01552 cur = waresl.wares; 01553 while(cur) { 01554 if (!strcmp((char *)dev, (char *)cur->fwh->devname)) { 01555 iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc); 01556 if (start < ntohl(cur->fwh->datalen)) { 01557 bytes = ntohl(cur->fwh->datalen) - start; 01558 if (bytes > bs) 01559 bytes = bs; 01560 iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes); 01561 } else { 01562 bytes = 0; 01563 iax_ie_append(ied, IAX_IE_FWBLOCKDATA); 01564 } 01565 if (bytes == bs) 01566 res = 0; 01567 else 01568 res = 1; 01569 break; 01570 } 01571 cur = cur->next; 01572 } 01573 ast_mutex_unlock(&waresl.lock); 01574 } 01575 return res; 01576 }
static int iax_park | ( | struct ast_channel * | chan1, | |
struct ast_channel * | chan2 | |||
) | [static] |
Definition at line 6200 of file chan_iax2.c.
References ast_channel::amaflags, ast_calloc, ast_channel_alloc(), ast_channel_masquerade(), ast_do_masquerade(), ast_hangup(), ast_log(), ast_pthread_create_background, AST_STATE_DOWN, iax_dual::chan1, iax_dual::chan2, ast_channel::context, ast_channel::exten, free, iax_park_thread(), LOG_WARNING, ast_channel::priority, ast_channel::readformat, and ast_channel::writeformat.
Referenced by socket_process().
06201 { 06202 struct iax_dual *d; 06203 struct ast_channel *chan1m, *chan2m; 06204 pthread_t th; 06205 chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 06206 chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name); 06207 if (chan2m && chan1m) { 06208 /* Make formats okay */ 06209 chan1m->readformat = chan1->readformat; 06210 chan1m->writeformat = chan1->writeformat; 06211 ast_channel_masquerade(chan1m, chan1); 06212 /* Setup the extensions and such */ 06213 ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context)); 06214 ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten)); 06215 chan1m->priority = chan1->priority; 06216 06217 /* We make a clone of the peer channel too, so we can play 06218 back the announcement */ 06219 /* Make formats okay */ 06220 chan2m->readformat = chan2->readformat; 06221 chan2m->writeformat = chan2->writeformat; 06222 ast_channel_masquerade(chan2m, chan2); 06223 /* Setup the extensions and such */ 06224 ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context)); 06225 ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten)); 06226 chan2m->priority = chan2->priority; 06227 if (ast_do_masquerade(chan2m)) { 06228 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 06229 ast_hangup(chan2m); 06230 return -1; 06231 } 06232 } else { 06233 if (chan1m) 06234 ast_hangup(chan1m); 06235 if (chan2m) 06236 ast_hangup(chan2m); 06237 return -1; 06238 } 06239 if ((d = ast_calloc(1, sizeof(*d)))) { 06240 pthread_attr_t attr; 06241 06242 pthread_attr_init(&attr); 06243 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06244 06245 d->chan1 = chan1m; 06246 d->chan2 = chan2m; 06247 if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) { 06248 pthread_attr_destroy(&attr); 06249 return 0; 06250 } 06251 pthread_attr_destroy(&attr); 06252 free(d); 06253 } 06254 return -1; 06255 }
static void* iax_park_thread | ( | void * | stuff | ) | [static] |
Definition at line 6180 of file chan_iax2.c.
References ast_frfree(), ast_hangup(), ast_log(), ast_park_call(), ast_read(), iax_dual::chan1, iax_dual::chan2, ext, f, free, and LOG_NOTICE.
Referenced by iax_park().
06181 { 06182 struct ast_channel *chan1, *chan2; 06183 struct iax_dual *d; 06184 struct ast_frame *f; 06185 int ext; 06186 int res; 06187 d = stuff; 06188 chan1 = d->chan1; 06189 chan2 = d->chan2; 06190 free(d); 06191 f = ast_read(chan1); 06192 if (f) 06193 ast_frfree(f); 06194 res = ast_park_call(chan1, chan2, 0, &ext); 06195 ast_hangup(chan2); 06196 ast_log(LOG_NOTICE, "Parked on extension '%d'\n", ext); 06197 return NULL; 06198 }
Definition at line 1132 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().
01133 { 01134 struct iax_frame *new = iax_frame_new(DIRECTION_INGRESS, fr->af.datalen, fr->cacheable); 01135 if (new) { 01136 size_t afdatalen = new->afdatalen; 01137 memcpy(new, fr, sizeof(*new)); 01138 iax_frame_wrap(new, &fr->af); 01139 new->afdatalen = afdatalen; 01140 new->data = NULL; 01141 new->datalen = 0; 01142 new->direction = DIRECTION_INGRESS; 01143 new->retrans = -1; 01144 } 01145 return new; 01146 }
static void insert_idle_thread | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 862 of file chan_iax2.c.
References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, and IAX_TYPE_DYNAMIC.
Referenced by iax2_process_thread().
00863 { 00864 if (thread->type == IAX_TYPE_DYNAMIC) { 00865 AST_LIST_LOCK(&dynamic_list); 00866 AST_LIST_INSERT_TAIL(&dynamic_list, thread, list); 00867 AST_LIST_UNLOCK(&dynamic_list); 00868 } else { 00869 AST_LIST_LOCK(&idle_list); 00870 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 00871 AST_LIST_UNLOCK(&idle_list); 00872 } 00873 00874 return; 00875 }
static void jb_debug_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 784 of file chan_iax2.c.
References ast_verbose().
Referenced by iax2_do_jb_debug(), and iax2_no_jb_debug().
00785 { 00786 va_list args; 00787 char buf[1024]; 00788 00789 va_start(args, fmt); 00790 vsnprintf(buf, 1024, fmt, args); 00791 va_end(args); 00792 00793 ast_verbose(buf); 00794 }
static void jb_error_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 760 of file chan_iax2.c.
References ast_log(), and LOG_ERROR.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00761 { 00762 va_list args; 00763 char buf[1024]; 00764 00765 va_start(args, fmt); 00766 vsnprintf(buf, 1024, fmt, args); 00767 va_end(args); 00768 00769 ast_log(LOG_ERROR, buf); 00770 }
static void jb_warning_output | ( | const char * | fmt, | |
... | ||||
) | [static] |
Definition at line 772 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by iax2_do_jb_debug(), iax2_no_jb_debug(), and load_module().
00773 { 00774 va_list args; 00775 char buf[1024]; 00776 00777 va_start(args, fmt); 00778 vsnprintf(buf, 1024, fmt, args); 00779 va_end(args); 00780 00781 ast_log(LOG_WARNING, buf); 00782 }
static int load_module | ( | void | ) | [static] |
Load IAX2 module, load configuraiton ---.
Definition at line 10334 of file chan_iax2.c.
References __unload_module(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register(), AST_LIST_HEAD_INIT, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, ast_mutex_init(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_register_application(), ast_register_switch(), ast_verbose(), cli_iax2, config, iax2_do_register(), iax2_poke_peer(), iax2_prov_app(), iax2_switch, iax2_tech, iax_debug_output(), iax_error_output(), IAX_MAX_CALLS, iax_provision_reload(), iax_set_error(), iax_set_output(), iaxpeer_function, iaxq, iaxs, iaxsl, io_context_create(), jb_error_output(), jb_setoutput(), jb_warning_output(), ast_firmware_list::lock, LOG_ERROR, LOG_WARNING, manager_iax2_show_netstats(), manager_iax2_show_peers(), option_verbose, papp, pdescrip, psyn, reload_firmware(), sched_context_create(), set_config(), iax2_peer::sockfd, start_network_thread(), VERBOSE_PREFIX_2, and waresl.
10335 { 10336 char *config = "iax.conf"; 10337 int res = 0; 10338 int x; 10339 struct iax2_registry *reg = NULL; 10340 struct iax2_peer *peer = NULL; 10341 10342 ast_custom_function_register(&iaxpeer_function); 10343 10344 iax_set_output(iax_debug_output); 10345 iax_set_error(iax_error_output); 10346 jb_setoutput(jb_error_output, jb_warning_output, NULL); 10347 10348 #ifdef HAVE_ZAPTEL 10349 #ifdef ZT_TIMERACK 10350 timingfd = open("/dev/zap/timer", O_RDWR); 10351 if (timingfd < 0) 10352 #endif 10353 timingfd = open("/dev/zap/pseudo", O_RDWR); 10354 if (timingfd < 0) 10355 ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno)); 10356 #endif 10357 10358 memset(iaxs, 0, sizeof(iaxs)); 10359 10360 for (x=0;x<IAX_MAX_CALLS;x++) 10361 ast_mutex_init(&iaxsl[x]); 10362 10363 ast_cond_init(&sched_cond, NULL); 10364 10365 io = io_context_create(); 10366 sched = sched_context_create(); 10367 10368 if (!io || !sched) { 10369 ast_log(LOG_ERROR, "Out of memory\n"); 10370 return -1; 10371 } 10372 10373 netsock = ast_netsock_list_alloc(); 10374 if (!netsock) { 10375 ast_log(LOG_ERROR, "Could not allocate netsock list.\n"); 10376 return -1; 10377 } 10378 ast_netsock_init(netsock); 10379 10380 outsock = ast_netsock_list_alloc(); 10381 if (!outsock) { 10382 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 10383 return -1; 10384 } 10385 ast_netsock_init(outsock); 10386 10387 ast_mutex_init(&waresl.lock); 10388 10389 AST_LIST_HEAD_INIT(&iaxq.queue); 10390 10391 ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry)); 10392 10393 ast_register_application(papp, iax2_prov_app, psyn, pdescrip); 10394 10395 ast_manager_register( "IAXpeers", 0, manager_iax2_show_peers, "List IAX Peers" ); 10396 ast_manager_register( "IAXnetstats", 0, manager_iax2_show_netstats, "Show IAX Netstats" ); 10397 10398 if(set_config(config, 0) == -1) 10399 return AST_MODULE_LOAD_DECLINE; 10400 10401 if (ast_channel_register(&iax2_tech)) { 10402 ast_log(LOG_ERROR, "Unable to register channel class %s\n", "IAX2"); 10403 __unload_module(); 10404 return -1; 10405 } 10406 10407 if (ast_register_switch(&iax2_switch)) 10408 ast_log(LOG_ERROR, "Unable to register IAX switch\n"); 10409 10410 res = start_network_thread(); 10411 if (!res) { 10412 if (option_verbose > 1) 10413 ast_verbose(VERBOSE_PREFIX_2 "IAX Ready and Listening\n"); 10414 } else { 10415 ast_log(LOG_ERROR, "Unable to start network thread\n"); 10416 ast_netsock_release(netsock); 10417 ast_netsock_release(outsock); 10418 } 10419 10420 AST_LIST_LOCK(®istrations); 10421 AST_LIST_TRAVERSE(®istrations, reg, entry) 10422 iax2_do_register(reg); 10423 AST_LIST_UNLOCK(®istrations); 10424 10425 AST_LIST_LOCK(&peers); 10426 AST_LIST_TRAVERSE(&peers, peer, entry) { 10427 if (peer->sockfd < 0) 10428 peer->sockfd = defaultsockfd; 10429 iax2_poke_peer(peer, 0); 10430 } 10431 AST_LIST_UNLOCK(&peers); 10432 reload_firmware(); 10433 iax_provision_reload(); 10434 return res; 10435 }
static void lock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3098 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), and iaxsl.
Referenced by iax2_bridge().
03099 { 03100 ast_mutex_lock(&iaxsl[callno0]); 03101 while (ast_mutex_trylock(&iaxsl[callno1])) { 03102 ast_mutex_unlock(&iaxsl[callno0]); 03103 usleep(10); 03104 ast_mutex_lock(&iaxsl[callno0]); 03105 } 03106 }
static int make_trunk | ( | unsigned short | callno, | |
int | locked | |||
) | [static] |
Definition at line 1200 of file chan_iax2.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), chan_iax2_pvt::callno, IAX_MAX_CALLS, iaxs, iaxsl, chan_iax2_pvt::lagid, lastused, LOG_DEBUG, LOG_WARNING, MIN_REUSE_TIME, chan_iax2_pvt::pingid, send_lagrq(), send_ping(), TRUNK_CALL_START, update_max_nontrunk(), and update_max_trunk().
Referenced by iax2_request(), and socket_process().
01201 { 01202 int x; 01203 int res= 0; 01204 struct timeval now; 01205 if (iaxs[callno]->oseqno) { 01206 ast_log(LOG_WARNING, "Can't make trunk once a call has started!\n"); 01207 return -1; 01208 } 01209 if (callno & TRUNK_CALL_START) { 01210 ast_log(LOG_WARNING, "Call %d is already a trunk\n", callno); 01211 return -1; 01212 } 01213 gettimeofday(&now, NULL); 01214 for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) { 01215 ast_mutex_lock(&iaxsl[x]); 01216 if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) { 01217 iaxs[x] = iaxs[callno]; 01218 iaxs[x]->callno = x; 01219 iaxs[callno] = NULL; 01220 /* Update the two timers that should have been started */ 01221 if (iaxs[x]->pingid > -1) 01222 ast_sched_del(sched, iaxs[x]->pingid); 01223 if (iaxs[x]->lagid > -1) 01224 ast_sched_del(sched, iaxs[x]->lagid); 01225 iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x); 01226 iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x); 01227 if (locked) 01228 ast_mutex_unlock(&iaxsl[callno]); 01229 res = x; 01230 if (!locked) 01231 ast_mutex_unlock(&iaxsl[x]); 01232 break; 01233 } 01234 ast_mutex_unlock(&iaxsl[x]); 01235 } 01236 if (x >= IAX_MAX_CALLS - 1) { 01237 ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n"); 01238 return -1; 01239 } 01240 ast_log(LOG_DEBUG, "Made call %d into trunk call %d\n", callno, x); 01241 /* We move this call from a non-trunked to a trunked call */ 01242 update_max_trunk(); 01243 update_max_nontrunk(); 01244 return res; 01245 }
static int manager_iax2_show_netstats | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4293 of file chan_iax2.c.
References ast_cli_netstats(), astman_append(), and RESULT_SUCCESS.
Referenced by load_module().
04294 { 04295 ast_cli_netstats(s, -1, 0); 04296 astman_append(s, "\r\n"); 04297 return RESULT_SUCCESS; 04298 }
static int manager_iax2_show_peers | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4326 of file chan_iax2.c.
References __iax2_show_peers(), ast_strlen_zero(), astman_append(), and astman_get_header().
Referenced by load_module().
04327 { 04328 char *a[] = { "iax2", "show", "users" }; 04329 int ret; 04330 const char *id = astman_get_header(m,"ActionID"); 04331 04332 if (!ast_strlen_zero(id)) 04333 astman_append(s, "ActionID: %s\r\n",id); 04334 ret = __iax2_show_peers(1, -1, s, 3, a ); 04335 astman_append(s, "\r\n\r\n" ); 04336 return ret; 04337 } /* /JDG */
static int match | ( | struct sockaddr_in * | sin, | |
unsigned short | callno, | |||
unsigned short | dcallno, | |||
struct chan_iax2_pvt * | cur | |||
) | [static] |
Definition at line 1152 of file chan_iax2.c.
References chan_iax2_pvt::addr, chan_iax2_pvt::callno, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, TRANSFER_MEDIAPASS, chan_iax2_pvt::transfercallno, and chan_iax2_pvt::transferring.
Referenced by ast_parse_device_state(), find_callno(), find_command(), get_sip_pvt_byid_locked(), handle_updates(), pbx_find_extension(), realtime_switch_common(), and softhangup_exec().
01153 { 01154 if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) && 01155 (cur->addr.sin_port == sin->sin_port)) { 01156 /* This is the main host */ 01157 if ((cur->peercallno == callno) || 01158 ((dcallno == cur->callno) && !cur->peercallno)) { 01159 /* That's us. Be sure we keep track of the peer call number */ 01160 return 1; 01161 } 01162 } 01163 if ((cur->transfer.sin_addr.s_addr == sin->sin_addr.s_addr) && 01164 (cur->transfer.sin_port == sin->sin_port) && (cur->transferring)) { 01165 /* We're transferring */ 01166 if ((dcallno == cur->callno) || (cur->transferring == TRANSFER_MEDIAPASS && cur->transfercallno == callno)) 01167 return 1; 01168 } 01169 return 0; 01170 }
static void memcpy_decrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
aes_decrypt_ctx * | dcx | |||
) | [static] |
Definition at line 3712 of file chan_iax2.c.
References aes_decrypt(), ast_log(), and LOG_WARNING.
Referenced by decode_frame().
03713 { 03714 #if 0 03715 /* Debug with "fake encryption" */ 03716 int x; 03717 if (len % 16) 03718 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 03719 for (x=0;x<len;x++) 03720 dst[x] = src[x] ^ 0xff; 03721 #else 03722 unsigned char lastblock[16] = { 0 }; 03723 int x; 03724 while(len > 0) { 03725 aes_decrypt(src, dst, dcx); 03726 for (x=0;x<16;x++) 03727 dst[x] ^= lastblock[x]; 03728 memcpy(lastblock, src, sizeof(lastblock)); 03729 dst += 16; 03730 src += 16; 03731 len -= 16; 03732 } 03733 #endif 03734 }
static void memcpy_encrypt | ( | unsigned char * | dst, | |
const unsigned char * | src, | |||
int | len, | |||
aes_encrypt_ctx * | ecx | |||
) | [static] |
Definition at line 3736 of file chan_iax2.c.
References aes_encrypt(), ast_log(), and LOG_WARNING.
Referenced by encrypt_frame().
03737 { 03738 #if 0 03739 /* Debug with "fake encryption" */ 03740 int x; 03741 if (len % 16) 03742 ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len); 03743 for (x=0;x<len;x++) 03744 dst[x] = src[x] ^ 0xff; 03745 #else 03746 unsigned char curblock[16] = { 0 }; 03747 int x; 03748 while(len > 0) { 03749 for (x=0;x<16;x++) 03750 curblock[x] ^= src[x]; 03751 aes_encrypt(curblock, dst, ecx); 03752 memcpy(curblock, dst, sizeof(curblock)); 03753 dst += 16; 03754 src += 16; 03755 len -= 16; 03756 } 03757 #endif 03758 }
static void merge_encryption | ( | struct chan_iax2_pvt * | p, | |
unsigned int | enc | |||
) | [static] |
Definition at line 4884 of file chan_iax2.c.
References chan_iax2_pvt::encmethods, and IAX_ENCRYPT_AES128.
Referenced by authenticate_reply(), and socket_process().
04885 { 04886 /* Select exactly one common encryption if there are any */ 04887 p->encmethods &= enc; 04888 if (p->encmethods) { 04889 if (p->encmethods & IAX_ENCRYPT_AES128) 04890 p->encmethods = IAX_ENCRYPT_AES128; 04891 else 04892 p->encmethods = 0; 04893 } 04894 }
static void* network_thread | ( | void * | ignore | ) | [static] |
Definition at line 8345 of file chan_iax2.c.
References ast_io_add(), AST_IO_IN, AST_IO_PRI, ast_io_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_sched_add(), attempt_transmit(), iax_frame::callno, f, iax_frame_free(), iaxq, iaxs, iaxsl, LOG_DEBUG, iax_frame::retrans, iax_frame::retries, iax_frame::retrytime, send_packet(), iax_frame::sentyet, signal_condition(), and timing_read().
Referenced by start_network_thread().
08346 { 08347 /* Our job is simple: Send queued messages, retrying if necessary. Read frames 08348 from the network, and queue them for delivery to the channels */ 08349 int res, count, wakeup; 08350 struct iax_frame *f; 08351 08352 if (timingfd > -1) 08353 ast_io_add(io, timingfd, timing_read, AST_IO_IN | AST_IO_PRI, NULL); 08354 08355 for(;;) { 08356 pthread_testcancel(); 08357 08358 /* Go through the queue, sending messages which have not yet been 08359 sent, and scheduling retransmissions if appropriate */ 08360 AST_LIST_LOCK(&iaxq.queue); 08361 count = 0; 08362 wakeup = -1; 08363 AST_LIST_TRAVERSE_SAFE_BEGIN(&iaxq.queue, f, list) { 08364 if (f->sentyet) 08365 continue; 08366 08367 /* Try to lock the pvt, if we can't... don't fret - defer it till later */ 08368 if (ast_mutex_trylock(&iaxsl[f->callno])) { 08369 wakeup = 1; 08370 continue; 08371 } 08372 08373 f->sentyet++; 08374 08375 if (iaxs[f->callno]) { 08376 send_packet(f); 08377 count++; 08378 } 08379 08380 ast_mutex_unlock(&iaxsl[f->callno]); 08381 08382 if (f->retries < 0) { 08383 /* This is not supposed to be retransmitted */ 08384 AST_LIST_REMOVE_CURRENT(&iaxq.queue, list); 08385 iaxq.count--; 08386 /* Free the iax frame */ 08387 iax_frame_free(f); 08388 } else { 08389 /* We need reliable delivery. Schedule a retransmission */ 08390 f->retries++; 08391 f->retrans = ast_sched_add(sched, f->retrytime, attempt_transmit, f); 08392 signal_condition(&sched_lock, &sched_cond); 08393 } 08394 } 08395 AST_LIST_TRAVERSE_SAFE_END 08396 AST_LIST_UNLOCK(&iaxq.queue); 08397 08398 pthread_testcancel(); 08399 08400 if (count >= 20) 08401 ast_log(LOG_DEBUG, "chan_iax2: Sent %d queued outbound frames all at once\n", count); 08402 08403 /* Now do the IO, and run scheduled tasks */ 08404 res = ast_io_wait(io, wakeup); 08405 if (res >= 0) { 08406 if (res >= 20) 08407 ast_log(LOG_DEBUG, "chan_iax2: ast_io_wait ran %d I/Os all at once\n", res); 08408 } 08409 } 08410 return NULL; 08411 }
static struct chan_iax2_pvt* new_iax | ( | struct sockaddr_in * | sin, | |
int | lockpeer, | |||
const char * | host | |||
) | [static, read] |
Definition at line 1094 of file chan_iax2.c.
References ast_calloc, ast_string_field_init, ast_string_field_set, chan_iax2_pvt::authid, chan_iax2_pvt::autoid, chan_iax2_pvt::bridgecallno, chan_iax2_pvt::callno, exten, free, chan_iax2_pvt::initid, chan_iax2_pvt::jb, jb_new(), jb_setconf(), chan_iax2_pvt::jbid, chan_iax2_pvt::lagid, jb_conf::max_contig_interp, jb_conf::max_jitterbuf, chan_iax2_pvt::peercallno, chan_iax2_pvt::pingid, iax2_user::prefs, chan_iax2_pvt::prefs, jb_conf::resync_threshold, and chan_iax2_pvt::transfercallno.
Referenced by find_callno().
01095 { 01096 struct chan_iax2_pvt *tmp; 01097 jb_conf jbconf; 01098 01099 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) 01100 return NULL; 01101 01102 if (ast_string_field_init(tmp, 32)) { 01103 free(tmp); 01104 tmp = NULL; 01105 return NULL; 01106 } 01107 01108 tmp->prefs = prefs; 01109 tmp->callno = 0; 01110 tmp->peercallno = 0; 01111 tmp->transfercallno = 0; 01112 tmp->bridgecallno = 0; 01113 tmp->pingid = -1; 01114 tmp->lagid = -1; 01115 tmp->autoid = -1; 01116 tmp->authid = -1; 01117 tmp->initid = -1; 01118 01119 ast_string_field_set(tmp,exten, "s"); 01120 ast_string_field_set(tmp,host, host); 01121 01122 tmp->jb = jb_new(); 01123 tmp->jbid = -1; 01124 jbconf.max_jitterbuf = maxjitterbuffer; 01125 jbconf.resync_threshold = resyncthreshold; 01126 jbconf.max_contig_interp = maxjitterinterps; 01127 jb_setconf(tmp->jb,&jbconf); 01128 01129 return tmp; 01130 }
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 2830 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().
02831 { 02832 if (ast_strlen_zero(data)) 02833 return; 02834 02835 pds->peer = strsep(&data, "/"); 02836 pds->exten = strsep(&data, "/"); 02837 pds->options = data; 02838 02839 if (pds->exten) { 02840 data = pds->exten; 02841 pds->exten = strsep(&data, "@"); 02842 pds->context = data; 02843 } 02844 02845 if (strchr(pds->peer, '@')) { 02846 data = pds->peer; 02847 pds->username = strsep(&data, "@"); 02848 pds->peer = data; 02849 } 02850 02851 if (pds->username) { 02852 data = pds->username; 02853 pds->username = strsep(&data, ":"); 02854 pds->password = data; 02855 } 02856 02857 data = pds->peer; 02858 pds->peer = strsep(&data, ":"); 02859 pds->port = data; 02860 02861 /* check for a key name wrapped in [] in the secret position, if found, 02862 move it to the key field instead 02863 */ 02864 if (pds->password && (pds->password[0] == '[')) { 02865 pds->key = ast_strip_quoted(pds->password, "[", "]"); 02866 pds->password = NULL; 02867 } 02868 }
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 8495 of file chan_iax2.c.
References ast_get_ip(), ast_log(), ast_netsock_bind(), ast_netsock_find(), ast_netsock_sockfd(), ast_netsock_unref(), ast_strdupa, check_srcaddr(), IAX_DEFAULT_PORTNO, LOG_DEBUG, LOG_WARNING, socket_read(), iax2_peer::sockfd, and strsep().
Referenced by build_peer().
08496 { 08497 struct sockaddr_in sin; 08498 int nonlocal = 1; 08499 int port = IAX_DEFAULT_PORTNO; 08500 int sockfd = defaultsockfd; 08501 char *tmp; 08502 char *addr; 08503 char *portstr; 08504 08505 if (!(tmp = ast_strdupa(srcaddr))) 08506 return -1; 08507 08508 addr = strsep(&tmp, ":"); 08509 portstr = tmp; 08510 08511 if (portstr) { 08512 port = atoi(portstr); 08513 if (port < 1) 08514 port = IAX_DEFAULT_PORTNO; 08515 } 08516 08517 if (!ast_get_ip(&sin, addr)) { 08518 struct ast_netsock *sock; 08519 int res; 08520 08521 sin.sin_port = 0; 08522 sin.sin_family = AF_INET; 08523 res = check_srcaddr((struct sockaddr *) &sin, sizeof(sin)); 08524 if (res == 0) { 08525 /* ip address valid. */ 08526 sin.sin_port = htons(port); 08527 if (!(sock = ast_netsock_find(netsock, &sin))) 08528 sock = ast_netsock_find(outsock, &sin); 08529 if (sock) { 08530 sockfd = ast_netsock_sockfd(sock); 08531 nonlocal = 0; 08532 } else { 08533 unsigned int orig_saddr = sin.sin_addr.s_addr; 08534 /* INADDR_ANY matches anyway! */ 08535 sin.sin_addr.s_addr = INADDR_ANY; 08536 if (ast_netsock_find(netsock, &sin)) { 08537 sin.sin_addr.s_addr = orig_saddr; 08538 sock = ast_netsock_bind(outsock, io, srcaddr, port, tos, socket_read, NULL); 08539 if (sock) { 08540 sockfd = ast_netsock_sockfd(sock); 08541 ast_netsock_unref(sock); 08542 nonlocal = 0; 08543 } else { 08544 nonlocal = 2; 08545 } 08546 } 08547 } 08548 } 08549 } 08550 08551 peer->sockfd = sockfd; 08552 08553 if (nonlocal == 1) { 08554 ast_log(LOG_WARNING, "Non-local or unbound address specified (%s) in sourceaddress for '%s', reverting to default\n", 08555 srcaddr, peer->name); 08556 return -1; 08557 } else if (nonlocal == 2) { 08558 ast_log(LOG_WARNING, "Unable to bind to sourceaddress '%s' for '%s', reverting to default\n", 08559 srcaddr, peer->name); 08560 return -1; 08561 } else { 08562 ast_log(LOG_DEBUG, "Using sourceaddress %s for '%s'\n", srcaddr, peer->name); 08563 return 0; 08564 } 08565 }
static int peer_status | ( | struct iax2_peer * | peer, | |
char * | status, | |||
int | statuslen | |||
) | [static] |
peer_status: Report Peer status in character string
Definition at line 2034 of file chan_iax2.c.
References iax2_peer::lastms, and iax2_peer::maxms.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), function_iaxpeer(), function_sippeer(), and iax2_show_peer().
02035 { 02036 int res = 0; 02037 if (peer->maxms) { 02038 if (peer->lastms < 0) { 02039 ast_copy_string(status, "UNREACHABLE", statuslen); 02040 } else if (peer->lastms > peer->maxms) { 02041 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 02042 res = 1; 02043 } else if (peer->lastms) { 02044 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 02045 res = 1; 02046 } else { 02047 ast_copy_string(status, "UNKNOWN", statuslen); 02048 } 02049 } else { 02050 ast_copy_string(status, "Unmonitored", statuslen); 02051 res = -1; 02052 } 02053 return res; 02054 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 9118 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_test_flag, destroy_peer(), and IAX_DELME.
09118 { 09119 /* Prune peers who still are supposed to be deleted */ 09120 struct iax2_peer *peer = NULL; 09121 09122 AST_LIST_LOCK(&peers); 09123 AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, entry) { 09124 if (ast_test_flag(peer, IAX_DELME)) { 09125 destroy_peer(peer); 09126 AST_LIST_REMOVE_CURRENT(&peers, entry); 09127 } 09128 } 09129 AST_LIST_TRAVERSE_SAFE_END 09130 AST_LIST_UNLOCK(&peers); 09131 }
static void prune_users | ( | void | ) | [static] |
Definition at line 9077 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_test_flag, destroy_user(), and IAX_DELME.
Referenced by reload_config().
09078 { 09079 struct iax2_user *user = NULL; 09080 09081 AST_LIST_LOCK(&users); 09082 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, entry) { 09083 if (ast_test_flag(user, IAX_DELME)) { 09084 destroy_user(user); 09085 AST_LIST_REMOVE_CURRENT(&users, entry); 09086 } 09087 } 09088 AST_LIST_TRAVERSE_SAFE_END 09089 AST_LIST_UNLOCK(&users); 09090 09091 }
static int raw_hangup | ( | struct sockaddr_in * | sin, | |
unsigned short | src, | |||
unsigned short | dst, | |||
int | sockfd | |||
) | [static] |
Definition at line 4864 of file chan_iax2.c.
References AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), compress_subclass(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, IAX_COMMAND_INVAL, IAX_FLAG_FULL, iax_showframe(), ast_iax2_full_hdr::iseqno, LOG_DEBUG, option_debug, ast_iax2_full_hdr::oseqno, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.
Referenced by socket_process().
04865 { 04866 struct ast_iax2_full_hdr fh; 04867 fh.scallno = htons(src | IAX_FLAG_FULL); 04868 fh.dcallno = htons(dst); 04869 fh.ts = 0; 04870 fh.oseqno = 0; 04871 fh.iseqno = 0; 04872 fh.type = AST_FRAME_IAX; 04873 fh.csub = compress_subclass(IAX_COMMAND_INVAL); 04874 if (iaxdebug) 04875 iax_showframe(NULL, &fh, 0, sin, 0); 04876 #if 0 04877 if (option_debug) 04878 #endif 04879 ast_log(LOG_DEBUG, "Raw Hangup %s:%d, src=%d, dst=%d\n", 04880 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), src, dst); 04881 return sendto(sockfd, &fh, sizeof(fh), 0, (struct sockaddr *)sin, sizeof(*sin)); 04882 }
static struct iax2_peer * realtime_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin | |||
) | [static, read] |
Definition at line 2505 of file chan_iax2.c.
References iax2_peer::addr, ast_copy_flags, ast_get_time_t(), ast_inet_ntoa(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_load_realtime(), ast_log(), ast_sched_add(), ast_sched_del(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_peer(), destroy_peer(), iax2_peer::expire, expire_registry(), IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_TEMPONLY, LOG_DEBUG, ast_variable::name, ast_variable::next, option_debug, realtime_update_peer(), reg_source_db(), ast_variable::value, and var.
02506 { 02507 struct ast_variable *var; 02508 struct ast_variable *tmp; 02509 struct iax2_peer *peer=NULL; 02510 time_t regseconds = 0, nowtime; 02511 int dynamic=0; 02512 02513 if (peername) 02514 var = ast_load_realtime("iaxpeers", "name", peername, NULL); 02515 else { 02516 char porta[25]; 02517 sprintf(porta, "%d", ntohs(sin->sin_port)); 02518 var = ast_load_realtime("iaxpeers", "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", porta, NULL); 02519 if (var) { 02520 /* We'll need the peer name in order to build the structure! */ 02521 for (tmp = var; tmp; tmp = tmp->next) { 02522 if (!strcasecmp(tmp->name, "name")) 02523 peername = tmp->value; 02524 } 02525 } 02526 } 02527 if (!var) 02528 return NULL; 02529 02530 peer = build_peer(peername, var, NULL, ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS) ? 0 : 1); 02531 02532 if (!peer) { 02533 ast_variables_destroy(var); 02534 return NULL; 02535 } 02536 02537 for (tmp = var; tmp; tmp = tmp->next) { 02538 /* Make sure it's not a user only... */ 02539 if (!strcasecmp(tmp->name, "type")) { 02540 if (strcasecmp(tmp->value, "friend") && 02541 strcasecmp(tmp->value, "peer")) { 02542 /* Whoops, we weren't supposed to exist! */ 02543 destroy_peer(peer); 02544 peer = NULL; 02545 break; 02546 } 02547 } else if (!strcasecmp(tmp->name, "regseconds")) { 02548 ast_get_time_t(tmp->value, ®seconds, 0, NULL); 02549 } else if (!strcasecmp(tmp->name, "ipaddr")) { 02550 inet_aton(tmp->value, &(peer->addr.sin_addr)); 02551 } else if (!strcasecmp(tmp->name, "port")) { 02552 peer->addr.sin_port = htons(atoi(tmp->value)); 02553 } else if (!strcasecmp(tmp->name, "host")) { 02554 if (!strcasecmp(tmp->value, "dynamic")) 02555 dynamic = 1; 02556 } 02557 } 02558 02559 ast_variables_destroy(var); 02560 02561 if (!peer) 02562 return NULL; 02563 02564 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 02565 ast_copy_flags(peer, &globalflags, IAX_RTAUTOCLEAR|IAX_RTCACHEFRIENDS); 02566 if (ast_test_flag(peer, IAX_RTAUTOCLEAR)) { 02567 if (peer->expire > -1) 02568 ast_sched_del(sched, peer->expire); 02569 peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, (void*)peer->name); 02570 } 02571 AST_LIST_LOCK(&peers); 02572 AST_LIST_INSERT_HEAD(&peers, peer, entry); 02573 AST_LIST_UNLOCK(&peers); 02574 if (ast_test_flag(peer, IAX_DYNAMIC)) 02575 reg_source_db(peer); 02576 } else { 02577 ast_set_flag(peer, IAX_TEMPONLY); 02578 } 02579 02580 if (!ast_test_flag(&globalflags, IAX_RTIGNOREREGEXPIRE) && dynamic) { 02581 time(&nowtime); 02582 if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE) { 02583 memset(&peer->addr, 0, sizeof(peer->addr)); 02584 realtime_update_peer(peer->name, &peer->addr, 0); 02585 if (option_debug) 02586 ast_log(LOG_DEBUG, "realtime_peer: Bah, '%s' is expired (%d/%d/%d)!\n", 02587 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02588 } 02589 else { 02590 if (option_debug) 02591 ast_log(LOG_DEBUG, "realtime_peer: Registration for '%s' still active (%d/%d/%d)!\n", 02592 peername, (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 02593 } 02594 } 02595 02596 return peer; 02597 }
static void realtime_update_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin, | |||
time_t | regtime | |||
) | [static] |
Definition at line 2640 of file chan_iax2.c.
References ast_inet_ntoa(), and ast_update_realtime().
Referenced by __expire_registry(), realtime_peer(), update_peer(), and update_registry().
02641 { 02642 char port[10]; 02643 char regseconds[20]; 02644 02645 snprintf(regseconds, sizeof(regseconds), "%d", (int)regtime); 02646 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 02647 ast_update_realtime("iaxpeers", "name", peername, 02648 "ipaddr", ast_inet_ntoa(sin->sin_addr), "port", port, 02649 "regseconds", regseconds, NULL); 02650 }
static struct iax2_user* realtime_user | ( | const char * | username | ) | [static, read] |
Definition at line 2599 of file chan_iax2.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_load_realtime(), ast_set_flag, ast_test_flag, ast_variables_destroy(), build_user(), IAX_RTCACHEFRIENDS, IAX_TEMPONLY, ast_variable::name, ast_variable::next, ast_variable::value, and var.
02600 { 02601 struct ast_variable *var; 02602 struct ast_variable *tmp; 02603 struct iax2_user *user=NULL; 02604 02605 var = ast_load_realtime("iaxusers", "name", username, NULL); 02606 if (!var) 02607 return NULL; 02608 02609 tmp = var; 02610 while(tmp) { 02611 /* Make sure it's not a peer only... */ 02612 if (!strcasecmp(tmp->name, "type")) { 02613 if (strcasecmp(tmp->value, "friend") && 02614 strcasecmp(tmp->value, "user")) { 02615 return NULL; 02616 } 02617 } 02618 tmp = tmp->next; 02619 } 02620 02621 user = build_user(username, var, NULL, !ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)); 02622 02623 ast_variables_destroy(var); 02624 02625 if (!user) 02626 return NULL; 02627 02628 if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) { 02629 ast_set_flag(user, IAX_RTCACHEFRIENDS); 02630 AST_LIST_LOCK(&users); 02631 AST_LIST_INSERT_HEAD(&users, user, entry); 02632 AST_LIST_UNLOCK(&users); 02633 } else { 02634 ast_set_flag(user, IAX_TEMPONLY); 02635 } 02636 02637 return user; 02638 }
static void reg_source_db | ( | struct iax2_peer * | p | ) | [static] |
Definition at line 5619 of file chan_iax2.c.
References iax2_peer::addr, ast_db_get(), ast_device_state_changed(), ast_inet_ntoa(), ast_sched_add(), ast_sched_del(), ast_test_flag, ast_verbose(), iax2_peer::expire, expire_registry(), iax2_peer::expiry, iax2_poke_peer(), iax2_regfunk, IAX_TEMPONLY, option_verbose, register_peer_exten(), and VERBOSE_PREFIX_3.
Referenced by build_peer(), realtime_peer(), set_config(), and temp_peer().
05620 { 05621 char data[80]; 05622 struct in_addr in; 05623 char *c, *d; 05624 if (!ast_test_flag(p, IAX_TEMPONLY) && (!ast_db_get("IAX/Registry", p->name, data, sizeof(data)))) { 05625 c = strchr(data, ':'); 05626 if (c) { 05627 *c = '\0'; 05628 c++; 05629 if (inet_aton(data, &in)) { 05630 d = strchr(c, ':'); 05631 if (d) { 05632 *d = '\0'; 05633 d++; 05634 if (option_verbose > 2) 05635 ast_verbose(VERBOSE_PREFIX_3 "Seeding '%s' at %s:%d for %d\n", p->name, 05636 ast_inet_ntoa(in), atoi(c), atoi(d)); 05637 iax2_poke_peer(p, 0); 05638 p->expiry = atoi(d); 05639 memset(&p->addr, 0, sizeof(p->addr)); 05640 p->addr.sin_family = AF_INET; 05641 p->addr.sin_addr = in; 05642 p->addr.sin_port = htons(atoi(c)); 05643 if (p->expire > -1) 05644 ast_sched_del(sched, p->expire); 05645 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05646 p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name); 05647 if (iax2_regfunk) 05648 iax2_regfunk(p->name, 1); 05649 register_peer_exten(p, 1); 05650 } 05651 05652 } 05653 } 05654 } 05655 }
static void register_peer_exten | ( | struct iax2_peer * | peer, | |
int | onoff | |||
) | [static] |
Definition at line 5548 of file chan_iax2.c.
References ast_add_extension(), ast_context_remove_extension(), ast_exists_extension(), ast_free, ast_strdup, ast_strlen_zero(), ext, S_OR, and strsep().
Referenced by __expire_registry(), destroy_peer(), expire_register(), parse_register_contact(), reg_source_db(), sip_destroy_peer(), and update_registry().
05549 { 05550 char multi[256]; 05551 char *stringp, *ext; 05552 if (!ast_strlen_zero(regcontext)) { 05553 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 05554 stringp = multi; 05555 while((ext = strsep(&stringp, "&"))) { 05556 if (onoff) { 05557 if (!ast_exists_extension(NULL, regcontext, ext, 1, NULL)) 05558 ast_add_extension(regcontext, 1, ext, 1, NULL, NULL, 05559 "Noop", ast_strdup(peer->name), ast_free, "IAX2"); 05560 } else 05561 ast_context_remove_extension(regcontext, ext, 1, NULL); 05562 } 05563 } 05564 }
static int register_verify | ( | int | callno, | |
struct sockaddr_in * | sin, | |||
struct iax_ies * | ies | |||
) | [static] |
Verify inbound registration.
Definition at line 5025 of file chan_iax2.c.
References iax2_peer::addr, ast_apply_ha(), ast_check_signature, ast_clear_flag, ast_device_state_changed(), ast_inet_ntoa(), ast_key_get, AST_KEY_PUBLIC, ast_log(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, iax2_peer::authmethods, destroy_peer(), chan_iax2_pvt::expiry, find_peer(), iax2_peer::ha, IAX_AUTH_MD5, IAX_AUTH_PLAINTEXT, IAX_AUTH_RSA, IAX_DYNAMIC, IAX_STATE_AUTHENTICATED, IAX_STATE_UNCHANGED, IAX_TEMPONLY, iaxs, inaddrcmp(), key(), LOG_NOTICE, LOG_WARNING, iax_ies::md5_result, MD5Final(), MD5Init(), MD5Update(), iax_ies::password, iax_ies::refresh, iax_ies::rsa_result, secret, strsep(), and iax_ies::username.
Referenced by handle_request_register(), and socket_process().
05026 { 05027 char requeststr[256] = ""; 05028 char peer[256] = ""; 05029 char md5secret[256] = ""; 05030 char rsasecret[256] = ""; 05031 char secret[256] = ""; 05032 struct iax2_peer *p; 05033 struct ast_key *key; 05034 char *keyn; 05035 int x; 05036 int expire = 0; 05037 05038 ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED); 05039 /* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */ 05040 if (ies->username) 05041 ast_copy_string(peer, ies->username, sizeof(peer)); 05042 if (ies->password) 05043 ast_copy_string(secret, ies->password, sizeof(secret)); 05044 if (ies->md5_result) 05045 ast_copy_string(md5secret, ies->md5_result, sizeof(md5secret)); 05046 if (ies->rsa_result) 05047 ast_copy_string(rsasecret, ies->rsa_result, sizeof(rsasecret)); 05048 if (ies->refresh) 05049 expire = ies->refresh; 05050 05051 if (ast_strlen_zero(peer)) { 05052 ast_log(LOG_NOTICE, "Empty registration from %s\n", ast_inet_ntoa(sin->sin_addr)); 05053 return -1; 05054 } 05055 05056 /* SLD: first call to lookup peer during registration */ 05057 p = find_peer(peer, 1); 05058 05059 if (!p) { 05060 if (authdebug) 05061 ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05062 return -1; 05063 } 05064 05065 if (!ast_test_flag(p, IAX_DYNAMIC)) { 05066 if (authdebug) 05067 ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr)); 05068 if (ast_test_flag(p, IAX_TEMPONLY)) 05069 destroy_peer(p); 05070 return -1; 05071 } 05072 05073 if (!ast_apply_ha(p->ha, sin)) { 05074 if (authdebug) 05075 ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05076 if (ast_test_flag(p, IAX_TEMPONLY)) 05077 destroy_peer(p); 05078 return -1; 05079 } 05080 if (!inaddrcmp(&p->addr, sin)) 05081 ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED); 05082 ast_string_field_set(iaxs[callno], secret, p->secret); 05083 ast_string_field_set(iaxs[callno], inkeys, p->inkeys); 05084 /* Check secret against what we have on file */ 05085 if (!ast_strlen_zero(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05086 if (!ast_strlen_zero(p->inkeys)) { 05087 char tmpkeys[256]; 05088 char *stringp=NULL; 05089 ast_copy_string(tmpkeys, p->inkeys, sizeof(tmpkeys)); 05090 stringp=tmpkeys; 05091 keyn = strsep(&stringp, ":"); 05092 while(keyn) { 05093 key = ast_key_get(keyn, AST_KEY_PUBLIC); 05094 if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) { 05095 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05096 break; 05097 } else if (!key) 05098 ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn); 05099 keyn = strsep(&stringp, ":"); 05100 } 05101 if (!keyn) { 05102 if (authdebug) 05103 ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys); 05104 if (ast_test_flag(p, IAX_TEMPONLY)) 05105 destroy_peer(p); 05106 return -1; 05107 } 05108 } else { 05109 if (authdebug) 05110 ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer); 05111 if (ast_test_flag(p, IAX_TEMPONLY)) 05112 destroy_peer(p); 05113 return -1; 05114 } 05115 } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { 05116 struct MD5Context md5; 05117 unsigned char digest[16]; 05118 char *tmppw, *stringp; 05119 05120 tmppw = ast_strdupa(p->secret); 05121 stringp = tmppw; 05122 while((tmppw = strsep(&stringp, ";"))) { 05123 MD5Init(&md5); 05124 MD5Update(&md5, (unsigned char *)iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); 05125 MD5Update(&md5, (unsigned char *)tmppw, strlen(tmppw)); 05126 MD5Final(digest, &md5); 05127 for (x=0;x<16;x++) 05128 sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ 05129 if (!strcasecmp(requeststr, md5secret)) 05130 break; 05131 } 05132 if (tmppw) { 05133 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05134 } else { 05135 if (authdebug) 05136 ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(sin->sin_addr), p->name, requeststr, md5secret); 05137 if (ast_test_flag(p, IAX_TEMPONLY)) 05138 destroy_peer(p); 05139 return -1; 05140 } 05141 } else if (!ast_strlen_zero(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) { 05142 /* They've provided a plain text password and we support that */ 05143 if (strcmp(secret, p->secret)) { 05144 if (authdebug) 05145 ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name); 05146 if (ast_test_flag(p, IAX_TEMPONLY)) 05147 destroy_peer(p); 05148 return -1; 05149 } else 05150 ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED); 05151 } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) { 05152 if (authdebug) 05153 ast_log(LOG_NOTICE, "Inappropriate authentication received\n"); 05154 if (ast_test_flag(p, IAX_TEMPONLY)) 05155 destroy_peer(p); 05156 return -1; 05157 } 05158 ast_string_field_set(iaxs[callno], peer, peer); 05159 /* Choose lowest expiry number */ 05160 if (expire && (expire < iaxs[callno]->expiry)) 05161 iaxs[callno]->expiry = expire; 05162 05163 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05164 05165 if (ast_test_flag(p, IAX_TEMPONLY)) 05166 destroy_peer(p); 05167 return 0; 05168 05169 }
static int registry_authrequest | ( | const char * | name, | |
int | callno | |||
) | [static] |
Definition at line 5764 of file chan_iax2.c.
References AST_FRAME_IAX, ast_log(), ast_random(), ast_string_field_set, ast_test_flag, iax2_peer::authmethods, iax_ie_data::buf, destroy_peer(), find_peer(), IAX_AUTH_MD5, IAX_AUTH_RSA, IAX_COMMAND_REGAUTH, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_AUTHMETHODS, IAX_IE_CHALLENGE, IAX_IE_USERNAME, IAX_TEMPONLY, iaxs, LOG_WARNING, iax_ie_data::pos, and send_command().
Referenced by socket_process().
05765 { 05766 struct iax_ie_data ied; 05767 struct iax2_peer *p; 05768 char challenge[10]; 05769 /* SLD: third call to find_peer in registration */ 05770 p = find_peer(name, 1); 05771 if (p) { 05772 memset(&ied, 0, sizeof(ied)); 05773 iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods); 05774 if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) { 05775 /* Build the challenge */ 05776 snprintf(challenge, sizeof(challenge), "%d", (int)ast_random()); 05777 ast_string_field_set(iaxs[callno], challenge, challenge); 05778 /* snprintf(iaxs[callno]->challenge, sizeof(iaxs[callno]->challenge), "%d", (int)ast_random()); */ 05779 iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge); 05780 } 05781 iax_ie_append_str(&ied, IAX_IE_USERNAME, name); 05782 if (ast_test_flag(p, IAX_TEMPONLY)) 05783 destroy_peer(p); 05784 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);; 05785 } 05786 ast_log(LOG_WARNING, "No such peer '%s'\n", name); 05787 return 0; 05788 }
static int registry_rerequest | ( | struct iax_ies * | ies, | |
int | callno, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 5790 of file chan_iax2.c.
References iax2_registry::addr, AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), authenticate(), iax_ies::authmethods, iax_ie_data::buf, iax_ies::challenge, IAX_COMMAND_REGREQ, iax_ie_append_short(), iax_ie_append_str(), IAX_IE_REFRESH, IAX_IE_USERNAME, iaxs, inaddrcmp(), LOG_NOTICE, LOG_WARNING, iax_ie_data::pos, iax2_registry::refresh, chan_iax2_pvt::reg, REG_STATE_AUTHSENT, REG_STATE_NOAUTH, iax2_registry::regstate, iax2_registry::secret, send_command(), iax2_registry::username, and iax_ies::username.
Referenced by socket_process().
05791 { 05792 struct iax2_registry *reg; 05793 /* Start pessimistic */ 05794 struct iax_ie_data ied; 05795 char peer[256] = ""; 05796 char challenge[256] = ""; 05797 int res; 05798 int authmethods = 0; 05799 if (ies->authmethods) 05800 authmethods = ies->authmethods; 05801 if (ies->username) 05802 ast_copy_string(peer, ies->username, sizeof(peer)); 05803 if (ies->challenge) 05804 ast_copy_string(challenge, ies->challenge, sizeof(challenge)); 05805 memset(&ied, 0, sizeof(ied)); 05806 reg = iaxs[callno]->reg; 05807 if (reg) { 05808 if (inaddrcmp(®->addr, sin)) { 05809 ast_log(LOG_WARNING, "Received unsolicited registry authenticate request from '%s'\n", ast_inet_ntoa(sin->sin_addr)); 05810 return -1; 05811 } 05812 if (ast_strlen_zero(reg->secret)) { 05813 ast_log(LOG_NOTICE, "No secret associated with peer '%s'\n", reg->username); 05814 reg->regstate = REG_STATE_NOAUTH; 05815 return -1; 05816 } 05817 iax_ie_append_str(&ied, IAX_IE_USERNAME, reg->username); 05818 iax_ie_append_short(&ied, IAX_IE_REFRESH, reg->refresh); 05819 if (reg->secret[0] == '[') { 05820 char tmpkey[256]; 05821 ast_copy_string(tmpkey, reg->secret + 1, sizeof(tmpkey)); 05822 tmpkey[strlen(tmpkey) - 1] = '\0'; 05823 res = authenticate(challenge, NULL, tmpkey, authmethods, &ied, sin, NULL, NULL); 05824 } else 05825 res = authenticate(challenge, reg->secret, NULL, authmethods, &ied, sin, NULL, NULL); 05826 if (!res) { 05827 reg->regstate = REG_STATE_AUTHSENT; 05828 return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGREQ, 0, ied.buf, ied.pos, -1); 05829 } else 05830 return -1; 05831 ast_log(LOG_WARNING, "Registry acknowledge on unknown registery '%s'\n", peer); 05832 } else 05833 ast_log(LOG_NOTICE, "Can't reregister without a reg\n"); 05834 return -1; 05835 }
static char* regstate2str | ( | int | regstate | ) | [static] |
Definition at line 4339 of file chan_iax2.c.
References REG_STATE_AUTHSENT, REG_STATE_NOAUTH, REG_STATE_REGISTERED, REG_STATE_REGSENT, REG_STATE_REJECTED, REG_STATE_TIMEOUT, and REG_STATE_UNREGISTERED.
Referenced by handle_response_register(), iax2_show_registry(), sip_reg_timeout(), and sip_show_registry().
04340 { 04341 switch(regstate) { 04342 case REG_STATE_UNREGISTERED: 04343 return "Unregistered"; 04344 case REG_STATE_REGSENT: 04345 return "Request Sent"; 04346 case REG_STATE_AUTHSENT: 04347 return "Auth. Sent"; 04348 case REG_STATE_REGISTERED: 04349 return "Registered"; 04350 case REG_STATE_REJECTED: 04351 return "Rejected"; 04352 case REG_STATE_TIMEOUT: 04353 return "Timeout"; 04354 case REG_STATE_NOAUTH: 04355 return "No Authentication"; 04356 default: 04357 return "Unknown"; 04358 } 04359 }
static int reload | ( | void | ) | [static] |
Definition at line 9547 of file chan_iax2.c.
References reload_config().
09548 { 09549 return reload_config(); 09550 }
static int reload_config | ( | void | ) | [static] |
Definition at line 9507 of file chan_iax2.c.
References ast_clear_flag, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, config, delete_users(), iax2_do_register(), iax2_poke_peer(), IAX_FORCEJITTERBUF, IAX_NOTRANSFER, iax_provision_reload(), IAX_TRANSFERMEDIA, IAX_USEJITTERBUF, prune_peers(), prune_users(), reload_firmware(), and set_config().
09508 { 09509 char *config = "iax.conf"; 09510 struct iax2_registry *reg; 09511 struct iax2_peer *peer; 09512 09513 strcpy(accountcode, ""); 09514 strcpy(language, ""); 09515 strcpy(mohinterpret, "default"); 09516 strcpy(mohsuggest, ""); 09517 amaflags = 0; 09518 delayreject = 0; 09519 ast_clear_flag((&globalflags), IAX_NOTRANSFER); 09520 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 09521 ast_clear_flag((&globalflags), IAX_USEJITTERBUF); 09522 ast_clear_flag((&globalflags), IAX_FORCEJITTERBUF); 09523 delete_users(); 09524 set_config(config, 1); 09525 prune_peers(); 09526 prune_users(); 09527 AST_LIST_LOCK(®istrations); 09528 AST_LIST_TRAVERSE(®istrations, reg, entry) 09529 iax2_do_register(reg); 09530 AST_LIST_UNLOCK(®istrations); 09531 /* Qualify hosts, too */ 09532 AST_LIST_LOCK(&peers); 09533 AST_LIST_TRAVERSE(&peers, peer, entry) 09534 iax2_poke_peer(peer, 0); 09535 AST_LIST_UNLOCK(&peers); 09536 reload_firmware(); 09537 iax_provision_reload(); 09538 09539 return 0; 09540 }
static void reload_firmware | ( | void | ) | [static] |
Definition at line 1579 of file chan_iax2.c.
References ast_config_AST_DATA_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), iax_firmware::dead, destroy_firmware(), ast_firmware_list::lock, LOG_WARNING, iax_firmware::next, option_verbose, try_firmware(), VERBOSE_PREFIX_2, ast_firmware_list::wares, and waresl.
Referenced by load_module(), and reload_config().
01580 { 01581 struct iax_firmware *cur, *curl, *curp; 01582 DIR *fwd; 01583 struct dirent *de; 01584 char dir[256]; 01585 char fn[256]; 01586 /* Mark all as dead */ 01587 ast_mutex_lock(&waresl.lock); 01588 cur = waresl.wares; 01589 while(cur) { 01590 cur->dead = 1; 01591 cur = cur->next; 01592 } 01593 /* Now that we've freed them, load the new ones */ 01594 snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR); 01595 fwd = opendir(dir); 01596 if (fwd) { 01597 while((de = readdir(fwd))) { 01598 if (de->d_name[0] != '.') { 01599 snprintf(fn, sizeof(fn), "%s/%s", dir, de->d_name); 01600 if (!try_firmware(fn)) { 01601 if (option_verbose > 1) 01602 ast_verbose(VERBOSE_PREFIX_2 "Loaded firmware '%s'\n", de->d_name); 01603 } 01604 } 01605 } 01606 closedir(fwd); 01607 } else 01608 ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno)); 01609 01610 /* Clean up leftovers */ 01611 cur = waresl.wares; 01612 curp = NULL; 01613 while(cur) { 01614 curl = cur; 01615 cur = cur->next; 01616 if (curl->dead) { 01617 if (curp) { 01618 curp->next = cur; 01619 } else { 01620 waresl.wares = cur; 01621 } 01622 destroy_firmware(curl); 01623 } else { 01624 curp = cur; 01625 } 01626 } 01627 ast_mutex_unlock(&waresl.lock); 01628 }
Definition at line 6290 of file chan_iax2.c.
References iax_frame::callno, iax_rr::delay, iax_rr::dropped, iaxs, iax_rr::jitter, iax_rr::losscnt, iax_rr::losspct, iax_rr::ooo, iax_rr::packets, chan_iax2_pvt::remote_rr, iax_ies::rr_delay, iax_ies::rr_dropped, iax_ies::rr_jitter, iax_ies::rr_loss, iax_ies::rr_ooo, and iax_ies::rr_pkts.
Referenced by socket_process().
06291 { 06292 iaxs[fr->callno]->remote_rr.jitter = ies->rr_jitter; 06293 iaxs[fr->callno]->remote_rr.losspct = ies->rr_loss >> 24; 06294 iaxs[fr->callno]->remote_rr.losscnt = ies->rr_loss & 0xffffff; 06295 iaxs[fr->callno]->remote_rr.packets = ies->rr_pkts; 06296 iaxs[fr->callno]->remote_rr.delay = ies->rr_delay; 06297 iaxs[fr->callno]->remote_rr.dropped = ies->rr_dropped; 06298 iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; 06299 }
static void* sched_thread | ( | void * | ignore | ) | [static] |
Definition at line 8317 of file chan_iax2.c.
References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), and LOG_DEBUG.
Referenced by start_network_thread().
08318 { 08319 int count; 08320 int res; 08321 struct timeval tv; 08322 struct timespec ts; 08323 08324 for (;;) { 08325 res = ast_sched_wait(sched); 08326 if ((res > 1000) || (res < 0)) 08327 res = 1000; 08328 tv = ast_tvadd(ast_tvnow(), ast_samp2tv(res, 1000)); 08329 ts.tv_sec = tv.tv_sec; 08330 ts.tv_nsec = tv.tv_usec * 1000; 08331 08332 pthread_testcancel(); 08333 ast_mutex_lock(&sched_lock); 08334 ast_cond_timedwait(&sched_cond, &sched_lock, &ts); 08335 ast_mutex_unlock(&sched_lock); 08336 pthread_testcancel(); 08337 08338 count = ast_sched_runq(sched); 08339 if (count >= 20) 08340 ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count); 08341 } 08342 return NULL; 08343 }
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 2363 of file chan_iax2.c.
References __do_deliver(), iax_frame::af, ast_bridged_channel(), AST_CHAN_TP_WANTSJITTER, ast_codec_get_samples(), AST_FRAME_CNG, AST_FRAME_VOICE, ast_log(), ast_sched_del(), ast_test_flag, ast_tvadd(), calc_rxstamp(), iax_frame::callno, jb_frame::data, ast_frame::delivery, ast_frame::frametype, iax2_frame_free(), IAX_FORCEJITTERBUF, IAX_USEJITTERBUF, iaxs, chan_iax2_pvt::jb, JB_DROP, jb_getall(), JB_OK, jb_put(), jb_reset(), JB_SCHED, JB_TYPE_CONTROL, JB_TYPE_SILENCE, JB_TYPE_VOICE, chan_iax2_pvt::jbid, len, LOG_DEBUG, chan_iax2_pvt::owner, ast_channel_tech::properties, chan_iax2_pvt::rxcore, ast_channel::tech, iax_frame::ts, unwrap_timestamp(), and update_jbsched().
Referenced by socket_process().
02364 { 02365 int type, len; 02366 int ret; 02367 int needfree = 0; 02368 02369 /* Attempt to recover wrapped timestamps */ 02370 unwrap_timestamp(fr); 02371 02372 /* delivery time is sender's sent timestamp converted back into absolute time according to our clock */ 02373 if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) 02374 fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000)); 02375 else { 02376 #if 0 02377 ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n"); 02378 #endif 02379 fr->af.delivery = ast_tv(0,0); 02380 } 02381 02382 type = JB_TYPE_CONTROL; 02383 len = 0; 02384 02385 if(fr->af.frametype == AST_FRAME_VOICE) { 02386 type = JB_TYPE_VOICE; 02387 len = ast_codec_get_samples(&fr->af) / 8; 02388 } else if(fr->af.frametype == AST_FRAME_CNG) { 02389 type = JB_TYPE_SILENCE; 02390 } 02391 02392 if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) { 02393 if (tsout) 02394 *tsout = fr->ts; 02395 __do_deliver(fr); 02396 return -1; 02397 } 02398 02399 /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to 02400 * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */ 02401 if( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && 02402 iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) && 02403 (ast_bridged_channel(iaxs[fr->callno]->owner)->tech->properties & AST_CHAN_TP_WANTSJITTER)) { 02404 jb_frame frame; 02405 02406 /* deliver any frames in the jb */ 02407 while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) { 02408 __do_deliver(frame.data); 02409 /* __do_deliver() can make the call disappear */ 02410 if (!iaxs[fr->callno]) 02411 return -1; 02412 } 02413 02414 jb_reset(iaxs[fr->callno]->jb); 02415 02416 if (iaxs[fr->callno]->jbid > -1) 02417 ast_sched_del(sched, iaxs[fr->callno]->jbid); 02418 02419 iaxs[fr->callno]->jbid = -1; 02420 02421 /* deliver this frame now */ 02422 if (tsout) 02423 *tsout = fr->ts; 02424 __do_deliver(fr); 02425 return -1; 02426 } 02427 02428 /* insert into jitterbuffer */ 02429 /* TODO: Perhaps we could act immediately if it's not droppable and late */ 02430 ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts, 02431 calc_rxstamp(iaxs[fr->callno],fr->ts)); 02432 if (ret == JB_DROP) { 02433 needfree++; 02434 } else if (ret == JB_SCHED) { 02435 update_jbsched(iaxs[fr->callno]); 02436 } 02437 if (tsout) 02438 *tsout = fr->ts; 02439 if (needfree) { 02440 /* Free our iax frame */ 02441 iax2_frame_free(fr); 02442 return -1; 02443 } 02444 return 0; 02445 }
static int send_command | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno | |||
) | [static] |
Definition at line 4622 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().
04623 { 04624 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); 04625 }
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 4636 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().
04637 { 04638 /* It is assumed that the callno has already been locked */ 04639 iax2_predestroy(i->callno); 04640 return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 1); 04641 }
static int send_command_immediate | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno | |||
) | [static] |
Definition at line 4643 of file chan_iax2.c.
References __send_command().
Referenced by iax2_vnak(), and socket_process().
04644 { 04645 return __send_command(i, type, command, ts, data, datalen, seqno, 1, 0, 0); 04646 }
static int send_command_locked | ( | unsigned short | callno, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen, | |||
int | seqno | |||
) | [static] |
Definition at line 4627 of file chan_iax2.c.
References ast_mutex_lock(), ast_mutex_unlock(), iaxs, iaxsl, and send_command().
Referenced by iax2_answer(), iax2_digit_begin(), iax2_digit_end(), iax2_sendhtml(), iax2_sendimage(), iax2_sendtext(), iax2_setoption(), and iax2_transfer().
04628 { 04629 int res; 04630 ast_mutex_lock(&iaxsl[callno]); 04631 res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno); 04632 ast_mutex_unlock(&iaxsl[callno]); 04633 return res; 04634 }
static int send_command_transfer | ( | struct chan_iax2_pvt * | i, | |
char | type, | |||
int | command, | |||
unsigned int | ts, | |||
const unsigned char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 4648 of file chan_iax2.c.
References __send_command().
Referenced by socket_process(), and try_transfer().
04649 { 04650 return __send_command(i, type, command, ts, data, datalen, 0, 0, 1, 0); 04651 }
static int send_lagrq | ( | void * | data | ) | [static] |
Definition at line 1002 of file chan_iax2.c.
References __send_lagrq(), and schedule_action.
Referenced by __send_lagrq(), find_callno(), and make_trunk().
01003 { 01004 #ifdef SCHED_MULTITHREADED 01005 if (schedule_action(__send_lagrq, data)) 01006 #endif 01007 __send_lagrq(data); 01008 return 0; 01009 }
static int send_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 1701 of file chan_iax2.c.
References chan_iax2_pvt::addr, ast_inet_ntoa(), ast_log(), iax_frame::callno, iax_frame::data, iax_frame::datalen, error(), handle_error(), iax_showframe(), iaxs, LOG_DEBUG, option_debug, chan_iax2_pvt::peercallno, chan_iax2_pvt::transfer, transfer, iax_frame::transfer, and iax_frame::ts.
Referenced by __attempt_transmit(), iax2_send(), network_thread(), and vnak_retransmit().
01702 { 01703 int res; 01704 int callno = f->callno; 01705 01706 /* Don't send if there was an error, but return error instead */ 01707 if (!callno || !iaxs[callno] || iaxs[callno]->error) 01708 return -1; 01709 01710 /* Called with iaxsl held */ 01711 if (option_debug > 2 && iaxdebug) 01712 ast_log(LOG_DEBUG, "Sending %d on %d/%d to %s:%d\n", f->ts, callno, iaxs[callno]->peercallno, ast_inet_ntoa(iaxs[callno]->addr.sin_addr), ntohs(iaxs[callno]->addr.sin_port)); 01713 if (f->transfer) { 01714 if (iaxdebug) 01715 iax_showframe(f, NULL, 0, &iaxs[callno]->transfer, f->datalen - sizeof(struct ast_iax2_full_hdr)); 01716 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->transfer, 01717 sizeof(iaxs[callno]->transfer)); 01718 } else { 01719 if (iaxdebug) 01720 iax_showframe(f, NULL, 0, &iaxs[callno]->addr, f->datalen - sizeof(struct ast_iax2_full_hdr)); 01721 res = sendto(iaxs[callno]->sockfd, f->data, f->datalen, 0,(struct sockaddr *)&iaxs[callno]->addr, 01722 sizeof(iaxs[callno]->addr)); 01723 } 01724 if (res < 0) { 01725 if (option_debug && iaxdebug) 01726 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 01727 handle_error(); 01728 } else 01729 res = 0; 01730 return res; 01731 }
static int send_ping | ( | void * | data | ) | [static] |
Definition at line 967 of file chan_iax2.c.
References __send_ping(), and schedule_action.
Referenced by __send_ping(), find_callno(), and make_trunk().
00968 { 00969 #ifdef SCHED_MULTITHREADED 00970 if (schedule_action(__send_ping, data)) 00971 #endif 00972 __send_ping(data); 00973 return 0; 00974 }
static int send_trunk | ( | struct iax2_trunk_peer * | tpeer, | |
struct timeval * | now | |||
) | [static] |
Definition at line 5975 of file chan_iax2.c.
References iax2_trunk_peer::addr, iax_frame::afdata, ast_inet_ntoa(), ast_log(), ast_test_flag, calc_txpeerstamp(), iax2_trunk_peer::calls, ast_iax2_meta_hdr::cmddata, iax_frame::data, ast_iax2_meta_hdr::data, iax_frame::datalen, iax_frame::direction, DIRECTION_OUTGRESS, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, IAX_TRUNKTIMESTAMPS, LOG_DEBUG, ast_iax2_meta_hdr::metacmd, iax_frame::retrans, iax2_trunk_peer::sockfd, iax_frame::transfer, transmit_trunk(), iax2_trunk_peer::trunkdata, iax2_trunk_peer::trunkdatalen, ast_iax2_meta_trunk_hdr::ts, and ast_iax2_meta_hdr::zeros.
Referenced by timing_read().
05976 { 05977 int res = 0; 05978 struct iax_frame *fr; 05979 struct ast_iax2_meta_hdr *meta; 05980 struct ast_iax2_meta_trunk_hdr *mth; 05981 int calls = 0; 05982 05983 /* Point to frame */ 05984 fr = (struct iax_frame *)tpeer->trunkdata; 05985 /* Point to meta data */ 05986 meta = (struct ast_iax2_meta_hdr *)fr->afdata; 05987 mth = (struct ast_iax2_meta_trunk_hdr *)meta->data; 05988 if (tpeer->trunkdatalen) { 05989 /* We're actually sending a frame, so fill the meta trunk header and meta header */ 05990 meta->zeros = 0; 05991 meta->metacmd = IAX_META_TRUNK; 05992 if (ast_test_flag(&globalflags, IAX_TRUNKTIMESTAMPS)) 05993 meta->cmddata = IAX_META_TRUNK_MINI; 05994 else 05995 meta->cmddata = IAX_META_TRUNK_SUPERMINI; 05996 mth->ts = htonl(calc_txpeerstamp(tpeer, trunkfreq, now)); 05997 /* And the rest of the ast_iax2 header */ 05998 fr->direction = DIRECTION_OUTGRESS; 05999 fr->retrans = -1; 06000 fr->transfer = 0; 06001 /* Any appropriate call will do */ 06002 fr->data = fr->afdata; 06003 fr->datalen = tpeer->trunkdatalen + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr); 06004 res = transmit_trunk(fr, &tpeer->addr, tpeer->sockfd); 06005 calls = tpeer->calls; 06006 #if 0 06007 ast_log(LOG_DEBUG, "Trunking %d call chunks in %d bytes to %s:%d, ts=%d\n", calls, fr->datalen, ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), ntohl(mth->ts)); 06008 #endif 06009 /* Reset transmit trunk side data */ 06010 tpeer->trunkdatalen = 0; 06011 tpeer->calls = 0; 06012 } 06013 if (res < 0) 06014 return res; 06015 return calls; 06016 }
static int set_config | ( | char * | config_file, | |
int | reload | |||
) | [static] |
Load configuration.
Definition at line 9150 of file chan_iax2.c.
References ast_category_browse(), ast_cdr_amaflags2int(), ast_clear_flag, ast_config_destroy(), ast_config_load(), ast_context_create(), ast_context_find(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_netsock_bind(), ast_netsock_init(), ast_netsock_list_alloc(), ast_netsock_release(), ast_netsock_sockfd(), ast_netsock_unref(), ast_parse_allow_disallow(), ast_set2_flag, ast_set_flag, ast_set_flags_to, ast_str2tos(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), build_peer(), build_user(), DEFAULT_MAXMS, format, gen, get_encrypt_methods(), iax2_register(), IAX_CAPABILITY_FULLBANDWIDTH, IAX_CAPABILITY_LOWBANDWIDTH, IAX_CAPABILITY_MEDBANDWIDTH, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_DEFAULT_PORTNO, IAX_DEFAULT_REG_EXPIRE, IAX_DYNAMIC, IAX_FORCEJITTERBUF, IAX_NOTRANSFER, IAX_RTAUTOCLEAR, IAX_RTCACHEFRIENDS, IAX_RTIGNOREREGEXPIRE, IAX_RTUPDATE, IAX_TRANSFERMEDIA, IAX_TRUNKTIMESTAMPS, IAX_USEJITTERBUF, iaxmaxthreadcount, iaxthreadcount, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, option_verbose, portno, iax2_user::prefs, reg_source_db(), secret, set_timing(), socket_read(), ast_variable::value, and VERBOSE_PREFIX_2.
Referenced by load_module(), reload(), and reload_config().
09151 { 09152 struct ast_config *cfg, *ucfg; 09153 int capability=iax2_capability; 09154 struct ast_variable *v; 09155 char *cat; 09156 const char *utype; 09157 const char *tosval; 09158 int format; 09159 int portno = IAX_DEFAULT_PORTNO; 09160 int x; 09161 struct iax2_user *user; 09162 struct iax2_peer *peer; 09163 struct ast_netsock *ns; 09164 #if 0 09165 static unsigned short int last_port=0; 09166 #endif 09167 09168 cfg = ast_config_load(config_file); 09169 09170 if (!cfg) { 09171 ast_log(LOG_ERROR, "Unable to load config %s\n", config_file); 09172 return -1; 09173 } 09174 09175 /* Reset global codec prefs */ 09176 memset(&prefs, 0 , sizeof(struct ast_codec_pref)); 09177 09178 /* Reset Global Flags */ 09179 memset(&globalflags, 0, sizeof(globalflags)); 09180 ast_set_flag(&globalflags, IAX_RTUPDATE); 09181 09182 #ifdef SO_NO_CHECK 09183 nochecksums = 0; 09184 #endif 09185 09186 min_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09187 max_reg_expire = IAX_DEFAULT_REG_EXPIRE; 09188 09189 maxauthreq = 3; 09190 09191 v = ast_variable_browse(cfg, "general"); 09192 09193 /* Seed initial tos value */ 09194 tosval = ast_variable_retrieve(cfg, "general", "tos"); 09195 if (tosval) { 09196 if (ast_str2tos(tosval, &tos)) 09197 ast_log(LOG_WARNING, "Invalid tos value, see doc/ip-tos.txt for more information.\n"); 09198 } 09199 while(v) { 09200 if (!strcasecmp(v->name, "bindport")){ 09201 if (reload) 09202 ast_log(LOG_NOTICE, "Ignoring bindport on reload\n"); 09203 else 09204 portno = atoi(v->value); 09205 } else if (!strcasecmp(v->name, "pingtime")) 09206 ping_time = atoi(v->value); 09207 else if (!strcasecmp(v->name, "iaxthreadcount")) { 09208 if (reload) { 09209 if (atoi(v->value) != iaxthreadcount) 09210 ast_log(LOG_NOTICE, "Ignoring any changes to iaxthreadcount during reload\n"); 09211 } else { 09212 iaxthreadcount = atoi(v->value); 09213 if (iaxthreadcount < 1) { 09214 ast_log(LOG_NOTICE, "iaxthreadcount must be at least 1.\n"); 09215 iaxthreadcount = 1; 09216 } else if (iaxthreadcount > 256) { 09217 ast_log(LOG_NOTICE, "limiting iaxthreadcount to 256\n"); 09218 iaxthreadcount = 256; 09219 } 09220 } 09221 } else if (!strcasecmp(v->name, "iaxmaxthreadcount")) { 09222 if (reload) { 09223 AST_LIST_LOCK(&dynamic_list); 09224 iaxmaxthreadcount = atoi(v->value); 09225 AST_LIST_UNLOCK(&dynamic_list); 09226 } else { 09227 iaxmaxthreadcount = atoi(v->value); 09228 if (iaxmaxthreadcount < 0) { 09229 ast_log(LOG_NOTICE, "iaxmaxthreadcount must be at least 0.\n"); 09230 iaxmaxthreadcount = 0; 09231 } else if (iaxmaxthreadcount > 256) { 09232 ast_log(LOG_NOTICE, "Limiting iaxmaxthreadcount to 256\n"); 09233 iaxmaxthreadcount = 256; 09234 } 09235 } 09236 } else if (!strcasecmp(v->name, "nochecksums")) { 09237 #ifdef SO_NO_CHECK 09238 if (ast_true(v->value)) 09239 nochecksums = 1; 09240 else 09241 nochecksums = 0; 09242 #else 09243 if (ast_true(v->value)) 09244 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 09245 #endif 09246 } 09247 else if (!strcasecmp(v->name, "maxjitterbuffer")) 09248 maxjitterbuffer = atoi(v->value); 09249 else if (!strcasecmp(v->name, "resyncthreshold")) 09250 resyncthreshold = atoi(v->value); 09251 else if (!strcasecmp(v->name, "maxjitterinterps")) 09252 maxjitterinterps = atoi(v->value); 09253 else if (!strcasecmp(v->name, "lagrqtime")) 09254 lagrq_time = atoi(v->value); 09255 else if (!strcasecmp(v->name, "maxregexpire")) 09256 max_reg_expire = atoi(v->value); 09257 else if (!strcasecmp(v->name, "minregexpire")) 09258 min_reg_expire = atoi(v->value); 09259 else if (!strcasecmp(v->name, "bindaddr")) { 09260 if (reload) { 09261 ast_log(LOG_NOTICE, "Ignoring bindaddr on reload\n"); 09262 } else { 09263 if (!(ns = ast_netsock_bind(netsock, io, v->value, portno, tos, socket_read, NULL))) { 09264 ast_log(LOG_WARNING, "Unable apply binding to '%s' at line %d\n", v->value, v->lineno); 09265 } else { 09266 if (option_verbose > 1) { 09267 if (strchr(v->value, ':')) 09268 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s'\n", v->value); 09269 else 09270 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to '%s:%d'\n", v->value, portno); 09271 } 09272 if (defaultsockfd < 0) 09273 defaultsockfd = ast_netsock_sockfd(ns); 09274 ast_netsock_unref(ns); 09275 } 09276 } 09277 } else if (!strcasecmp(v->name, "authdebug")) 09278 authdebug = ast_true(v->value); 09279 else if (!strcasecmp(v->name, "encryption")) 09280 iax2_encryption = get_encrypt_methods(v->value); 09281 else if (!strcasecmp(v->name, "notransfer")) { 09282 ast_log(LOG_NOTICE, "The option 'notransfer' is deprecated in favor of 'transfer' which has options 'yes', 'no', and 'mediaonly'\n"); 09283 ast_clear_flag((&globalflags), IAX_TRANSFERMEDIA); 09284 ast_set2_flag((&globalflags), ast_true(v->value), IAX_NOTRANSFER); 09285 } else if (!strcasecmp(v->name, "transfer")) { 09286 if (!strcasecmp(v->value, "mediaonly")) { 09287 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_TRANSFERMEDIA); 09288 } else if (ast_true(v->value)) { 09289 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, 0); 09290 } else 09291 ast_set_flags_to((&globalflags), IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER); 09292 } else if (!strcasecmp(v->name, "codecpriority")) { 09293 if(!strcasecmp(v->value, "caller")) 09294 ast_set_flag((&globalflags), IAX_CODEC_USER_FIRST); 09295 else if(!strcasecmp(v->value, "disabled")) 09296 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 09297 else if(!strcasecmp(v->value, "reqonly")) { 09298 ast_set_flag((&globalflags), IAX_CODEC_NOCAP); 09299 ast_set_flag((&globalflags), IAX_CODEC_NOPREFS); 09300 } 09301 } else if (!strcasecmp(v->name, "jitterbuffer")) 09302 ast_set2_flag((&globalflags), ast_true(v->value), IAX_USEJITTERBUF); 09303 else if (!strcasecmp(v->name, "forcejitterbuffer")) 09304 ast_set2_flag((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF); 09305 else if (!strcasecmp(v->name, "delayreject")) 09306 delayreject = ast_true(v->value); 09307 else if (!strcasecmp(v->name, "rtcachefriends")) 09308 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTCACHEFRIENDS); 09309 else if (!strcasecmp(v->name, "rtignoreregexpire")) 09310 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTIGNOREREGEXPIRE); 09311 else if (!strcasecmp(v->name, "rtupdate")) 09312 ast_set2_flag((&globalflags), ast_true(v->value), IAX_RTUPDATE); 09313 else if (!strcasecmp(v->name, "trunktimestamps")) 09314 ast_set2_flag(&globalflags, ast_true(v->value), IAX_TRUNKTIMESTAMPS); 09315 else if (!strcasecmp(v->name, "rtautoclear")) { 09316 int i = atoi(v->value); 09317 if(i > 0) 09318 global_rtautoclear = i; 09319 else 09320 i = 0; 09321 ast_set2_flag((&globalflags), i || ast_true(v->value), IAX_RTAUTOCLEAR); 09322 } else if (!strcasecmp(v->name, "trunkfreq")) { 09323 trunkfreq = atoi(v->value); 09324 if (trunkfreq < 10) 09325 trunkfreq = 10; 09326 } else if (!strcasecmp(v->name, "autokill")) { 09327 if (sscanf(v->value, "%d", &x) == 1) { 09328 if (x >= 0) 09329 autokill = x; 09330 else 09331 ast_log(LOG_NOTICE, "Nice try, but autokill has to be >0 or 'yes' or 'no' at line %d\n", v->lineno); 09332 } else if (ast_true(v->value)) { 09333 autokill = DEFAULT_MAXMS; 09334 } else { 09335 autokill = 0; 09336 } 09337 } else if (!strcasecmp(v->name, "bandwidth")) { 09338 if (!strcasecmp(v->value, "low")) { 09339 capability = IAX_CAPABILITY_LOWBANDWIDTH; 09340 } else if (!strcasecmp(v->value, "medium")) { 09341 capability = IAX_CAPABILITY_MEDBANDWIDTH; 09342 } else if (!strcasecmp(v->value, "high")) { 09343 capability = IAX_CAPABILITY_FULLBANDWIDTH; 09344 } else 09345 ast_log(LOG_WARNING, "bandwidth must be either low, medium, or high\n"); 09346 } else if (!strcasecmp(v->name, "allow")) { 09347 ast_parse_allow_disallow(&prefs, &capability, v->value, 1); 09348 } else if (!strcasecmp(v->name, "disallow")) { 09349 ast_parse_allow_disallow(&prefs, &capability, v->value, 0); 09350 } else if (!strcasecmp(v->name, "register")) { 09351 iax2_register(v->value, v->lineno); 09352 } else if (!strcasecmp(v->name, "iaxcompat")) { 09353 iaxcompat = ast_true(v->value); 09354 } else if (!strcasecmp(v->name, "regcontext")) { 09355 ast_copy_string(regcontext, v->value, sizeof(regcontext)); 09356 /* Create context if it doesn't exist already */ 09357 if (!ast_context_find(regcontext)) 09358 ast_context_create(NULL, regcontext, "IAX2"); 09359 } else if (!strcasecmp(v->name, "tos")) { 09360 if (ast_str2tos(v->value, &tos)) 09361 ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/ip-tos.txt for more information.'\n", v->lineno); 09362 } else if (!strcasecmp(v->name, "accountcode")) { 09363 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 09364 } else if (!strcasecmp(v->name, "mohinterpret")) { 09365 ast_copy_string(mohinterpret, v->value, sizeof(user->mohinterpret)); 09366 } else if (!strcasecmp(v->name, "mohsuggest")) { 09367 ast_copy_string(mohsuggest, v->value, sizeof(user->mohsuggest)); 09368 } else if (!strcasecmp(v->name, "amaflags")) { 09369 format = ast_cdr_amaflags2int(v->value); 09370 if (format < 0) { 09371 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 09372 } else { 09373 amaflags = format; 09374 } 09375 } else if (!strcasecmp(v->name, "language")) { 09376 ast_copy_string(language, v->value, sizeof(language)); 09377 } else if (!strcasecmp(v->name, "maxauthreq")) { 09378 maxauthreq = atoi(v->value); 09379 if (maxauthreq < 0) 09380 maxauthreq = 0; 09381 } else if (!strcasecmp(v->name, "adsi")) { 09382 adsi = ast_true(v->value); 09383 } /*else if (strcasecmp(v->name,"type")) */ 09384 /* ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */ 09385 v = v->next; 09386 } 09387 09388 if (defaultsockfd < 0) { 09389 if (!(ns = ast_netsock_bind(netsock, io, "0.0.0.0", portno, tos, socket_read, NULL))) { 09390 ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno)); 09391 } else { 09392 if (option_verbose > 1) 09393 ast_verbose(VERBOSE_PREFIX_2 "Binding IAX2 to default address 0.0.0.0:%d\n", portno); 09394 defaultsockfd = ast_netsock_sockfd(ns); 09395 ast_netsock_unref(ns); 09396 } 09397 } 09398 if (reload) { 09399 ast_netsock_release(outsock); 09400 outsock = ast_netsock_list_alloc(); 09401 if (!outsock) { 09402 ast_log(LOG_ERROR, "Could not allocate outsock list.\n"); 09403 return -1; 09404 } 09405 ast_netsock_init(outsock); 09406 } 09407 09408 if (min_reg_expire > max_reg_expire) { 09409 ast_log(LOG_WARNING, "Minimum registration interval of %d is more than maximum of %d, resetting minimum to %d\n", 09410 min_reg_expire, max_reg_expire, max_reg_expire); 09411 min_reg_expire = max_reg_expire; 09412 } 09413 iax2_capability = capability; 09414 09415 ucfg = ast_config_load("users.conf"); 09416 if (ucfg) { 09417 struct ast_variable *gen; 09418 int genhasiax; 09419 int genregisteriax; 09420 const char *hasiax, *registeriax; 09421 09422 genhasiax = ast_true(ast_variable_retrieve(ucfg, "general", "hasiax")); 09423 genregisteriax = ast_true(ast_variable_retrieve(ucfg, "general", "registeriax")); 09424 gen = ast_variable_browse(ucfg, "general"); 09425 cat = ast_category_browse(ucfg, NULL); 09426 while (cat) { 09427 if (strcasecmp(cat, "general")) { 09428 hasiax = ast_variable_retrieve(ucfg, cat, "hasiax"); 09429 registeriax = ast_variable_retrieve(ucfg, cat, "registeriax"); 09430 if (ast_true(hasiax) || (!hasiax && genhasiax)) { 09431 /* Start with general parameters, then specific parameters, user and peer */ 09432 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 09433 if (user) { 09434 AST_LIST_LOCK(&users); 09435 AST_LIST_INSERT_HEAD(&users, user, entry); 09436 AST_LIST_UNLOCK(&users); 09437 } 09438 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 09439 if (peer) { 09440 AST_LIST_LOCK(&peers); 09441 AST_LIST_INSERT_HEAD(&peers, peer, entry); 09442 AST_LIST_UNLOCK(&peers); 09443 if (ast_test_flag(peer, IAX_DYNAMIC)) 09444 reg_source_db(peer); 09445 } 09446 } 09447 if (ast_true(registeriax) || (!registeriax && genregisteriax)) { 09448 char tmp[256]; 09449 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 09450 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 09451 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 09452 if (!host) 09453 host = ast_variable_retrieve(ucfg, "general", "host"); 09454 if (!username) 09455 username = ast_variable_retrieve(ucfg, "general", "username"); 09456 if (!secret) 09457 secret = ast_variable_retrieve(ucfg, "general", "secret"); 09458 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 09459 if (!ast_strlen_zero(secret)) 09460 snprintf(tmp, sizeof(tmp), "%s:%s@%s", username, secret, host); 09461 else 09462 snprintf(tmp, sizeof(tmp), "%s@%s", username, host); 09463 iax2_register(tmp, 0); 09464 } 09465 } 09466 } 09467 cat = ast_category_browse(ucfg, cat); 09468 } 09469 ast_config_destroy(ucfg); 09470 } 09471 09472 cat = ast_category_browse(cfg, NULL); 09473 while(cat) { 09474 if (strcasecmp(cat, "general")) { 09475 utype = ast_variable_retrieve(cfg, cat, "type"); 09476 if (utype) { 09477 if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) { 09478 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 09479 if (user) { 09480 AST_LIST_LOCK(&users); 09481 AST_LIST_INSERT_HEAD(&users, user, entry); 09482 AST_LIST_UNLOCK(&users); 09483 } 09484 } 09485 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) { 09486 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 09487 if (peer) { 09488 AST_LIST_LOCK(&peers); 09489 AST_LIST_INSERT_HEAD(&peers, peer, entry); 09490 AST_LIST_UNLOCK(&peers); 09491 if (ast_test_flag(peer, IAX_DYNAMIC)) 09492 reg_source_db(peer); 09493 } 09494 } else if (strcasecmp(utype, "user")) { 09495 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file); 09496 } 09497 } else 09498 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 09499 } 09500 cat = ast_category_browse(cfg, cat); 09501 } 09502 ast_config_destroy(cfg); 09503 set_timing(); 09504 return capability; 09505 }
static void set_timing | ( | void | ) | [static] |
Definition at line 9133 of file chan_iax2.c.
References ast_log(), and LOG_WARNING.
Referenced by set_config().
09134 { 09135 #ifdef HAVE_ZAPTEL 09136 int bs = trunkfreq * 8; 09137 if (timingfd > -1) { 09138 if ( 09139 #ifdef ZT_TIMERACK 09140 ioctl(timingfd, ZT_TIMERCONFIG, &bs) && 09141 #endif 09142 ioctl(timingfd, ZT_SET_BLOCKSIZE, &bs)) 09143 ast_log(LOG_WARNING, "Unable to set blocksize on timing source\n"); 09144 } 09145 #endif 09146 }
static void signal_condition | ( | ast_mutex_t * | lock, | |
ast_cond_t * | cond | |||
) | [static] |
Definition at line 742 of file chan_iax2.c.
References ast_cond_signal(), ast_mutex_lock(), and ast_mutex_unlock().
Referenced by __schedule_action(), iax2_transmit(), network_thread(), socket_read(), and update_jbsched().
00743 { 00744 ast_mutex_lock(lock); 00745 ast_cond_signal(cond); 00746 ast_mutex_unlock(lock); 00747 }
static int socket_process | ( | struct iax2_thread * | thread | ) | [static] |
Definition at line 6442 of file chan_iax2.c.
References chan_iax2_pvt::addr, iax_frame::af, iax_frame::afdatalen, chan_iax2_pvt::aseqno, ast_async_goto(), ast_best_codec(), ast_bridged_channel(), AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_SUBSCRIBED, AST_CAUSE_NO_ROUTE_DESTINATION, ast_clear_flag, ast_codec_choose(), ast_codec_get_samples(), ast_codec_pref_convert(), ast_codec_pref_index(), ast_codec_pref_string(), AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_device_state_changed(), ast_exists_extension(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_IAX, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname(), ast_iax2_new(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_parking_ext(), ast_queue_control(), ast_queue_control_data(), ast_sched_add(), ast_sched_del(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_STATE_RING, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose(), auth_fail(), authenticate_reply(), authenticate_request(), authenticate_verify(), chan_iax2_pvt::authmethods, iax_ie_data::buf, CACHE_FLAG_TRANSMITTED, calc_timestamp(), iax_ies::called_number, iax2_peer::callno, chan_iax2_pvt::callno, ast_iax2_meta_trunk_entry::callno, ast_iax2_mini_hdr::callno, iax_frame::callno, chan_iax2_pvt::capability, iax_ies::cause, iax_ies::causecode, check_access(), check_provisioning(), chan_iax2_pvt::chosenformat, cid_num, ast_iax2_meta_hdr::cmddata, iax_ies::codec_prefs, complete_dpreply(), complete_transfer(), construct_rr(), ast_iax2_full_hdr::csub, ast_frame::data, ast_iax2_meta_trunk_hdr::data, ast_iax2_meta_hdr::data, ast_frame::datalen, ast_iax2_full_hdr::dcallno, decrypt_frame(), iax_ies::devicetype, dp_lookup(), chan_iax2_pvt::encmethods, iax_ies::encmethods, chan_iax2_pvt::error, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, exists(), exten, iax_frame::final, find_callno(), find_tpeer(), fix_peerts(), iax2_dpcache::flags, iax_ies::format, format, chan_iax2_pvt::frames_received, ast_frame::frametype, iax_ies::fwdesc, ast_channel::hangupcause, iax2_peer::historicms, iax2_ack_registry(), iax2_destroy(), iax2_dprequest(), iax2_poke_peer_s(), iax2_send(), iax2_vnak(), IAX_ALREADYGONE, IAX_AUTH_MD5, IAX_CODEC_NOCAP, IAX_CODEC_NOPREFS, IAX_CODEC_USER_FIRST, IAX_COMMAND_ACCEPT, IAX_COMMAND_ACK, IAX_COMMAND_AUTHREP, IAX_COMMAND_AUTHREQ, IAX_COMMAND_DIAL, IAX_COMMAND_DPREP, IAX_COMMAND_DPREQ, IAX_COMMAND_FWDATA, IAX_COMMAND_FWDOWNL, IAX_COMMAND_HANGUP, IAX_COMMAND_INVAL, IAX_COMMAND_LAGRP, IAX_COMMAND_LAGRQ, IAX_COMMAND_NEW, IAX_COMMAND_PING, IAX_COMMAND_POKE, IAX_COMMAND_PONG, IAX_COMMAND_QUELCH, IAX_COMMAND_REGACK, IAX_COMMAND_REGAUTH, IAX_COMMAND_REGREJ, IAX_COMMAND_REGREL, IAX_COMMAND_REGREQ, IAX_COMMAND_REJECT, IAX_COMMAND_TRANSFER, IAX_COMMAND_TXACC, IAX_COMMAND_TXCNT, IAX_COMMAND_TXMEDIA, IAX_COMMAND_TXREADY, IAX_COMMAND_TXREJ, IAX_COMMAND_TXREL, IAX_COMMAND_TXREQ, IAX_COMMAND_UNQUELCH, IAX_COMMAND_UNSUPPORT, IAX_COMMAND_VNAK, IAX_DELAYPBXSTART, IAX_ENCRYPTED, iax_firmware_append(), IAX_FLAG_FULL, IAX_FLAG_RETRANS, iax_frame_wrap(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLNO, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_FORMAT, IAX_IE_IAX_UNKNOWN, IAX_META_TRUNK, IAX_META_TRUNK_MINI, IAX_META_TRUNK_SUPERMINI, iax_park(), iax_parse_ies(), IAX_PROVISION, IAX_QUELCH, iax_showframe(), IAX_STATE_AUTHENTICATED, IAX_STATE_STARTED, IAX_STATE_TBD, IAX_STATE_UNCHANGED, IAX_TRUNK, iax_ies::iax_unknown, iaxfrdup2(), iaxq, iaxs, iaxsl, inaddrcmp(), chan_iax2_pvt::initid, chan_iax2_pvt::iseqno, ast_iax2_full_hdr::iseqno, iax_frame::iseqno, chan_iax2_pvt::last, iax2_peer::lastms, ast_frame::len, ast_iax2_meta_trunk_entry::len, ast_iax2_meta_trunk_mini::len, len, ast_channel::lock, iax2_trunk_peer::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_trunk(), ast_frame::mallocd, manager_event(), iax2_peer::maxms, merge_encryption(), ast_iax2_meta_hdr::metacmd, ast_iax2_meta_trunk_mini::mini, iax_ies::musiconhold, ast_channel::nativeformats, NEW_ALLOW, NEW_PREVENT, ast_frame::offset, option_debug, option_verbose, chan_iax2_pvt::oseqno, iax_frame::oseqno, ast_iax2_full_hdr::oseqno, iax_frame::outoforder, chan_iax2_pvt::owner, pbx_builtin_setvar_helper(), iax2_dpcache::peer, chan_iax2_pvt::peercallno, chan_iax2_pvt::peercapability, chan_iax2_pvt::peerformat, iax2_peer::pokeexpire, iax2_peer::pokefreqnotok, iax2_peer::pokefreqok, iax_ie_data::pos, chan_iax2_pvt::prefs, iax_ies::provver, iax_ies::provverpres, raw_hangup(), ast_channel::readformat, iax_ies::refresh, REG_STATE_REJECTED, register_verify(), registry_authrequest(), registry_rerequest(), iax_frame::retries, chan_iax2_pvt::rprefs, chan_iax2_pvt::rseqno, iax2_trunk_peer::rxtrunktime, S_OR, ast_frame::samples, save_rr(), schedule_delivery(), send_command(), send_command_final(), send_command_immediate(), send_command_transfer(), iax_ies::serviceident, iax2_peer::smoothing, spawn_dp_lookup(), ast_frame::src, chan_iax2_pvt::state, stop_stuff(), ast_frame::subclass, iax_frame::transfer, TRANSFER_BEGIN, TRANSFER_MBEGIN, TRANSFER_MEDIA, TRANSFER_MEDIAPASS, TRANSFER_MREADY, TRANSFER_READY, TRANSFER_RELEASED, chan_iax2_pvt::transferring, iax2_trunk_peer::trunkact, try_transfer(), ast_iax2_full_hdr::ts, iax_frame::ts, ast_iax2_mini_hdr::ts, ast_iax2_meta_trunk_hdr::ts, ast_iax2_full_hdr::type, uncompress_subclass(), update_registry(), iax_ies::username, VERBOSE_PREFIX_3, VERBOSE_PREFIX_4, chan_iax2_pvt::videoformat, vnak_retransmit(), chan_iax2_pvt::voiceformat, and ast_iax2_meta_hdr::zeros.
Referenced by handle_deferred_full_frames(), and iax2_process_thread().
06443 { 06444 struct sockaddr_in sin; 06445 int res; 06446 int updatehistory=1; 06447 int new = NEW_PREVENT; 06448 void *ptr; 06449 int dcallno = 0; 06450 struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf; 06451 struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf; 06452 struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf; 06453 struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf; 06454 struct ast_iax2_meta_trunk_hdr *mth; 06455 struct ast_iax2_meta_trunk_entry *mte; 06456 struct ast_iax2_meta_trunk_mini *mtm; 06457 struct iax_frame *fr; 06458 struct iax_frame *cur; 06459 struct ast_frame f = { 0, }; 06460 struct ast_channel *c; 06461 struct iax2_dpcache *dp; 06462 struct iax2_peer *peer; 06463 struct iax2_trunk_peer *tpeer; 06464 struct timeval rxtrunktime; 06465 struct iax_ies ies; 06466 struct iax_ie_data ied0, ied1; 06467 int format; 06468 int fd; 06469 int exists; 06470 int minivid = 0; 06471 unsigned int ts; 06472 char empty[32]=""; /* Safety measure */ 06473 struct iax_frame *duped_fr; 06474 char host_pref_buf[128]; 06475 char caller_pref_buf[128]; 06476 struct ast_codec_pref pref; 06477 char *using_prefs = "mine"; 06478 06479 /* allocate an iax_frame with 4096 bytes of data buffer */ 06480 fr = alloca(sizeof(*fr) + 4096); 06481 fr->callno = 0; 06482 fr->afdatalen = 4096; /* From alloca() above */ 06483 06484 /* Copy frequently used parameters to the stack */ 06485 res = thread->buf_len; 06486 fd = thread->iofd; 06487 memcpy(&sin, &thread->iosin, sizeof(sin)); 06488 06489 if (res < sizeof(*mh)) { 06490 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh)); 06491 return 1; 06492 } 06493 if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) { 06494 if (res < sizeof(*vh)) { 06495 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)); 06496 return 1; 06497 } 06498 06499 /* This is a video frame, get call number */ 06500 fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, 1, fd); 06501 minivid = 1; 06502 } else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) { 06503 unsigned char metatype; 06504 06505 if (res < sizeof(*meta)) { 06506 ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 06507 return 1; 06508 } 06509 06510 /* This is a meta header */ 06511 switch(meta->metacmd) { 06512 case IAX_META_TRUNK: 06513 if (res < (sizeof(*meta) + sizeof(*mth))) { 06514 ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res, 06515 sizeof(*meta) + sizeof(*mth)); 06516 return 1; 06517 } 06518 mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data); 06519 ts = ntohl(mth->ts); 06520 metatype = meta->cmddata; 06521 res -= (sizeof(*meta) + sizeof(*mth)); 06522 ptr = mth->data; 06523 tpeer = find_tpeer(&sin, fd); 06524 if (!tpeer) { 06525 ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 06526 return 1; 06527 } 06528 tpeer->trunkact = ast_tvnow(); 06529 if (!ts || ast_tvzero(tpeer->rxtrunktime)) 06530 tpeer->rxtrunktime = tpeer->trunkact; 06531 rxtrunktime = tpeer->rxtrunktime; 06532 ast_mutex_unlock(&tpeer->lock); 06533 while(res >= sizeof(*mte)) { 06534 /* Process channels */ 06535 unsigned short callno, trunked_ts, len; 06536 06537 if (metatype == IAX_META_TRUNK_MINI) { 06538 mtm = (struct ast_iax2_meta_trunk_mini *)ptr; 06539 ptr += sizeof(*mtm); 06540 res -= sizeof(*mtm); 06541 len = ntohs(mtm->len); 06542 callno = ntohs(mtm->mini.callno); 06543 trunked_ts = ntohs(mtm->mini.ts); 06544 } else if (metatype == IAX_META_TRUNK_SUPERMINI) { 06545 mte = (struct ast_iax2_meta_trunk_entry *)ptr; 06546 ptr += sizeof(*mte); 06547 res -= sizeof(*mte); 06548 len = ntohs(mte->len); 06549 callno = ntohs(mte->callno); 06550 trunked_ts = 0; 06551 } else { 06552 ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 06553 break; 06554 } 06555 /* Stop if we don't have enough data */ 06556 if (len > res) 06557 break; 06558 fr->callno = find_callno(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, 1, fd); 06559 if (fr->callno) { 06560 ast_mutex_lock(&iaxsl[fr->callno]); 06561 /* If it's a valid call, deliver the contents. If not, we 06562 drop it, since we don't have a scallno to use for an INVAL */ 06563 /* Process as a mini frame */ 06564 memset(&f, 0, sizeof(f)); 06565 f.frametype = AST_FRAME_VOICE; 06566 if (iaxs[fr->callno]) { 06567 if (iaxs[fr->callno]->voiceformat > 0) { 06568 f.subclass = iaxs[fr->callno]->voiceformat; 06569 f.datalen = len; 06570 if (f.datalen >= 0) { 06571 if (f.datalen) 06572 f.data = ptr; 06573 if(trunked_ts) { 06574 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff); 06575 } else 06576 fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts); 06577 /* Don't pass any packets until we're started */ 06578 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 06579 /* Common things */ 06580 f.src = "IAX2"; 06581 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 06582 f.samples = ast_codec_get_samples(&f); 06583 iax_frame_wrap(fr, &f); 06584 duped_fr = iaxfrdup2(fr); 06585 if (duped_fr) { 06586 schedule_delivery(duped_fr, updatehistory, 1, &fr->ts); 06587 } 06588 /* It is possible for the pvt structure to go away after we call schedule_delivery */ 06589 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 06590 iaxs[fr->callno]->last = fr->ts; 06591 #if 1 06592 if (option_debug && iaxdebug) 06593 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 06594 #endif 06595 } 06596 } 06597 } else { 06598 ast_log(LOG_WARNING, "Datalen < 0?\n"); 06599 } 06600 } else { 06601 ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n "); 06602 iax2_vnak(fr->callno); 06603 } 06604 } 06605 ast_mutex_unlock(&iaxsl[fr->callno]); 06606 } 06607 ptr += len; 06608 res -= len; 06609 } 06610 06611 } 06612 return 1; 06613 } 06614 06615 #ifdef DEBUG_SUPPORT 06616 if (iaxdebug && (res >= sizeof(*fh))) 06617 iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh)); 06618 #endif 06619 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 06620 if (res < sizeof(*fh)) { 06621 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)); 06622 return 1; 06623 } 06624 06625 /* Get the destination call number */ 06626 dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS; 06627 /* Retrieve the type and subclass */ 06628 f.frametype = fh->type; 06629 if (f.frametype == AST_FRAME_VIDEO) { 06630 f.subclass = uncompress_subclass(fh->csub & ~0x40) | ((fh->csub >> 6) & 0x1); 06631 } else { 06632 f.subclass = uncompress_subclass(fh->csub); 06633 } 06634 if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == IAX_COMMAND_NEW) || (f.subclass == IAX_COMMAND_REGREQ) || 06635 (f.subclass == IAX_COMMAND_POKE) || (f.subclass == IAX_COMMAND_FWDOWNL) || 06636 (f.subclass == IAX_COMMAND_REGREL))) 06637 new = NEW_ALLOW; 06638 } else { 06639 /* Don't know anything about it yet */ 06640 f.frametype = AST_FRAME_NULL; 06641 f.subclass = 0; 06642 } 06643 06644 if (!fr->callno) 06645 fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, 1, fd); 06646 06647 if (fr->callno > 0) 06648 ast_mutex_lock(&iaxsl[fr->callno]); 06649 06650 if (!fr->callno || !iaxs[fr->callno]) { 06651 /* A call arrived for a nonexistent destination. Unless it's an "inval" 06652 frame, reply with an inval */ 06653 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 06654 /* We can only raw hangup control frames */ 06655 if (((f.subclass != IAX_COMMAND_INVAL) && 06656 (f.subclass != IAX_COMMAND_TXCNT) && 06657 (f.subclass != IAX_COMMAND_TXACC) && 06658 (f.subclass != IAX_COMMAND_FWDOWNL))|| 06659 (f.frametype != AST_FRAME_IAX)) 06660 raw_hangup(&sin, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS, ntohs(mh->callno) & ~IAX_FLAG_FULL, 06661 fd); 06662 } 06663 if (fr->callno > 0) 06664 ast_mutex_unlock(&iaxsl[fr->callno]); 06665 return 1; 06666 } 06667 if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) { 06668 if (decrypt_frame(fr->callno, fh, &f, &res)) { 06669 ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n"); 06670 ast_mutex_unlock(&iaxsl[fr->callno]); 06671 return 1; 06672 } 06673 #ifdef DEBUG_SUPPORT 06674 else if (iaxdebug) 06675 iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh)); 06676 #endif 06677 } 06678 06679 /* count this frame */ 06680 iaxs[fr->callno]->frames_received++; 06681 06682 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid && 06683 f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */ 06684 f.subclass != IAX_COMMAND_TXACC) /* for attended transfer */ 06685 iaxs[fr->callno]->peercallno = (unsigned short)(ntohs(mh->callno) & ~IAX_FLAG_FULL); 06686 if (ntohs(mh->callno) & IAX_FLAG_FULL) { 06687 if (option_debug && iaxdebug) 06688 ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); 06689 /* Check if it's out of order (and not an ACK or INVAL) */ 06690 fr->oseqno = fh->oseqno; 06691 fr->iseqno = fh->iseqno; 06692 fr->ts = ntohl(fh->ts); 06693 #ifdef IAXTESTS 06694 if (test_resync) { 06695 if (option_debug) 06696 ast_log(LOG_DEBUG, "Simulating frame ts resync, was %u now %u\n", fr->ts, fr->ts + test_resync); 06697 fr->ts += test_resync; 06698 } 06699 #endif /* IAXTESTS */ 06700 #if 0 06701 if ( (ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || 06702 ( (f.frametype != AST_FRAME_VOICE) && ! (f.frametype == AST_FRAME_IAX && 06703 (f.subclass == IAX_COMMAND_NEW || 06704 f.subclass == IAX_COMMAND_AUTHREQ || 06705 f.subclass == IAX_COMMAND_ACCEPT || 06706 f.subclass == IAX_COMMAND_REJECT)) ) ) 06707 #endif 06708 if ((ntohs(fh->dcallno) & IAX_FLAG_RETRANS) || (f.frametype != AST_FRAME_VOICE)) 06709 updatehistory = 0; 06710 if ((iaxs[fr->callno]->iseqno != fr->oseqno) && 06711 (iaxs[fr->callno]->iseqno || 06712 ((f.subclass != IAX_COMMAND_TXCNT) && 06713 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 06714 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 06715 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 06716 (f.subclass != IAX_COMMAND_TXACC)) || 06717 (f.frametype != AST_FRAME_IAX))) { 06718 if ( 06719 ((f.subclass != IAX_COMMAND_ACK) && 06720 (f.subclass != IAX_COMMAND_INVAL) && 06721 (f.subclass != IAX_COMMAND_TXCNT) && 06722 (f.subclass != IAX_COMMAND_TXREADY) && /* for attended transfer */ 06723 (f.subclass != IAX_COMMAND_TXREL) && /* for attended transfer */ 06724 (f.subclass != IAX_COMMAND_UNQUELCH ) && /* for attended transfer */ 06725 (f.subclass != IAX_COMMAND_TXACC) && 06726 (f.subclass != IAX_COMMAND_VNAK)) || 06727 (f.frametype != AST_FRAME_IAX)) { 06728 /* If it's not an ACK packet, it's out of order. */ 06729 if (option_debug) 06730 ast_log(LOG_DEBUG, "Packet arrived out of order (expecting %d, got %d) (frametype = %d, subclass = %d)\n", 06731 iaxs[fr->callno]->iseqno, fr->oseqno, f.frametype, f.subclass); 06732 /* Check to see if we need to request retransmission, 06733 * and take sequence number wraparound into account */ 06734 if ((unsigned char) (iaxs[fr->callno]->iseqno - fr->oseqno) < 128) { 06735 /* If we've already seen it, ack it XXX There's a border condition here XXX */ 06736 if ((f.frametype != AST_FRAME_IAX) || 06737 ((f.subclass != IAX_COMMAND_ACK) && (f.subclass != IAX_COMMAND_INVAL))) { 06738 if (option_debug) 06739 ast_log(LOG_DEBUG, "Acking anyway\n"); 06740 /* XXX Maybe we should handle its ack to us, but then again, it's probably outdated anyway, and if 06741 we have anything to send, we'll retransmit and get an ACK back anyway XXX */ 06742 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 06743 } 06744 } else { 06745 /* Send a VNAK requesting retransmission */ 06746 iax2_vnak(fr->callno); 06747 } 06748 ast_mutex_unlock(&iaxsl[fr->callno]); 06749 return 1; 06750 } 06751 } else { 06752 /* Increment unless it's an ACK or VNAK */ 06753 if (((f.subclass != IAX_COMMAND_ACK) && 06754 (f.subclass != IAX_COMMAND_INVAL) && 06755 (f.subclass != IAX_COMMAND_TXCNT) && 06756 (f.subclass != IAX_COMMAND_TXACC) && 06757 (f.subclass != IAX_COMMAND_VNAK)) || 06758 (f.frametype != AST_FRAME_IAX)) 06759 iaxs[fr->callno]->iseqno++; 06760 } 06761 /* A full frame */ 06762 if (res < sizeof(*fh)) { 06763 ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh)); 06764 ast_mutex_unlock(&iaxsl[fr->callno]); 06765 return 1; 06766 } 06767 /* Ensure text frames are NULL-terminated */ 06768 if (f.frametype == AST_FRAME_TEXT && thread->buf[res - 1] != '\0') { 06769 if (res < thread->buf_size) 06770 thread->buf[res++] = '\0'; 06771 else /* Trims one character from the text message, but that's better than overwriting the end of the buffer. */ 06772 thread->buf[res - 1] = '\0'; 06773 } 06774 f.datalen = res - sizeof(*fh); 06775 06776 /* Handle implicit ACKing unless this is an INVAL, and only if this is 06777 from the real peer, not the transfer peer */ 06778 if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 06779 ((f.subclass != IAX_COMMAND_INVAL) || 06780 (f.frametype != AST_FRAME_IAX))) { 06781 unsigned char x; 06782 int call_to_destroy; 06783 /* XXX This code is not very efficient. Surely there is a better way which still 06784 properly handles boundary conditions? XXX */ 06785 /* First we have to qualify that the ACKed value is within our window */ 06786 for (x=iaxs[fr->callno]->rseqno; x != iaxs[fr->callno]->oseqno; x++) 06787 if (fr->iseqno == x) 06788 break; 06789 if ((x != iaxs[fr->callno]->oseqno) || (iaxs[fr->callno]->oseqno == fr->iseqno)) { 06790 /* The acknowledgement is within our window. Time to acknowledge everything 06791 that it says to */ 06792 for (x=iaxs[fr->callno]->rseqno; x != fr->iseqno; x++) { 06793 /* Ack the packet with the given timestamp */ 06794 if (option_debug && iaxdebug) 06795 ast_log(LOG_DEBUG, "Cancelling transmission of packet %d\n", x); 06796 call_to_destroy = 0; 06797 AST_LIST_LOCK(&iaxq.queue); 06798 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 06799 /* If it's our call, and our timestamp, mark -1 retries */ 06800 if ((fr->callno == cur->callno) && (x == cur->oseqno)) { 06801 cur->retries = -1; 06802 /* Destroy call if this is the end */ 06803 if (cur->final) 06804 call_to_destroy = fr->callno; 06805 } 06806 } 06807 AST_LIST_UNLOCK(&iaxq.queue); 06808 if (call_to_destroy) { 06809 if (iaxdebug && option_debug) 06810 ast_log(LOG_DEBUG, "Really destroying %d, having been acked on final message\n", call_to_destroy); 06811 iax2_destroy(call_to_destroy); 06812 } 06813 } 06814 /* Note how much we've received acknowledgement for */ 06815 if (iaxs[fr->callno]) 06816 iaxs[fr->callno]->rseqno = fr->iseqno; 06817 else { 06818 /* Stop processing now */ 06819 ast_mutex_unlock(&iaxsl[fr->callno]); 06820 return 1; 06821 } 06822 } else 06823 ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr->iseqno, iaxs[fr->callno]->rseqno, iaxs[fr->callno]->oseqno); 06824 } 06825 if (inaddrcmp(&sin, &iaxs[fr->callno]->addr) && 06826 ((f.frametype != AST_FRAME_IAX) || 06827 ((f.subclass != IAX_COMMAND_TXACC) && 06828 (f.subclass != IAX_COMMAND_TXCNT)))) { 06829 /* Only messages we accept from a transfer host are TXACC and TXCNT */ 06830 ast_mutex_unlock(&iaxsl[fr->callno]); 06831 return 1; 06832 } 06833 06834 if (f.datalen) { 06835 if (f.frametype == AST_FRAME_IAX) { 06836 if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) { 06837 ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(sin.sin_addr)); 06838 ast_mutex_unlock(&iaxsl[fr->callno]); 06839 return 1; 06840 } 06841 f.data = NULL; 06842 f.datalen = 0; 06843 } else 06844 f.data = thread->buf + sizeof(*fh); 06845 } else { 06846 if (f.frametype == AST_FRAME_IAX) 06847 f.data = NULL; 06848 else 06849 f.data = empty; 06850 memset(&ies, 0, sizeof(ies)); 06851 } 06852 06853 /* when we receive the first full frame for a new incoming channel, 06854 it is safe to start the PBX on the channel because we have now 06855 completed a 3-way handshake with the peer */ 06856 if ((f.frametype == AST_FRAME_VOICE) || 06857 (f.frametype == AST_FRAME_VIDEO) || 06858 (f.frametype == AST_FRAME_IAX)) { 06859 if (ast_test_flag(iaxs[fr->callno], IAX_DELAYPBXSTART)) { 06860 ast_clear_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 06861 if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) { 06862 ast_mutex_unlock(&iaxsl[fr->callno]); 06863 return 1; 06864 } 06865 } 06866 } 06867 06868 if (f.frametype == AST_FRAME_VOICE) { 06869 if (f.subclass != iaxs[fr->callno]->voiceformat) { 06870 iaxs[fr->callno]->voiceformat = f.subclass; 06871 ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass); 06872 if (iaxs[fr->callno]->owner) { 06873 int orignative; 06874 retryowner: 06875 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 06876 ast_mutex_unlock(&iaxsl[fr->callno]); 06877 usleep(1); 06878 ast_mutex_lock(&iaxsl[fr->callno]); 06879 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner; 06880 } 06881 if (iaxs[fr->callno]) { 06882 if (iaxs[fr->callno]->owner) { 06883 orignative = iaxs[fr->callno]->owner->nativeformats; 06884 iaxs[fr->callno]->owner->nativeformats = f.subclass; 06885 if (iaxs[fr->callno]->owner->readformat) 06886 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 06887 iaxs[fr->callno]->owner->nativeformats = orignative; 06888 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 06889 } 06890 } else { 06891 ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n"); 06892 ast_mutex_unlock(&iaxsl[fr->callno]); 06893 return 1; 06894 } 06895 } 06896 } 06897 } 06898 if (f.frametype == AST_FRAME_VIDEO) { 06899 if (f.subclass != iaxs[fr->callno]->videoformat) { 06900 ast_log(LOG_DEBUG, "Ooh, video format changed to %d\n", f.subclass & ~0x1); 06901 iaxs[fr->callno]->videoformat = f.subclass & ~0x1; 06902 } 06903 } 06904 if (f.frametype == AST_FRAME_IAX) { 06905 if (iaxs[fr->callno]->initid > -1) { 06906 /* Don't auto congest anymore since we've gotten something usefulb ack */ 06907 ast_sched_del(sched, iaxs[fr->callno]->initid); 06908 iaxs[fr->callno]->initid = -1; 06909 } 06910 /* Handle the IAX pseudo frame itself */ 06911 if (option_debug && iaxdebug) 06912 ast_log(LOG_DEBUG, "IAX subclass %d received\n", f.subclass); 06913 06914 /* Update last ts unless the frame's timestamp originated with us. */ 06915 if (iaxs[fr->callno]->last < fr->ts && 06916 f.subclass != IAX_COMMAND_ACK && 06917 f.subclass != IAX_COMMAND_PONG && 06918 f.subclass != IAX_COMMAND_LAGRP) { 06919 iaxs[fr->callno]->last = fr->ts; 06920 if (option_debug && iaxdebug) 06921 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 06922 } 06923 06924 switch(f.subclass) { 06925 case IAX_COMMAND_ACK: 06926 /* Do nothing */ 06927 break; 06928 case IAX_COMMAND_QUELCH: 06929 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 06930 /* Generate Manager Hold event, if necessary*/ 06931 if (iaxs[fr->callno]->owner) { 06932 manager_event(EVENT_FLAG_CALL, "Hold", 06933 "Channel: %s\r\n" 06934 "Uniqueid: %s\r\n", 06935 iaxs[fr->callno]->owner->name, 06936 iaxs[fr->callno]->owner->uniqueid); 06937 } 06938 06939 ast_set_flag(iaxs[fr->callno], IAX_QUELCH); 06940 if (ies.musiconhold) { 06941 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) { 06942 const char *mohsuggest = iaxs[fr->callno]->mohsuggest; 06943 ast_queue_control_data(iaxs[fr->callno]->owner, AST_CONTROL_HOLD, 06944 S_OR(mohsuggest, NULL), 06945 !ast_strlen_zero(mohsuggest) ? strlen(mohsuggest) + 1 : 0); 06946 } 06947 } 06948 } 06949 break; 06950 case IAX_COMMAND_UNQUELCH: 06951 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 06952 /* Generate Manager Unhold event, if necessary*/ 06953 if (iaxs[fr->callno]->owner && ast_test_flag(iaxs[fr->callno], IAX_QUELCH)) { 06954 manager_event(EVENT_FLAG_CALL, "Unhold", 06955 "Channel: %s\r\n" 06956 "Uniqueid: %s\r\n", 06957 iaxs[fr->callno]->owner->name, 06958 iaxs[fr->callno]->owner->uniqueid); 06959 } 06960 06961 ast_clear_flag(iaxs[fr->callno], IAX_QUELCH); 06962 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner)) 06963 ast_queue_control(iaxs[fr->callno]->owner, AST_CONTROL_UNHOLD); 06964 } 06965 break; 06966 case IAX_COMMAND_TXACC: 06967 if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) { 06968 /* Ack the packet with the given timestamp */ 06969 AST_LIST_LOCK(&iaxq.queue); 06970 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 06971 /* Cancel any outstanding txcnt's */ 06972 if ((fr->callno == cur->callno) && (cur->transfer)) 06973 cur->retries = -1; 06974 } 06975 AST_LIST_UNLOCK(&iaxq.queue); 06976 memset(&ied1, 0, sizeof(ied1)); 06977 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->callno); 06978 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREADY, 0, ied1.buf, ied1.pos, -1); 06979 iaxs[fr->callno]->transferring = TRANSFER_READY; 06980 } 06981 break; 06982 case IAX_COMMAND_NEW: 06983 /* Ignore if it's already up */ 06984 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) 06985 break; 06986 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) 06987 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 06988 /* If we're in trunk mode, do it now, and update the trunk number in our frame before continuing */ 06989 if (ast_test_flag(iaxs[fr->callno], IAX_TRUNK)) { 06990 int new_callno; 06991 if ((new_callno = make_trunk(fr->callno, 1)) != -1) 06992 fr->callno = new_callno; 06993 } 06994 /* For security, always ack immediately */ 06995 if (delayreject) 06996 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 06997 if (check_access(fr->callno, &sin, &ies)) { 06998 /* They're not allowed on */ 06999 auth_fail(fr->callno, IAX_COMMAND_REJECT); 07000 if (authdebug) 07001 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); 07002 break; 07003 } 07004 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 07005 const char *context, *exten, *cid_num; 07006 07007 context = ast_strdupa(iaxs[fr->callno]->context); 07008 exten = ast_strdupa(iaxs[fr->callno]->exten); 07009 cid_num = ast_strdupa(iaxs[fr->callno]->cid_num); 07010 07011 /* This might re-enter the IAX code and need the lock */ 07012 ast_mutex_unlock(&iaxsl[fr->callno]); 07013 exists = ast_exists_extension(NULL, context, exten, 1, cid_num); 07014 ast_mutex_lock(&iaxsl[fr->callno]); 07015 07016 if (!iaxs[fr->callno]) { 07017 ast_mutex_unlock(&iaxsl[fr->callno]); 07018 return 1; 07019 } 07020 } else 07021 exists = 0; 07022 if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { 07023 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 07024 memset(&ied0, 0, sizeof(ied0)); 07025 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 07026 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 07027 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07028 if (authdebug) 07029 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); 07030 } else { 07031 /* Select an appropriate format */ 07032 07033 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07034 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07035 using_prefs = "reqonly"; 07036 } else { 07037 using_prefs = "disabled"; 07038 } 07039 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 07040 memset(&pref, 0, sizeof(pref)); 07041 strcpy(caller_pref_buf, "disabled"); 07042 strcpy(host_pref_buf, "disabled"); 07043 } else { 07044 using_prefs = "mine"; 07045 /* If the information elements are in here... use them */ 07046 if (ies.codec_prefs) 07047 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 07048 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07049 /* If we are codec_first_choice we let the caller have the 1st shot at picking the codec.*/ 07050 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07051 pref = iaxs[fr->callno]->rprefs; 07052 using_prefs = "caller"; 07053 } else { 07054 pref = iaxs[fr->callno]->prefs; 07055 } 07056 } else 07057 pref = iaxs[fr->callno]->prefs; 07058 07059 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 07060 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 07061 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 07062 } 07063 if (!format) { 07064 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07065 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 07066 if (!format) { 07067 memset(&ied0, 0, sizeof(ied0)); 07068 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07069 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07070 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07071 if (authdebug) { 07072 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07073 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); 07074 else 07075 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); 07076 } 07077 } else { 07078 /* Pick one... */ 07079 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07080 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 07081 format = 0; 07082 } else { 07083 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07084 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 07085 memset(&pref, 0, sizeof(pref)); 07086 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07087 strcpy(caller_pref_buf,"disabled"); 07088 strcpy(host_pref_buf,"disabled"); 07089 } else { 07090 using_prefs = "mine"; 07091 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07092 /* Do the opposite of what we tried above. */ 07093 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07094 pref = iaxs[fr->callno]->prefs; 07095 } else { 07096 pref = iaxs[fr->callno]->rprefs; 07097 using_prefs = "caller"; 07098 } 07099 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 07100 07101 } else /* if no codec_prefs IE do it the old way */ 07102 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07103 } 07104 } 07105 07106 if (!format) { 07107 memset(&ied0, 0, sizeof(ied0)); 07108 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07109 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07110 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07111 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07112 if (authdebug) 07113 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); 07114 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07115 break; 07116 } 07117 } 07118 } 07119 if (format) { 07120 /* No authentication required, let them in */ 07121 memset(&ied1, 0, sizeof(ied1)); 07122 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 07123 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 07124 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 07125 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07126 if (option_verbose > 2) 07127 ast_verbose(VERBOSE_PREFIX_3 "Accepting UNAUTHENTICATED call from %s:\n" 07128 "%srequested format = %s,\n" 07129 "%srequested prefs = %s,\n" 07130 "%sactual format = %s,\n" 07131 "%shost prefs = %s,\n" 07132 "%spriority = %s\n", 07133 ast_inet_ntoa(sin.sin_addr), 07134 VERBOSE_PREFIX_4, 07135 ast_getformatname(iaxs[fr->callno]->peerformat), 07136 VERBOSE_PREFIX_4, 07137 caller_pref_buf, 07138 VERBOSE_PREFIX_4, 07139 ast_getformatname(format), 07140 VERBOSE_PREFIX_4, 07141 host_pref_buf, 07142 VERBOSE_PREFIX_4, 07143 using_prefs); 07144 07145 iaxs[fr->callno]->chosenformat = format; 07146 ast_set_flag(iaxs[fr->callno], IAX_DELAYPBXSTART); 07147 } else { 07148 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 07149 /* If this is a TBD call, we're ready but now what... */ 07150 if (option_verbose > 2) 07151 ast_verbose(VERBOSE_PREFIX_3 "Accepted unauthenticated TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 07152 } 07153 } 07154 } 07155 break; 07156 } 07157 if (iaxs[fr->callno]->authmethods & IAX_AUTH_MD5) 07158 merge_encryption(iaxs[fr->callno],ies.encmethods); 07159 else 07160 iaxs[fr->callno]->encmethods = 0; 07161 if (!authenticate_request(iaxs[fr->callno])) 07162 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED); 07163 break; 07164 case IAX_COMMAND_DPREQ: 07165 /* Request status in the dialplan */ 07166 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD) && 07167 !ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED) && ies.called_number) { 07168 if (iaxcompat) { 07169 /* Spawn a thread for the lookup */ 07170 spawn_dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num); 07171 } else { 07172 /* Just look it up */ 07173 dp_lookup(fr->callno, iaxs[fr->callno]->context, ies.called_number, iaxs[fr->callno]->cid_num, 1); 07174 } 07175 } 07176 break; 07177 case IAX_COMMAND_HANGUP: 07178 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07179 ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr->callno); 07180 /* Set hangup cause according to remote */ 07181 if (ies.causecode && iaxs[fr->callno]->owner) 07182 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07183 /* Send ack immediately, before we destroy */ 07184 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07185 iax2_destroy(fr->callno); 07186 break; 07187 case IAX_COMMAND_REJECT: 07188 /* Set hangup cause according to remote */ 07189 if (ies.causecode && iaxs[fr->callno]->owner) 07190 iaxs[fr->callno]->owner->hangupcause = ies.causecode; 07191 07192 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07193 if (iaxs[fr->callno]->owner && authdebug) 07194 ast_log(LOG_WARNING, "Call rejected by %s: %s\n", 07195 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), 07196 ies.cause ? ies.cause : "<Unknown>"); 07197 ast_log(LOG_DEBUG, "Immediately destroying %d, having received reject\n", 07198 fr->callno); 07199 } 07200 /* Send ack immediately, before we destroy */ 07201 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, 07202 fr->ts, NULL, 0, fr->iseqno); 07203 if (!ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) 07204 iaxs[fr->callno]->error = EPERM; 07205 iax2_destroy(fr->callno); 07206 break; 07207 case IAX_COMMAND_TRANSFER: 07208 if (iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) && ies.called_number) { 07209 /* Set BLINDTRANSFER channel variables */ 07210 pbx_builtin_setvar_helper(iaxs[fr->callno]->owner, "BLINDTRANSFER", ast_bridged_channel(iaxs[fr->callno]->owner)->name); 07211 pbx_builtin_setvar_helper(ast_bridged_channel(iaxs[fr->callno]->owner), "BLINDTRANSFER", iaxs[fr->callno]->owner->name); 07212 if (!strcmp(ies.called_number, ast_parking_ext())) { 07213 if (iax_park(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->owner)) { 07214 ast_log(LOG_WARNING, "Failed to park call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name); 07215 } else if (ast_bridged_channel(iaxs[fr->callno]->owner)) 07216 ast_log(LOG_DEBUG, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name); 07217 } else { 07218 if (ast_async_goto(ast_bridged_channel(iaxs[fr->callno]->owner), iaxs[fr->callno]->context, ies.called_number, 1)) 07219 ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name, 07220 ies.called_number, iaxs[fr->callno]->context); 07221 else 07222 ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", ast_bridged_channel(iaxs[fr->callno]->owner)->name, 07223 ies.called_number, iaxs[fr->callno]->context); 07224 } 07225 } else 07226 ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr->callno); 07227 break; 07228 case IAX_COMMAND_ACCEPT: 07229 /* Ignore if call is already up or needs authentication or is a TBD */ 07230 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED)) 07231 break; 07232 if (ast_test_flag(iaxs[fr->callno], IAX_PROVISION)) { 07233 /* Send ack immediately, before we destroy */ 07234 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07235 iax2_destroy(fr->callno); 07236 break; 07237 } 07238 if (ies.format) { 07239 iaxs[fr->callno]->peerformat = ies.format; 07240 } else { 07241 if (iaxs[fr->callno]->owner) 07242 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->owner->nativeformats; 07243 else 07244 iaxs[fr->callno]->peerformat = iaxs[fr->callno]->capability; 07245 } 07246 if (option_verbose > 2) 07247 ast_verbose(VERBOSE_PREFIX_3 "Call accepted by %s (format %s)\n", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), ast_getformatname(iaxs[fr->callno]->peerformat)); 07248 if (!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) { 07249 memset(&ied0, 0, sizeof(ied0)); 07250 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07251 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07252 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07253 if (authdebug) 07254 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); 07255 } else { 07256 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07257 if (iaxs[fr->callno]->owner) { 07258 /* Switch us to use a compatible format */ 07259 iaxs[fr->callno]->owner->nativeformats = iaxs[fr->callno]->peerformat; 07260 if (option_verbose > 2) 07261 ast_verbose(VERBOSE_PREFIX_3 "Format for call is %s\n", ast_getformatname(iaxs[fr->callno]->owner->nativeformats)); 07262 retryowner2: 07263 if (ast_mutex_trylock(&iaxs[fr->callno]->owner->lock)) { 07264 ast_mutex_unlock(&iaxsl[fr->callno]); 07265 usleep(1); 07266 ast_mutex_lock(&iaxsl[fr->callno]); 07267 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) goto retryowner2; 07268 } 07269 07270 if (iaxs[fr->callno] && iaxs[fr->callno]->owner) { 07271 /* Setup read/write formats properly. */ 07272 if (iaxs[fr->callno]->owner->writeformat) 07273 ast_set_write_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->writeformat); 07274 if (iaxs[fr->callno]->owner->readformat) 07275 ast_set_read_format(iaxs[fr->callno]->owner, iaxs[fr->callno]->owner->readformat); 07276 ast_mutex_unlock(&iaxs[fr->callno]->owner->lock); 07277 } 07278 } 07279 } 07280 if (iaxs[fr->callno]) { 07281 ast_mutex_lock(&dpcache_lock); 07282 dp = iaxs[fr->callno]->dpentries; 07283 while(dp) { 07284 if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) { 07285 iax2_dprequest(dp, fr->callno); 07286 } 07287 dp = dp->peer; 07288 } 07289 ast_mutex_unlock(&dpcache_lock); 07290 } 07291 break; 07292 case IAX_COMMAND_POKE: 07293 /* Send back a pong packet with the original timestamp */ 07294 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, NULL, 0, -1); 07295 break; 07296 case IAX_COMMAND_PING: 07297 { 07298 struct iax_ie_data pingied; 07299 construct_rr(iaxs[fr->callno], &pingied); 07300 /* Send back a pong packet with the original timestamp */ 07301 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_PONG, fr->ts, pingied.buf, pingied.pos, -1); 07302 } 07303 break; 07304 case IAX_COMMAND_PONG: 07305 /* Calculate ping time */ 07306 iaxs[fr->callno]->pingtime = calc_timestamp(iaxs[fr->callno], 0, &f) - fr->ts; 07307 /* save RR info */ 07308 save_rr(fr, &ies); 07309 07310 if (iaxs[fr->callno]->peerpoke) { 07311 peer = iaxs[fr->callno]->peerpoke; 07312 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) { 07313 if (iaxs[fr->callno]->pingtime <= peer->maxms) { 07314 ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime); 07315 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07316 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07317 } 07318 } else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) { 07319 if (iaxs[fr->callno]->pingtime > peer->maxms) { 07320 ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime); 07321 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime); 07322 ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */ 07323 } 07324 } 07325 peer->lastms = iaxs[fr->callno]->pingtime; 07326 if (peer->smoothing && (peer->lastms > -1)) 07327 peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2; 07328 else if (peer->smoothing && peer->lastms < 0) 07329 peer->historicms = (0 + peer->historicms) / 2; 07330 else 07331 peer->historicms = iaxs[fr->callno]->pingtime; 07332 07333 /* Remove scheduled iax2_poke_noanswer */ 07334 if (peer->pokeexpire > -1) 07335 ast_sched_del(sched, peer->pokeexpire); 07336 /* Schedule the next cycle */ 07337 if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) 07338 peer->pokeexpire = ast_sched_add(sched, peer->pokefreqnotok, iax2_poke_peer_s, peer); 07339 else 07340 peer->pokeexpire = ast_sched_add(sched, peer->pokefreqok, iax2_poke_peer_s, peer); 07341 /* and finally send the ack */ 07342 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07343 /* And wrap up the qualify call */ 07344 iax2_destroy(fr->callno); 07345 peer->callno = 0; 07346 if (option_debug) 07347 ast_log(LOG_DEBUG, "Peer %s: got pong, lastms %d, historicms %d, maxms %d\n", peer->name, peer->lastms, peer->historicms, peer->maxms); 07348 } 07349 break; 07350 case IAX_COMMAND_LAGRQ: 07351 case IAX_COMMAND_LAGRP: 07352 f.src = "LAGRQ"; 07353 f.mallocd = 0; 07354 f.offset = 0; 07355 f.samples = 0; 07356 iax_frame_wrap(fr, &f); 07357 if(f.subclass == IAX_COMMAND_LAGRQ) { 07358 /* Received a LAGRQ - echo back a LAGRP */ 07359 fr->af.subclass = IAX_COMMAND_LAGRP; 07360 iax2_send(iaxs[fr->callno], &fr->af, fr->ts, -1, 0, 0, 0); 07361 } else { 07362 /* Received LAGRP in response to our LAGRQ */ 07363 unsigned int ts; 07364 /* This is a reply we've been given, actually measure the difference */ 07365 ts = calc_timestamp(iaxs[fr->callno], 0, &fr->af); 07366 iaxs[fr->callno]->lag = ts - fr->ts; 07367 if (option_debug && iaxdebug) 07368 ast_log(LOG_DEBUG, "Peer %s lag measured as %dms\n", 07369 ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr), iaxs[fr->callno]->lag); 07370 } 07371 break; 07372 case IAX_COMMAND_AUTHREQ: 07373 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 07374 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>"); 07375 break; 07376 } 07377 if (authenticate_reply(iaxs[fr->callno], &iaxs[fr->callno]->addr, &ies, iaxs[fr->callno]->secret, iaxs[fr->callno]->outkey)) { 07378 ast_log(LOG_WARNING, 07379 "I don't know how to authenticate %s to %s\n", 07380 ies.username ? ies.username : "<unknown>", ast_inet_ntoa(iaxs[fr->callno]->addr.sin_addr)); 07381 } 07382 break; 07383 case IAX_COMMAND_AUTHREP: 07384 /* For security, always ack immediately */ 07385 if (delayreject) 07386 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07387 /* Ignore once we've started */ 07388 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED | IAX_STATE_TBD)) { 07389 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>"); 07390 break; 07391 } 07392 if (authenticate_verify(iaxs[fr->callno], &ies)) { 07393 if (authdebug) 07394 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); 07395 memset(&ied0, 0, sizeof(ied0)); 07396 auth_fail(fr->callno, IAX_COMMAND_REJECT); 07397 break; 07398 } 07399 if (strcasecmp(iaxs[fr->callno]->exten, "TBD")) { 07400 /* This might re-enter the IAX code and need the lock */ 07401 exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num); 07402 } else 07403 exists = 0; 07404 if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { 07405 if (authdebug) 07406 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); 07407 memset(&ied0, 0, sizeof(ied0)); 07408 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 07409 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 07410 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07411 } else { 07412 /* Select an appropriate format */ 07413 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07414 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07415 using_prefs = "reqonly"; 07416 } else { 07417 using_prefs = "disabled"; 07418 } 07419 format = iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability; 07420 memset(&pref, 0, sizeof(pref)); 07421 strcpy(caller_pref_buf, "disabled"); 07422 strcpy(host_pref_buf, "disabled"); 07423 } else { 07424 using_prefs = "mine"; 07425 if (ies.codec_prefs) 07426 ast_codec_pref_convert(&iaxs[fr->callno]->rprefs, ies.codec_prefs, 32, 0); 07427 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07428 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07429 pref = iaxs[fr->callno]->rprefs; 07430 using_prefs = "caller"; 07431 } else { 07432 pref = iaxs[fr->callno]->prefs; 07433 } 07434 } else /* if no codec_prefs IE do it the old way */ 07435 pref = iaxs[fr->callno]->prefs; 07436 07437 format = ast_codec_choose(&pref, iaxs[fr->callno]->capability & iaxs[fr->callno]->peercapability, 0); 07438 ast_codec_pref_string(&iaxs[fr->callno]->rprefs, caller_pref_buf, sizeof(caller_pref_buf) - 1); 07439 ast_codec_pref_string(&iaxs[fr->callno]->prefs, host_pref_buf, sizeof(host_pref_buf) - 1); 07440 } 07441 if (!format) { 07442 if(!ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07443 ast_log(LOG_DEBUG, "We don't do requested format %s, falling back to peer capability %d\n", ast_getformatname(iaxs[fr->callno]->peerformat), iaxs[fr->callno]->peercapability); 07444 format = iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability; 07445 } 07446 if (!format) { 07447 if (authdebug) { 07448 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07449 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); 07450 else 07451 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); 07452 } 07453 memset(&ied0, 0, sizeof(ied0)); 07454 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07455 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07456 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07457 } else { 07458 /* Pick one... */ 07459 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) { 07460 if(!(iaxs[fr->callno]->peerformat & iaxs[fr->callno]->capability)) 07461 format = 0; 07462 } else { 07463 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOPREFS)) { 07464 using_prefs = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? "reqonly" : "disabled"; 07465 memset(&pref, 0, sizeof(pref)); 07466 format = ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP) ? 07467 iaxs[fr->callno]->peerformat : ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07468 strcpy(caller_pref_buf,"disabled"); 07469 strcpy(host_pref_buf,"disabled"); 07470 } else { 07471 using_prefs = "mine"; 07472 if (ast_codec_pref_index(&iaxs[fr->callno]->rprefs, 0)) { 07473 /* Do the opposite of what we tried above. */ 07474 if (ast_test_flag(iaxs[fr->callno], IAX_CODEC_USER_FIRST)) { 07475 pref = iaxs[fr->callno]->prefs; 07476 } else { 07477 pref = iaxs[fr->callno]->rprefs; 07478 using_prefs = "caller"; 07479 } 07480 format = ast_codec_choose(&pref, iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability, 1); 07481 } else /* if no codec_prefs IE do it the old way */ 07482 format = ast_best_codec(iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07483 } 07484 } 07485 if (!format) { 07486 ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr->callno]->peercapability & iaxs[fr->callno]->capability); 07487 if (authdebug) { 07488 if(ast_test_flag(iaxs[fr->callno], IAX_CODEC_NOCAP)) 07489 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); 07490 else 07491 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); 07492 } 07493 memset(&ied0, 0, sizeof(ied0)); 07494 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); 07495 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); 07496 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07497 } 07498 } 07499 } 07500 if (format) { 07501 /* Authentication received */ 07502 memset(&ied1, 0, sizeof(ied1)); 07503 iax_ie_append_int(&ied1, IAX_IE_FORMAT, format); 07504 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACCEPT, 0, ied1.buf, ied1.pos, -1); 07505 if (strcmp(iaxs[fr->callno]->exten, "TBD")) { 07506 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07507 if (option_verbose > 2) 07508 ast_verbose(VERBOSE_PREFIX_3 "Accepting AUTHENTICATED call from %s:\n" 07509 "%srequested format = %s,\n" 07510 "%srequested prefs = %s,\n" 07511 "%sactual format = %s,\n" 07512 "%shost prefs = %s,\n" 07513 "%spriority = %s\n", 07514 ast_inet_ntoa(sin.sin_addr), 07515 VERBOSE_PREFIX_4, 07516 ast_getformatname(iaxs[fr->callno]->peerformat), 07517 VERBOSE_PREFIX_4, 07518 caller_pref_buf, 07519 VERBOSE_PREFIX_4, 07520 ast_getformatname(format), 07521 VERBOSE_PREFIX_4, 07522 host_pref_buf, 07523 VERBOSE_PREFIX_4, 07524 using_prefs); 07525 07526 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07527 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format))) 07528 iax2_destroy(fr->callno); 07529 } else { 07530 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 07531 /* If this is a TBD call, we're ready but now what... */ 07532 if (option_verbose > 2) 07533 ast_verbose(VERBOSE_PREFIX_3 "Accepted AUTHENTICATED TBD call from %s\n", ast_inet_ntoa(sin.sin_addr)); 07534 } 07535 } 07536 } 07537 break; 07538 case IAX_COMMAND_DIAL: 07539 if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD)) { 07540 ast_clear_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD); 07541 ast_string_field_set(iaxs[fr->callno], exten, ies.called_number ? ies.called_number : "s"); 07542 if (!ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num)) { 07543 if (authdebug) 07544 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); 07545 memset(&ied0, 0, sizeof(ied0)); 07546 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); 07547 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); 07548 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07549 } else { 07550 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07551 if (option_verbose > 2) 07552 ast_verbose(VERBOSE_PREFIX_3 "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat); 07553 ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); 07554 send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); 07555 if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat))) 07556 iax2_destroy(fr->callno); 07557 } 07558 } 07559 break; 07560 case IAX_COMMAND_INVAL: 07561 iaxs[fr->callno]->error = ENOTCONN; 07562 ast_log(LOG_DEBUG, "Immediately destroying %d, having received INVAL\n", fr->callno); 07563 iax2_destroy(fr->callno); 07564 if (option_debug) 07565 ast_log(LOG_DEBUG, "Destroying call %d\n", fr->callno); 07566 break; 07567 case IAX_COMMAND_VNAK: 07568 ast_log(LOG_DEBUG, "Received VNAK: resending outstanding frames\n"); 07569 /* Force retransmission */ 07570 vnak_retransmit(fr->callno, fr->iseqno); 07571 break; 07572 case IAX_COMMAND_REGREQ: 07573 case IAX_COMMAND_REGREL: 07574 /* For security, always ack immediately */ 07575 if (delayreject) 07576 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07577 if (register_verify(fr->callno, &sin, &ies)) { 07578 /* Send delayed failure */ 07579 auth_fail(fr->callno, IAX_COMMAND_REGREJ); 07580 break; 07581 } 07582 if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) || 07583 ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) { 07584 if (f.subclass == IAX_COMMAND_REGREL) 07585 memset(&sin, 0, sizeof(sin)); 07586 if (update_registry(iaxs[fr->callno]->peer, &sin, fr->callno, ies.devicetype, fd, ies.refresh)) 07587 ast_log(LOG_WARNING, "Registry error\n"); 07588 if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) 07589 check_provisioning(&sin, fd, ies.serviceident, ies.provver); 07590 break; 07591 } 07592 registry_authrequest(iaxs[fr->callno]->peer, fr->callno); 07593 break; 07594 case IAX_COMMAND_REGACK: 07595 if (iax2_ack_registry(&ies, &sin, fr->callno)) 07596 ast_log(LOG_WARNING, "Registration failure\n"); 07597 /* Send ack immediately, before we destroy */ 07598 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07599 iax2_destroy(fr->callno); 07600 break; 07601 case IAX_COMMAND_REGREJ: 07602 if (iaxs[fr->callno]->reg) { 07603 if (authdebug) { 07604 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)); 07605 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelDriver: IAX2\r\nUsername: %s\r\nStatus: Rejected\r\nCause: %s\r\n", iaxs[fr->callno]->reg->username, ies.cause ? ies.cause : "<unknown>"); 07606 } 07607 iaxs[fr->callno]->reg->regstate = REG_STATE_REJECTED; 07608 } 07609 /* Send ack immediately, before we destroy */ 07610 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07611 iax2_destroy(fr->callno); 07612 break; 07613 case IAX_COMMAND_REGAUTH: 07614 /* Authentication request */ 07615 if (registry_rerequest(&ies, fr->callno, &sin)) { 07616 memset(&ied0, 0, sizeof(ied0)); 07617 iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); 07618 iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); 07619 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07620 } 07621 break; 07622 case IAX_COMMAND_TXREJ: 07623 iaxs[fr->callno]->transferring = 0; 07624 if (option_verbose > 2) 07625 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 07626 memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer)); 07627 if (iaxs[fr->callno]->bridgecallno) { 07628 if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) { 07629 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0; 07630 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1); 07631 } 07632 } 07633 break; 07634 case IAX_COMMAND_TXREADY: 07635 if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) || 07636 (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) { 07637 if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) 07638 iaxs[fr->callno]->transferring = TRANSFER_MREADY; 07639 else 07640 iaxs[fr->callno]->transferring = TRANSFER_READY; 07641 if (option_verbose > 2) 07642 ast_verbose(VERBOSE_PREFIX_3 "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>"); 07643 if (iaxs[fr->callno]->bridgecallno) { 07644 if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) || 07645 (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) { 07646 /* They're both ready, now release them. */ 07647 if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) { 07648 if (option_verbose > 2) 07649 ast_verbose(VERBOSE_PREFIX_3 "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 07650 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 07651 07652 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; 07653 iaxs[fr->callno]->transferring = TRANSFER_MEDIA; 07654 07655 memset(&ied0, 0, sizeof(ied0)); 07656 memset(&ied1, 0, sizeof(ied1)); 07657 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 07658 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 07659 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1); 07660 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1); 07661 } else { 07662 if (option_verbose > 2) 07663 ast_verbose(VERBOSE_PREFIX_3 "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>", 07664 iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>"); 07665 07666 iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED; 07667 iaxs[fr->callno]->transferring = TRANSFER_RELEASED; 07668 ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE); 07669 ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE); 07670 07671 /* Stop doing lag & ping requests */ 07672 stop_stuff(fr->callno); 07673 stop_stuff(iaxs[fr->callno]->bridgecallno); 07674 07675 memset(&ied0, 0, sizeof(ied0)); 07676 memset(&ied1, 0, sizeof(ied1)); 07677 iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno); 07678 iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno); 07679 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1); 07680 send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1); 07681 } 07682 07683 } 07684 } 07685 } 07686 break; 07687 case IAX_COMMAND_TXREQ: 07688 try_transfer(iaxs[fr->callno], &ies); 07689 break; 07690 case IAX_COMMAND_TXCNT: 07691 if (iaxs[fr->callno]->transferring) 07692 send_command_transfer(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); 07693 break; 07694 case IAX_COMMAND_TXREL: 07695 /* Send ack immediately, rather than waiting until we've changed addresses */ 07696 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07697 complete_transfer(fr->callno, &ies); 07698 stop_stuff(fr->callno); /* for attended transfer to work with libiax */ 07699 break; 07700 case IAX_COMMAND_TXMEDIA: 07701 if (iaxs[fr->callno]->transferring == TRANSFER_READY) { 07702 AST_LIST_LOCK(&iaxq.queue); 07703 AST_LIST_TRAVERSE(&iaxq.queue, cur, list) { 07704 /* Cancel any outstanding frames and start anew */ 07705 if ((fr->callno == cur->callno) && (cur->transfer)) { 07706 cur->retries = -1; 07707 } 07708 } 07709 AST_LIST_UNLOCK(&iaxq.queue); 07710 /* Start sending our media to the transfer address, but otherwise leave the call as-is */ 07711 iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS; 07712 } 07713 break; 07714 case IAX_COMMAND_DPREP: 07715 complete_dpreply(iaxs[fr->callno], &ies); 07716 break; 07717 case IAX_COMMAND_UNSUPPORT: 07718 ast_log(LOG_NOTICE, "Peer did not understand our iax command '%d'\n", ies.iax_unknown); 07719 break; 07720 case IAX_COMMAND_FWDOWNL: 07721 /* Firmware download */ 07722 memset(&ied0, 0, sizeof(ied0)); 07723 res = iax_firmware_append(&ied0, (unsigned char *)ies.devicetype, ies.fwdesc); 07724 if (res < 0) 07725 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); 07726 else if (res > 0) 07727 send_command_final(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 07728 else 07729 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_FWDATA, 0, ied0.buf, ied0.pos, -1); 07730 break; 07731 default: 07732 ast_log(LOG_DEBUG, "Unknown IAX command %d on %d/%d\n", f.subclass, fr->callno, iaxs[fr->callno]->peercallno); 07733 memset(&ied0, 0, sizeof(ied0)); 07734 iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass); 07735 send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1); 07736 } 07737 /* Don't actually pass these frames along */ 07738 if ((f.subclass != IAX_COMMAND_ACK) && 07739 (f.subclass != IAX_COMMAND_TXCNT) && 07740 (f.subclass != IAX_COMMAND_TXACC) && 07741 (f.subclass != IAX_COMMAND_INVAL) && 07742 (f.subclass != IAX_COMMAND_VNAK)) { 07743 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 07744 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07745 } 07746 ast_mutex_unlock(&iaxsl[fr->callno]); 07747 return 1; 07748 } 07749 /* Unless this is an ACK or INVAL frame, ack it */ 07750 if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno) 07751 send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); 07752 } else if (minivid) { 07753 f.frametype = AST_FRAME_VIDEO; 07754 if (iaxs[fr->callno]->videoformat > 0) 07755 f.subclass = iaxs[fr->callno]->videoformat | (ntohs(vh->ts) & 0x8000 ? 1 : 0); 07756 else { 07757 ast_log(LOG_WARNING, "Received mini frame before first full video frame\n "); 07758 iax2_vnak(fr->callno); 07759 ast_mutex_unlock(&iaxsl[fr->callno]); 07760 return 1; 07761 } 07762 f.datalen = res - sizeof(*vh); 07763 if (f.datalen) 07764 f.data = thread->buf + sizeof(*vh); 07765 else 07766 f.data = NULL; 07767 #ifdef IAXTESTS 07768 if (test_resync) { 07769 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | ((ntohs(vh->ts) + test_resync) & 0x7fff); 07770 } else 07771 #endif /* IAXTESTS */ 07772 fr->ts = (iaxs[fr->callno]->last & 0xFFFF8000L) | (ntohs(vh->ts) & 0x7fff); 07773 } else { 07774 /* A mini frame */ 07775 f.frametype = AST_FRAME_VOICE; 07776 if (iaxs[fr->callno]->voiceformat > 0) 07777 f.subclass = iaxs[fr->callno]->voiceformat; 07778 else { 07779 ast_log(LOG_WARNING, "Received mini frame before first full voice frame\n "); 07780 iax2_vnak(fr->callno); 07781 ast_mutex_unlock(&iaxsl[fr->callno]); 07782 return 1; 07783 } 07784 f.datalen = res - sizeof(struct ast_iax2_mini_hdr); 07785 if (f.datalen < 0) { 07786 ast_log(LOG_WARNING, "Datalen < 0?\n"); 07787 ast_mutex_unlock(&iaxsl[fr->callno]); 07788 return 1; 07789 } 07790 if (f.datalen) 07791 f.data = thread->buf + sizeof(*mh); 07792 else 07793 f.data = NULL; 07794 #ifdef IAXTESTS 07795 if (test_resync) { 07796 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ((ntohs(mh->ts) + test_resync) & 0xffff); 07797 } else 07798 #endif /* IAXTESTS */ 07799 fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | ntohs(mh->ts); 07800 /* FIXME? Surely right here would be the right place to undo timestamp wraparound? */ 07801 } 07802 /* Don't pass any packets until we're started */ 07803 if (!ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { 07804 ast_mutex_unlock(&iaxsl[fr->callno]); 07805 return 1; 07806 } 07807 /* Common things */ 07808 f.src = "IAX2"; 07809 f.mallocd = 0; 07810 f.offset = 0; 07811 f.len = 0; 07812 if (f.datalen && (f.frametype == AST_FRAME_VOICE)) { 07813 f.samples = ast_codec_get_samples(&f); 07814 /* We need to byteswap incoming slinear samples from network byte order */ 07815 if (f.subclass == AST_FORMAT_SLINEAR) 07816 ast_frame_byteswap_be(&f); 07817 } else 07818 f.samples = 0; 07819 iax_frame_wrap(fr, &f); 07820 07821 /* If this is our most recent packet, use it as our basis for timestamping */ 07822 if (iaxs[fr->callno]->last < fr->ts) { 07823 /*iaxs[fr->callno]->last = fr->ts; (do it afterwards cos schedule/forward_delivery needs the last ts too)*/ 07824 fr->outoforder = 0; 07825 } else { 07826 if (option_debug && iaxdebug) 07827 ast_log(LOG_DEBUG, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr->ts, iaxs[fr->callno]->last); 07828 fr->outoforder = -1; 07829 } 07830 duped_fr = iaxfrdup2(fr); 07831 if (duped_fr) { 07832 schedule_delivery(duped_fr, updatehistory, 0, &fr->ts); 07833 } 07834 if (iaxs[fr->callno] && iaxs[fr->callno]->last < fr->ts) { 07835 iaxs[fr->callno]->last = fr->ts; 07836 #if 1 07837 if (option_debug && iaxdebug) 07838 ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts); 07839 #endif 07840 } 07841 07842 /* Always run again */ 07843 ast_mutex_unlock(&iaxsl[fr->callno]); 07844 return 1; 07845 }
static int socket_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 6364 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_random(), ast_iax2_full_hdr::csub, defer_full_frame(), iax2_thread::ffinfo, find_idle_thread(), handle_error(), IAX_FLAG_FULL, IAX_IOSTATE_IDLE, IAX_IOSTATE_READY, inaddrcmp(), len, LOG_NOTICE, LOG_WARNING, ast_iax2_full_hdr::scallno, signal_condition(), t, thread, and ast_iax2_full_hdr::type.
Referenced by network_thread(), peer_set_srcaddr(), and set_config().
06365 { 06366 struct iax2_thread *thread; 06367 socklen_t len; 06368 time_t t; 06369 static time_t last_errtime = 0; 06370 struct ast_iax2_full_hdr *fh; 06371 06372 if (!(thread = find_idle_thread())) { 06373 time(&t); 06374 if (t != last_errtime) 06375 ast_log(LOG_NOTICE, "Out of idle IAX2 threads for I/O, pausing!\n"); 06376 last_errtime = t; 06377 usleep(1); 06378 return 1; 06379 } 06380 06381 len = sizeof(thread->iosin); 06382 thread->iofd = fd; 06383 thread->buf_len = recvfrom(fd, thread->readbuf, sizeof(thread->readbuf), 0, (struct sockaddr *) &thread->iosin, &len); 06384 thread->buf_size = sizeof(thread->readbuf); 06385 thread->buf = thread->readbuf; 06386 if (thread->buf_len < 0) { 06387 if (errno != ECONNREFUSED && errno != EAGAIN) 06388 ast_log(LOG_WARNING, "Error: %s\n", strerror(errno)); 06389 handle_error(); 06390 thread->iostate = IAX_IOSTATE_IDLE; 06391 signal_condition(&thread->lock, &thread->cond); 06392 return 1; 06393 } 06394 if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */ 06395 thread->iostate = IAX_IOSTATE_IDLE; 06396 signal_condition(&thread->lock, &thread->cond); 06397 return 1; 06398 } 06399 06400 /* Determine if this frame is a full frame; if so, and any thread is currently 06401 processing a full frame for the same callno from this peer, then drop this 06402 frame (and the peer will retransmit it) */ 06403 fh = (struct ast_iax2_full_hdr *) thread->buf; 06404 if (ntohs(fh->scallno) & IAX_FLAG_FULL) { 06405 struct iax2_thread *cur = NULL; 06406 uint16_t callno = ntohs(fh->scallno) & ~IAX_FLAG_FULL; 06407 06408 AST_LIST_LOCK(&active_list); 06409 AST_LIST_TRAVERSE(&active_list, cur, list) { 06410 if ((cur->ffinfo.callno == callno) && 06411 !inaddrcmp(&cur->ffinfo.sin, &thread->iosin)) 06412 break; 06413 } 06414 if (cur) { 06415 /* we found another thread processing a full frame for this call, 06416 so queue it up for processing later. */ 06417 defer_full_frame(thread, cur); 06418 AST_LIST_UNLOCK(&active_list); 06419 thread->iostate = IAX_IOSTATE_IDLE; 06420 signal_condition(&thread->lock, &thread->cond); 06421 return 1; 06422 } else { 06423 /* this thread is going to process this frame, so mark it */ 06424 thread->ffinfo.callno = callno; 06425 memcpy(&thread->ffinfo.sin, &thread->iosin, sizeof(thread->ffinfo.sin)); 06426 thread->ffinfo.type = fh->type; 06427 thread->ffinfo.csub = fh->csub; 06428 } 06429 AST_LIST_UNLOCK(&active_list); 06430 } 06431 06432 /* Mark as ready and send on its way */ 06433 thread->iostate = IAX_IOSTATE_READY; 06434 #ifdef DEBUG_SCHED_MULTITHREAD 06435 ast_copy_string(thread->curfunc, "socket_process", sizeof(thread->curfunc)); 06436 #endif 06437 signal_condition(&thread->lock, &thread->cond); 06438 06439 return 1; 06440 }
static void spawn_dp_lookup | ( | int | callno, | |
const char * | context, | |||
const char * | callednum, | |||
const char * | callerid | |||
) | [static] |
Definition at line 6151 of file chan_iax2.c.
References ast_calloc, ast_log(), ast_pthread_create, ast_strdup, dpreq_data::callednum, dpreq_data::callerid, dpreq_data::callno, dpreq_data::context, dp_lookup_thread(), and LOG_WARNING.
Referenced by socket_process().
06152 { 06153 pthread_t newthread; 06154 struct dpreq_data *dpr; 06155 pthread_attr_t attr; 06156 06157 if (!(dpr = ast_calloc(1, sizeof(*dpr)))) 06158 return; 06159 06160 pthread_attr_init(&attr); 06161 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06162 06163 dpr->callno = callno; 06164 ast_copy_string(dpr->context, context, sizeof(dpr->context)); 06165 ast_copy_string(dpr->callednum, callednum, sizeof(dpr->callednum)); 06166 if (callerid) 06167 dpr->callerid = ast_strdup(callerid); 06168 if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) { 06169 ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); 06170 } 06171 06172 pthread_attr_destroy(&attr); 06173 }
static int start_network_thread | ( | void | ) | [static] |
Definition at line 8413 of file chan_iax2.c.
References ast_calloc, ast_cond_init(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create, ast_pthread_create_background, ast_verbose(), free, iax2_process_thread(), IAX_TYPE_POOL, iaxthreadcount, LOG_WARNING, network_thread(), option_verbose, sched_thread(), thread, and VERBOSE_PREFIX_2.
Referenced by load_module().
08414 { 08415 pthread_attr_t attr; 08416 int threadcount = 0; 08417 int x; 08418 for (x = 0; x < iaxthreadcount; x++) { 08419 struct iax2_thread *thread = ast_calloc(1, sizeof(struct iax2_thread)); 08420 if (thread) { 08421 thread->type = IAX_TYPE_POOL; 08422 thread->threadnum = ++threadcount; 08423 ast_mutex_init(&thread->lock); 08424 ast_cond_init(&thread->cond, NULL); 08425 pthread_attr_init(&attr); 08426 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08427 if (ast_pthread_create(&thread->threadid, &attr, iax2_process_thread, thread)) { 08428 ast_log(LOG_WARNING, "Failed to create new thread!\n"); 08429 free(thread); 08430 thread = NULL; 08431 } 08432 AST_LIST_LOCK(&idle_list); 08433 AST_LIST_INSERT_TAIL(&idle_list, thread, list); 08434 AST_LIST_UNLOCK(&idle_list); 08435 } 08436 } 08437 ast_pthread_create_background(&schedthreadid, NULL, sched_thread, NULL); 08438 ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL); 08439 if (option_verbose > 1) 08440 ast_verbose(VERBOSE_PREFIX_2 "%d helper threaads started\n", threadcount); 08441 return 0; 08442 }
static void stop_stuff | ( | int | callno | ) | [static] |
Definition at line 5837 of file chan_iax2.c.
References iax2_destroy_helper(), and iaxs.
Referenced by socket_process().
05838 { 05839 iax2_destroy_helper(iaxs[callno]); 05840 }
static int timing_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | cbdata | |||
) | [static] |
Definition at line 6026 of file chan_iax2.c.
References iax2_trunk_peer::addr, ast_inet_ntoa(), AST_IO_PRI, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, iax2_trunk_expired(), iax2_trunk_peer::lock, LOG_DEBUG, LOG_WARNING, MAX_TRUNKDATA, iax2_trunk_peer::next, send_trunk(), tpeers, iax2_trunk_peer::trunkdataalloc, and iax2_trunk_peer::trunkdatalen.
Referenced by network_thread().
06027 { 06028 char buf[1024]; 06029 int res; 06030 struct iax2_trunk_peer *tpeer, *prev = NULL, *drop=NULL; 06031 int processed = 0; 06032 int totalcalls = 0; 06033 #ifdef ZT_TIMERACK 06034 int x = 1; 06035 #endif 06036 struct timeval now; 06037 if (iaxtrunkdebug) 06038 ast_verbose("Beginning trunk processing. Trunk queue ceiling is %d bytes per host\n", MAX_TRUNKDATA); 06039 gettimeofday(&now, NULL); 06040 if (events & AST_IO_PRI) { 06041 #ifdef ZT_TIMERACK 06042 /* Great, this is a timing interface, just call the ioctl */ 06043 if (ioctl(fd, ZT_TIMERACK, &x)) 06044 ast_log(LOG_WARNING, "Unable to acknowledge zap timer\n"); 06045 res = 0; 06046 #endif 06047 } else { 06048 /* Read and ignore from the pseudo channel for timing */ 06049 res = read(fd, buf, sizeof(buf)); 06050 if (res < 1) { 06051 ast_log(LOG_WARNING, "Unable to read from timing fd\n"); 06052 return 1; 06053 } 06054 } 06055 /* For each peer that supports trunking... */ 06056 ast_mutex_lock(&tpeerlock); 06057 tpeer = tpeers; 06058 while(tpeer) { 06059 processed++; 06060 res = 0; 06061 ast_mutex_lock(&tpeer->lock); 06062 /* We can drop a single tpeer per pass. That makes all this logic 06063 substantially easier */ 06064 if (!drop && iax2_trunk_expired(tpeer, &now)) { 06065 /* Take it out of the list, but don't free it yet, because it 06066 could be in use */ 06067 if (prev) 06068 prev->next = tpeer->next; 06069 else 06070 tpeers = tpeer->next; 06071 drop = tpeer; 06072 } else { 06073 res = send_trunk(tpeer, &now); 06074 if (iaxtrunkdebug) 06075 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); 06076 } 06077 totalcalls += res; 06078 res = 0; 06079 ast_mutex_unlock(&tpeer->lock); 06080 prev = tpeer; 06081 tpeer = tpeer->next; 06082 } 06083 ast_mutex_unlock(&tpeerlock); 06084 if (drop) { 06085 ast_mutex_lock(&drop->lock); 06086 /* Once we have this lock, we're sure nobody else is using it or could use it once we release it, 06087 because by the time they could get tpeerlock, we've already grabbed it */ 06088 ast_log(LOG_DEBUG, "Dropping unused iax2 trunk peer '%s:%d'\n", ast_inet_ntoa(drop->addr.sin_addr), ntohs(drop->addr.sin_port)); 06089 free(drop->trunkdata); 06090 ast_mutex_unlock(&drop->lock); 06091 ast_mutex_destroy(&drop->lock); 06092 free(drop); 06093 06094 } 06095 if (iaxtrunkdebug) 06096 ast_verbose("Ending trunk processing with %d peers and %d call chunks processed\n", processed, totalcalls); 06097 iaxtrunkdebug =0; 06098 return 1; 06099 }
static int transmit_trunk | ( | struct iax_frame * | f, | |
struct sockaddr_in * | sin, | |||
int | sockfd | |||
) | [static] |
Definition at line 1687 of file chan_iax2.c.
References ast_log(), iax_frame::data, iax_frame::datalen, handle_error(), LOG_DEBUG, and option_debug.
Referenced by send_trunk().
01688 { 01689 int res; 01690 res = sendto(sockfd, f->data, f->datalen, 0,(struct sockaddr *)sin, 01691 sizeof(*sin)); 01692 if (res < 0) { 01693 if (option_debug) 01694 ast_log(LOG_DEBUG, "Received error: %s\n", strerror(errno)); 01695 handle_error(); 01696 } else 01697 res = 0; 01698 return res; 01699 }
static int try_firmware | ( | char * | s | ) | [static] |
Definition at line 1378 of file chan_iax2.c.
References ast_calloc, ast_log(), ast_random(), ast_strlen_zero(), MD5Context::buf, ast_iax2_firmware_header::chksum, ast_iax2_firmware_header::data, ast_iax2_firmware_header::datalen, iax_firmware::dead, ast_iax2_firmware_header::devname, iax_firmware::fd, iax_firmware::fwh, IAX_FIRMWARE_MAGIC, last, len, LOG_WARNING, ast_iax2_firmware_header::magic, MD5Final(), MD5Init(), MD5Update(), iax_firmware::mmaplen, iax_firmware::next, ast_iax2_firmware_header::version, ast_firmware_list::wares, and waresl.
Referenced by reload_firmware().
01379 { 01380 struct stat stbuf; 01381 struct iax_firmware *cur; 01382 int ifd; 01383 int fd; 01384 int res; 01385 01386 struct ast_iax2_firmware_header *fwh, fwh2; 01387 struct MD5Context md5; 01388 unsigned char sum[16]; 01389 unsigned char buf[1024]; 01390 int len, chunk; 01391 char *s2; 01392 char *last; 01393 s2 = alloca(strlen(s) + 100); 01394 if (!s2) { 01395 ast_log(LOG_WARNING, "Alloca failed!\n"); 01396 return -1; 01397 } 01398 last = strrchr(s, '/'); 01399 if (last) 01400 last++; 01401 else 01402 last = s; 01403 snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random()); 01404 res = stat(s, &stbuf); 01405 if (res < 0) { 01406 ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno)); 01407 return -1; 01408 } 01409 /* Make sure it's not a directory */ 01410 if (S_ISDIR(stbuf.st_mode)) 01411 return -1; 01412 ifd = open(s, O_RDONLY); 01413 if (ifd < 0) { 01414 ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); 01415 return -1; 01416 } 01417 fd = open(s2, O_RDWR | O_CREAT | O_EXCL); 01418 if (fd < 0) { 01419 ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); 01420 close(ifd); 01421 return -1; 01422 } 01423 /* Unlink our newly created file */ 01424 unlink(s2); 01425 01426 /* Now copy the firmware into it */ 01427 len = stbuf.st_size; 01428 while(len) { 01429 chunk = len; 01430 if (chunk > sizeof(buf)) 01431 chunk = sizeof(buf); 01432 res = read(ifd, buf, chunk); 01433 if (res != chunk) { 01434 ast_log(LOG_WARNING, "Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01435 close(ifd); 01436 close(fd); 01437 return -1; 01438 } 01439 res = write(fd, buf, chunk); 01440 if (res != chunk) { 01441 ast_log(LOG_WARNING, "Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno)); 01442 close(ifd); 01443 close(fd); 01444 return -1; 01445 } 01446 len -= chunk; 01447 } 01448 close(ifd); 01449 /* Return to the beginning */ 01450 lseek(fd, 0, SEEK_SET); 01451 if ((res = read(fd, &fwh2, sizeof(fwh2))) != sizeof(fwh2)) { 01452 ast_log(LOG_WARNING, "Unable to read firmware header in '%s'\n", s); 01453 close(fd); 01454 return -1; 01455 } 01456 if (ntohl(fwh2.magic) != IAX_FIRMWARE_MAGIC) { 01457 ast_log(LOG_WARNING, "'%s' is not a valid firmware file\n", s); 01458 close(fd); 01459 return -1; 01460 } 01461 if (ntohl(fwh2.datalen) != (stbuf.st_size - sizeof(fwh2))) { 01462 ast_log(LOG_WARNING, "Invalid data length in firmware '%s'\n", s); 01463 close(fd); 01464 return -1; 01465 } 01466 if (fwh2.devname[sizeof(fwh2.devname) - 1] || ast_strlen_zero((char *)fwh2.devname)) { 01467 ast_log(LOG_WARNING, "No or invalid device type specified for '%s'\n", s); 01468 close(fd); 01469 return -1; 01470 } 01471 fwh = (struct ast_iax2_firmware_header*)mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 01472 if (fwh == (void *) -1) { 01473 ast_log(LOG_WARNING, "mmap failed: %s\n", strerror(errno)); 01474 close(fd); 01475 return -1; 01476 } 01477 MD5Init(&md5); 01478 MD5Update(&md5, fwh->data, ntohl(fwh->datalen)); 01479 MD5Final(sum, &md5); 01480 if (memcmp(sum, fwh->chksum, sizeof(sum))) { 01481 ast_log(LOG_WARNING, "Firmware file '%s' fails checksum\n", s); 01482 munmap((void*)fwh, stbuf.st_size); 01483 close(fd); 01484 return -1; 01485 } 01486 cur = waresl.wares; 01487 while(cur) { 01488 if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) { 01489 /* Found a candidate */ 01490 if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version))) 01491 /* The version we have on loaded is older, load this one instead */ 01492 break; 01493 /* This version is no newer than what we have. Don't worry about it. 01494 We'll consider it a proper load anyhow though */ 01495 munmap((void*)fwh, stbuf.st_size); 01496 close(fd); 01497 return 0; 01498 } 01499 cur = cur->next; 01500 } 01501 if (!cur) { 01502 /* Allocate a new one and link it */ 01503 if ((cur = ast_calloc(1, sizeof(*cur)))) { 01504 cur->fd = -1; 01505 cur->next = waresl.wares; 01506 waresl.wares = cur; 01507 } 01508 } 01509 if (cur) { 01510 if (cur->fwh) { 01511 munmap((void*)cur->fwh, cur->mmaplen); 01512 } 01513 if (cur->fd > -1) 01514 close(cur->fd); 01515 cur->fwh = fwh; 01516 cur->fd = fd; 01517 cur->mmaplen = stbuf.st_size; 01518 cur->dead = 0; 01519 } 01520 return 0; 01521 }
static int try_transfer | ( | struct chan_iax2_pvt * | pvt, | |
struct iax_ies * | ies | |||
) | [static] |
Definition at line 5300 of file chan_iax2.c.
References iax_ies::apparent_addr, AST_FRAME_IAX, ast_log(), iax_ie_data::buf, iax_ies::callno, IAX_COMMAND_TXCNT, iax_ie_append_int(), IAX_IE_TRANSFERID, LOG_WARNING, iax_ie_data::pos, send_command_transfer(), chan_iax2_pvt::transfer, TRANSFER_BEGIN, chan_iax2_pvt::transfercallno, iax_ies::transferid, chan_iax2_pvt::transferid, and chan_iax2_pvt::transferring.
Referenced by socket_process().
05301 { 05302 int newcall = 0; 05303 char newip[256]; 05304 struct iax_ie_data ied; 05305 struct sockaddr_in new; 05306 05307 05308 memset(&ied, 0, sizeof(ied)); 05309 if (ies->apparent_addr) 05310 bcopy(ies->apparent_addr, &new, sizeof(new)); 05311 if (ies->callno) 05312 newcall = ies->callno; 05313 if (!newcall || !new.sin_addr.s_addr || !new.sin_port) { 05314 ast_log(LOG_WARNING, "Invalid transfer request\n"); 05315 return -1; 05316 } 05317 pvt->transfercallno = newcall; 05318 memcpy(&pvt->transfer, &new, sizeof(pvt->transfer)); 05319 inet_aton(newip, &pvt->transfer.sin_addr); 05320 pvt->transfer.sin_family = AF_INET; 05321 pvt->transferring = TRANSFER_BEGIN; 05322 pvt->transferid = ies->transferid; 05323 if (ies->transferid) 05324 iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid); 05325 send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos); 05326 return 0; 05327 }
static int uncompress_subclass | ( | unsigned char | csub | ) | [static] |
Definition at line 1031 of file chan_iax2.c.
References IAX_FLAG_SC_LOG, and IAX_MAX_SHIFT.
Referenced by decode_frame(), and socket_process().
01032 { 01033 /* If the SC_LOG flag is set, return 2^csub otherwise csub */ 01034 if (csub & IAX_FLAG_SC_LOG) { 01035 /* special case for 'compressed' -1 */ 01036 if (csub == 0xff) 01037 return -1; 01038 else 01039 return 1 << (csub & ~IAX_FLAG_SC_LOG & IAX_MAX_SHIFT); 01040 } 01041 else 01042 return csub; 01043 }
static int unload_module | ( | void | ) | [static] |
Definition at line 10326 of file chan_iax2.c.
References __unload_module(), ast_custom_function_unregister(), and iaxpeer_function.
10327 { 10328 ast_custom_function_unregister(&iaxpeer_function); 10329 return __unload_module(); 10330 }
static void unlock_both | ( | unsigned short | callno0, | |
unsigned short | callno1 | |||
) | [static] |
Definition at line 3108 of file chan_iax2.c.
References ast_mutex_unlock(), and iaxsl.
Referenced by iax2_bridge().
03109 { 03110 ast_mutex_unlock(&iaxsl[callno1]); 03111 ast_mutex_unlock(&iaxsl[callno0]); 03112 }
static void unwrap_timestamp | ( | struct iax_frame * | fr | ) | [static] |
Definition at line 2221 of file chan_iax2.c.
References ast_log(), iax_frame::callno, iaxs, chan_iax2_pvt::last, LOG_DEBUG, option_debug, and iax_frame::ts.
Referenced by schedule_delivery().
02222 { 02223 int x; 02224 02225 if ( (fr->ts & 0xFFFF0000) == (iaxs[fr->callno]->last & 0xFFFF0000) ) { 02226 x = fr->ts - iaxs[fr->callno]->last; 02227 if (x < -50000) { 02228 /* Sudden big jump backwards in timestamp: 02229 What likely happened here is that miniframe timestamp has circled but we haven't 02230 gotten the update from the main packet. We'll just pretend that we did, and 02231 update the timestamp appropriately. */ 02232 fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) + 0x10000) | (fr->ts & 0xFFFF); 02233 if (option_debug && iaxdebug) 02234 ast_log(LOG_DEBUG, "schedule_delivery: pushed forward timestamp\n"); 02235 } 02236 if (x > 50000) { 02237 /* Sudden apparent big jump forwards in timestamp: 02238 What's likely happened is this is an old miniframe belonging to the previous 02239 top-16-bit timestamp that has turned up out of order. 02240 Adjust the timestamp appropriately. */ 02241 fr->ts = ( (iaxs[fr->callno]->last & 0xFFFF0000) - 0x10000) | (fr->ts & 0xFFFF); 02242 if (option_debug && iaxdebug) 02243 ast_log(LOG_DEBUG, "schedule_delivery: pushed back timestamp\n"); 02244 } 02245 } 02246 }
static void update_jbsched | ( | struct chan_iax2_pvt * | pvt | ) | [static] |
Definition at line 2250 of file chan_iax2.c.
References ast_sched_add(), ast_sched_del(), chan_iax2_pvt::callno, CALLNO_TO_PTR, get_from_jb(), chan_iax2_pvt::jb, jb_next(), chan_iax2_pvt::jbid, chan_iax2_pvt::rxcore, and signal_condition().
Referenced by __get_from_jb(), and schedule_delivery().
02251 { 02252 int when; 02253 02254 when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore); 02255 02256 when = jb_next(pvt->jb) - when; 02257 02258 if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid); 02259 02260 if(when <= 0) { 02261 /* XXX should really just empty until when > 0.. */ 02262 when = 1; 02263 } 02264 02265 pvt->jbid = ast_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno)); 02266 02267 /* Signal scheduler thread */ 02268 signal_condition(&sched_lock, &sched_cond); 02269 }
static void update_max_nontrunk | ( | void | ) | [static] |
Definition at line 1186 of file chan_iax2.c.
References ast_log(), iaxs, LOG_DEBUG, option_debug, and TRUNK_CALL_START.
Referenced by find_callno(), and make_trunk().
01187 { 01188 int max = 1; 01189 int x; 01190 /* XXX Prolly don't need locks here XXX */ 01191 for (x=1;x<TRUNK_CALL_START - 1; x++) { 01192 if (iaxs[x]) 01193 max = x + 1; 01194 } 01195 maxnontrunkcall = max; 01196 if (option_debug && iaxdebug) 01197 ast_log(LOG_DEBUG, "New max nontrunk callno is %d\n", max); 01198 }
static void update_max_trunk | ( | void | ) | [static] |
Definition at line 1172 of file chan_iax2.c.
References ast_log(), IAX_MAX_CALLS, iaxs, LOG_DEBUG, option_debug, and TRUNK_CALL_START.
Referenced by iax2_destroy(), and make_trunk().
01173 { 01174 int max = TRUNK_CALL_START; 01175 int x; 01176 /* XXX Prolly don't need locks here XXX */ 01177 for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) { 01178 if (iaxs[x]) 01179 max = x + 1; 01180 } 01181 maxtrunkcall = max; 01182 if (option_debug && iaxdebug) 01183 ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max); 01184 }
static int update_packet | ( | struct iax_frame * | f | ) | [static] |
Definition at line 1861 of file chan_iax2.c.
References iax_frame::callno, iax_frame::data, iax_frame::dcallno, ast_iax2_full_hdr::dcallno, IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iseqno, chan_iax2_pvt::iseqno, and iax_frame::iseqno.
Referenced by __attempt_transmit().
01862 { 01863 /* Called with iaxsl lock held, and iaxs[callno] non-NULL */ 01864 struct ast_iax2_full_hdr *fh = f->data; 01865 /* Mark this as a retransmission */ 01866 fh->dcallno = ntohs(IAX_FLAG_RETRANS | f->dcallno); 01867 /* Update iseqno */ 01868 f->iseqno = iaxs[f->callno]->iseqno; 01869 fh->iseqno = f->iseqno; 01870 return 0; 01871 }
static int update_registry | ( | const char * | name, | |
struct sockaddr_in * | sin, | |||
int | callno, | |||
char * | devtype, | |||
int | fd, | |||
unsigned short | refresh | |||
) | [static] |
Definition at line 5657 of file chan_iax2.c.
References iax2_peer::addr, ast_app_inboxcount(), ast_db_del(), ast_db_put(), ast_device_state_changed(), AST_FRAME_IAX, ast_inet_ntoa(), ast_log(), ast_sched_add(), ast_sched_del(), ast_strlen_zero(), ast_test_flag, ast_verbose(), iax_ie_data::buf, destroy_peer(), EVENT_FLAG_SYSTEM, iax2_peer::expire, expire_registry(), iax2_peer::expiry, find_peer(), iax2_datetime(), iax2_poke_peer(), iax2_regfunk, iax_check_version(), IAX_COMMAND_REGACK, IAX_HASCALLERID, IAX_IE_APPARENT_ADDR, iax_ie_append_addr(), iax_ie_append_int(), iax_ie_append_short(), iax_ie_append_str(), IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_DATETIME, IAX_IE_FIRMWAREVER, IAX_IE_MSGCOUNT, IAX_IE_REFRESH, IAX_IE_USERNAME, IAX_RTCACHEFRIENDS, IAX_RTUPDATE, IAX_STATE_AUTHENTICATED, IAX_TEMPONLY, iaxs, inaddrcmp(), LOG_NOTICE, LOG_WARNING, manager_event(), option_verbose, iax_ie_data::pos, realtime_update_peer(), register_peer_exten(), send_command_final(), iax2_peer::sockfd, and VERBOSE_PREFIX_3.
Referenced by socket_process().
05658 { 05659 /* Called from IAX thread only, with proper iaxsl lock */ 05660 struct iax_ie_data ied; 05661 struct iax2_peer *p; 05662 int msgcount; 05663 char data[80]; 05664 int version; 05665 05666 memset(&ied, 0, sizeof(ied)); 05667 05668 /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ 05669 if (!(p = find_peer(name, 1))) { 05670 ast_log(LOG_WARNING, "No such peer '%s'\n", name); 05671 return -1; 05672 } 05673 05674 if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { 05675 if (sin->sin_addr.s_addr) { 05676 time_t nowtime; 05677 time(&nowtime); 05678 realtime_update_peer(name, sin, nowtime); 05679 } else { 05680 realtime_update_peer(name, sin, 0); 05681 } 05682 } 05683 if (inaddrcmp(&p->addr, sin)) { 05684 if (iax2_regfunk) 05685 iax2_regfunk(p->name, 1); 05686 /* Stash the IP address from which they registered */ 05687 memcpy(&p->addr, sin, sizeof(p->addr)); 05688 snprintf(data, sizeof(data), "%s:%d:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expiry); 05689 if (!ast_test_flag(p, IAX_TEMPONLY) && sin->sin_addr.s_addr) { 05690 ast_db_put("IAX/Registry", p->name, data); 05691 if (option_verbose > 2) 05692 ast_verbose(VERBOSE_PREFIX_3 "Registered IAX2 '%s' (%s) at %s:%d\n", p->name, 05693 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 05694 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Registered\r\n", p->name); 05695 register_peer_exten(p, 1); 05696 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05697 } else if (!ast_test_flag(p, IAX_TEMPONLY)) { 05698 if (option_verbose > 2) 05699 ast_verbose(VERBOSE_PREFIX_3 "Unregistered IAX2 '%s' (%s)\n", p->name, 05700 ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED"); 05701 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name); 05702 register_peer_exten(p, 0); 05703 ast_db_del("IAX/Registry", p->name); 05704 ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */ 05705 } 05706 /* Update the host */ 05707 /* Verify that the host is really there */ 05708 iax2_poke_peer(p, callno); 05709 } 05710 05711 /* Make sure our call still exists, an INVAL at the right point may make it go away */ 05712 if (!iaxs[callno]) 05713 return 0; 05714 05715 /* Store socket fd */ 05716 p->sockfd = fd; 05717 /* Setup the expiry */ 05718 if (p->expire > -1) 05719 ast_sched_del(sched, p->expire); 05720 /* treat an unspecified refresh interval as the minimum */ 05721 if (!refresh) 05722 refresh = min_reg_expire; 05723 if (refresh > max_reg_expire) { 05724 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 05725 p->name, max_reg_expire, refresh); 05726 p->expiry = max_reg_expire; 05727 } else if (refresh < min_reg_expire) { 05728 ast_log(LOG_NOTICE, "Restricting registration for peer '%s' to %d seconds (requested %d)\n", 05729 p->name, min_reg_expire, refresh); 05730 p->expiry = min_reg_expire; 05731 } else { 05732 p->expiry = refresh; 05733 } 05734 if (p->expiry && sin->sin_addr.s_addr) 05735 p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name); 05736 iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name); 05737 iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag)); 05738 if (sin->sin_addr.s_addr) { 05739 iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expiry); 05740 iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr); 05741 if (!ast_strlen_zero(p->mailbox)) { 05742 int new, old; 05743 ast_app_inboxcount(p->mailbox, &new, &old); 05744 if (new > 255) 05745 new = 255; 05746 if (old > 255) 05747 old = 255; 05748 msgcount = (old << 8) | new; 05749 iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount); 05750 } 05751 if (ast_test_flag(p, IAX_HASCALLERID)) { 05752 iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, p->cid_num); 05753 iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->cid_name); 05754 } 05755 } 05756 version = iax_check_version(devtype); 05757 if (version) 05758 iax_ie_append_short(&ied, IAX_IE_FIRMWAREVER, version); 05759 if (ast_test_flag(p, IAX_TEMPONLY)) 05760 destroy_peer(p); 05761 return send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1); 05762 }
static void vnak_retransmit | ( | int | callno, | |
int | last | |||
) | [static] |
Definition at line 5942 of file chan_iax2.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, iax_frame::callno, f, iaxq, iaxs, iax_frame::oseqno, iax_frame::retries, and send_packet().
Referenced by socket_process().
05943 { 05944 struct iax_frame *f; 05945 05946 AST_LIST_LOCK(&iaxq.queue); 05947 AST_LIST_TRAVERSE(&iaxq.queue, f, list) { 05948 /* Send a copy immediately */ 05949 if ((f->callno == callno) && iaxs[f->callno] && 05950 ((unsigned char ) (f->oseqno - last) < 128) && 05951 (f->retries >= 0)) { 05952 send_packet(f); 05953 } 05954 } 05955 AST_LIST_UNLOCK(&iaxq.queue); 05956 }
char accountcode[AST_MAX_ACCOUNT_CODE] [static] |
Definition at line 218 of file chan_iax2.c.
Referenced by __oh323_new(), ast_cdr_setaccount(), ast_channel_alloc(), begin_dial(), check_user_full(), disa_exec(), features_call(), gtalk_new(), local_call(), sip_new(), tds_log(), wait_for_answer(), and zt_new().
int adsi = 0 [static] |
Definition at line 222 of file chan_iax2.c.
int amaflags = 0 [static] |
Definition at line 221 of file chan_iax2.c.
int authdebug = 1 [static] |
Definition at line 158 of file chan_iax2.c.
int autokill = 0 [static] |
Definition at line 159 of file chan_iax2.c.
struct ast_cli_entry cli_iax2[] [static] |
struct ast_cli_entry cli_iax2_jb_debug_deprecated [static] |
Initial value:
{ { "iax2", "jb", "debug", NULL }, iax2_do_jb_debug, NULL, NULL }
Definition at line 10130 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_debug_deprecated [static] |
Initial value:
{ { "iax2", "no", "debug", NULL }, iax2_no_debug, NULL, NULL }
Definition at line 10135 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_jb_debug_deprecated [static] |
Initial value:
{ { "iax2", "no", "jb", "debug", NULL }, iax2_no_jb_debug, NULL, NULL }
Definition at line 10145 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_no_trunk_debug_deprecated [static] |
Initial value:
{ { "iax2", "no", "trunk", "debug", NULL }, iax2_no_trunk_debug, NULL, NULL }
Definition at line 10140 of file chan_iax2.c.
struct ast_cli_entry cli_iax2_trunk_debug_deprecated [static] |
Initial value:
{ { "iax2", "trunk", "debug", NULL }, iax2_do_trunk_debug, NULL, NULL }
Definition at line 10125 of file chan_iax2.c.
char context[80] = "default" [static] |
Definition at line 143 of file chan_iax2.c.
char debug_jb_usage[] [static] |
Initial value:
"Usage: iax2 set debug jb\n" " Enables jitterbuffer debugging information\n"
Definition at line 10099 of file chan_iax2.c.
char debug_trunk_usage[] [static] |
Initial value:
"Usage: iax2 set debug trunk\n" " Requests current status of IAX trunking\n"
Definition at line 10091 of file chan_iax2.c.
char debug_usage[] [static] |
Initial value:
"Usage: iax2 set debug\n" " Enables dumping of IAX packets for debugging purposes\n"
Definition at line 10083 of file chan_iax2.c.
int defaultsockfd = -1 [static] |
Definition at line 175 of file chan_iax2.c.
int delayreject = 0 [static] |
Definition at line 223 of file chan_iax2.c.
struct iax2_dpcache * dpcache [static] |
Referenced by find_cache(), and iax2_show_cache().
int global_rtautoclear = 120 [static] |
Definition at line 276 of file chan_iax2.c.
struct ast_flags globalflags = { 0 } [static] |
Definition at line 226 of file chan_iax2.c.
Referenced by find_or_create(), find_user(), find_user_realtime(), forward_message(), load_config(), make_email_file(), notify_new_message(), populate_defaults(), sendmail(), and vm_execmain().
int iax2_capability = IAX_CAPABILITY_FULLBANDWIDTH [static] |
Definition at line 204 of file chan_iax2.c.
int iax2_encryption = 0 [static] |
Definition at line 224 of file chan_iax2.c.
enum { ... } iax2_flags |
int(* iax2_regfunk)(const char *username, int onoff) = NULL |
Definition at line 177 of file chan_iax2.c.
Referenced by __expire_registry(), reg_source_db(), and update_registry().
char iax2_reload_usage[] [static] |
Initial value:
"Usage: iax2 reload\n" " Reloads IAX configuration from iax.conf\n"
Definition at line 10041 of file chan_iax2.c.
enum { ... } iax2_state |
struct ast_switch iax2_switch [static] |
struct ast_channel_tech iax2_tech [static] |
Definition at line 834 of file chan_iax2.c.
Referenced by __unload_module(), ast_iax2_new(), function_iaxpeer(), iax2_bridge(), iax2_prov_app(), and load_module().
char iax2_test_losspct_usage[] [static] |
Initial value:
"Usage: iax2 test losspct <percentage>\n" " For testing, throws away <percentage> percent of incoming packets\n"
Definition at line 10107 of file chan_iax2.c.
int iaxactivethreadcount = 0 [static] |
Definition at line 454 of file chan_iax2.c.
Referenced by __unload_module(), iax2_process_thread(), and iax2_process_thread_cleanup().
int iaxcompat = 0 [static] |
Definition at line 160 of file chan_iax2.c.
int iaxdebug = 0 [static] |
Definition at line 206 of file chan_iax2.c.
int iaxdefaultdpcache = 10 * 60 [static] |
Definition at line 162 of file chan_iax2.c.
int iaxdefaulttimeout = 5 [static] |
Definition at line 164 of file chan_iax2.c.
int iaxdynamicthreadcount = 0 [static] |
Definition at line 453 of file chan_iax2.c.
Referenced by find_idle_thread(), and iax2_process_thread().
int iaxmaxthreadcount = DEFAULT_MAX_THREAD_COUNT [static] |
struct ast_iax2_queue iaxq [static] |
struct chan_iax2_pvt* iaxs[IAX_MAX_CALLS] [static] |
Definition at line 797 of file chan_iax2.c.
Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __do_deliver(), __get_from_jb(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_fail(), auth_reject(), auto_hangup(), cache_get_callno_locked(), calc_timestamp(), check_access(), complete_transfer(), decrypt_frame(), delete_users(), dp_lookup(), find_cache(), find_callno(), fix_peerts(), function_iaxpeer(), iax2_ack_registry(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_dprequest(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_predestroy(), iax2_prov_app(), iax2_provision(), iax2_queue_frame(), iax2_request(), iax2_show_channels(), iax2_start_transfer(), iax2_vnak(), iax2_write(), iax_showframe(), load_module(), make_trunk(), network_thread(), register_verify(), registry_authrequest(), registry_rerequest(), save_rr(), schedule_delivery(), send_command_locked(), send_packet(), socket_process(), stop_stuff(), unwrap_timestamp(), update_max_nontrunk(), update_max_trunk(), update_packet(), update_registry(), and vnak_retransmit().
ast_mutex_t iaxsl[IAX_MAX_CALLS] [static] |
Definition at line 798 of file chan_iax2.c.
Referenced by __attempt_transmit(), __auth_reject(), __auto_congest(), __auto_hangup(), __get_from_jb(), __iax2_poke_noanswer(), __send_lagrq(), __send_ping(), __unload_module(), ast_cli_netstats(), ast_iax2_new(), auth_fail(), auth_reject(), auto_hangup(), cache_get_callno_locked(), delete_users(), destroy_peer(), dp_lookup(), find_cache(), find_callno(), iax2_bridge(), iax2_call(), iax2_destroy(), iax2_do_register(), iax2_fixup(), iax2_hangup(), iax2_indicate(), iax2_poke_peer(), iax2_provision(), iax2_queue_frame(), iax2_request(), iax2_show_channels(), iax2_write(), load_module(), lock_both(), make_trunk(), network_thread(), send_command_locked(), socket_process(), and unlock_both().
int iaxthreadcount = DEFAULT_THREAD_COUNT [static] |
Definition at line 451 of file chan_iax2.c.
Referenced by iax2_show_threads(), set_config(), and start_network_thread().
int iaxtrunkdebug = 0 [static] |
Definition at line 208 of file chan_iax2.c.
struct io_context* io [static] |
Definition at line 201 of file chan_iax2.c.
int lagrq_time = 10 [static] |
Definition at line 151 of file chan_iax2.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 145 of file chan_iax2.c.
struct timeval lastused[IAX_MAX_CALLS] [static] |
Definition at line 799 of file chan_iax2.c.
Referenced by find_callno(), iax2_destroy(), and make_trunk().
int max_reg_expire [static] |
Definition at line 169 of file chan_iax2.c.
int max_retries = 4 [static] |
Definition at line 149 of file chan_iax2.c.
int maxauthreq = 3 [static] |
Definition at line 148 of file chan_iax2.c.
int maxjitterbuffer = 1000 [static] |
Definition at line 154 of file chan_iax2.c.
int maxjitterinterps = 10 [static] |
Definition at line 156 of file chan_iax2.c.
int maxnontrunkcall = 1 [static] |
Definition at line 153 of file chan_iax2.c.
int maxtrunkcall = TRUNK_CALL_START [static] |
Definition at line 152 of file chan_iax2.c.
int min_reg_expire [static] |
Definition at line 168 of file chan_iax2.c.
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 219 of file chan_iax2.c.
char mohsuggest[MAX_MUSICCLASS] [static] |
Definition at line 220 of file chan_iax2.c.
Referenced by check_user_full(), create_addr_from_peer(), and sip_alloc().
struct ast_netsock_list* netsock [static] |
Definition at line 173 of file chan_iax2.c.
pthread_t netthreadid = AST_PTHREADT_NULL [static] |
Definition at line 228 of file chan_iax2.c.
char no_debug_jb_usage[] [static] |
Initial value:
"Usage: iax2 set debug jb off\n" " Disables jitterbuffer debugging information\n"
Definition at line 10103 of file chan_iax2.c.
char no_debug_trunk_usage[] [static] |
Initial value:
"Usage: iax2 set debug trunk off\n" " Requests current status of IAX trunking\n"
Definition at line 10095 of file chan_iax2.c.
char no_debug_usage[] [static] |
Initial value:
"Usage: iax2 set debug off\n" " Disables dumping of IAX packets for debugging purposes\n"
Definition at line 10087 of file chan_iax2.c.
struct ast_netsock_list* outsock [static] |
used if sourceaddress specified and bindaddr == INADDR_ANY
Definition at line 174 of file chan_iax2.c.
char* papp = "IAX2Provision" [static] |
char* pdescrip [static] |
Initial value:
" IAX2Provision([template]): Provisions the calling IAXy (assuming\n" "the calling entity is in fact an IAXy) with the given template or\n" "default if one is not specified. Returns -1 on error or 0 on success.\n"
Definition at line 8086 of file chan_iax2.c.
Referenced by load_module().
int ping_time = 21 [static] |
Definition at line 150 of file chan_iax2.c.
struct ast_codec_pref prefs [static] |
char prune_realtime_usage[] [static] |
Initial value:
"Usage: iax2 prune realtime [<peername>|all]\n" " Prunes object(s) from the cache\n"
Definition at line 10037 of file chan_iax2.c.
char* psyn = "Provision a calling IAXy with a given template" [static] |
char regcontext[AST_MAX_CONTEXT] = "" [static] |
Definition at line 146 of file chan_iax2.c.
int resyncthreshold = 1000 [static] |
Definition at line 155 of file chan_iax2.c.
struct sched_context* sched [static] |
Definition at line 202 of file chan_iax2.c.
ast_cond_t sched_cond [static] |
Definition at line 231 of file chan_iax2.c.
pthread_t schedthreadid = AST_PTHREADT_NULL [static] |
Definition at line 229 of file chan_iax2.c.
char show_cache_usage[] [static] |
Initial value:
"Usage: iax2 show cache\n" " Display currently cached IAX Dialplan results.\n"
Definition at line 10029 of file chan_iax2.c.
char show_channels_usage[] [static] |
Initial value:
"Usage: iax2 show channels\n" " Lists all currently active IAX channels.\n"
Definition at line 10057 of file chan_iax2.c.
char show_firmware_usage[] [static] |
Initial value:
"Usage: iax2 show firmware\n" " Lists all known IAX firmware images.\n"
Definition at line 10075 of file chan_iax2.c.
char show_netstats_usage[] [static] |
Initial value:
"Usage: iax2 show netstats\n" " Lists network status for all currently active IAX channels.\n"
Definition at line 10061 of file chan_iax2.c.
char show_peer_usage[] [static] |
Initial value:
"Usage: iax2 show peer <name>\n" " Display details on specific IAX peer\n"
Definition at line 10033 of file chan_iax2.c.
char show_peers_usage[] [static] |
Initial value:
"Usage: iax2 show peers [registered] [like <pattern>]\n" " Lists all known IAX2 peers.\n" " Optional 'registered' argument lists only peers with known addresses.\n" " Optional regular expression pattern is used to filter the peer list.\n"
Definition at line 10069 of file chan_iax2.c.
char show_prov_usage[] [static] |
Definition at line 10045 of file chan_iax2.c.
char show_reg_usage[] [static] |
Initial value:
"Usage: iax2 show registry\n" " Lists all registration requests and status.\n"
Definition at line 10079 of file chan_iax2.c.
char show_stats_usage[] [static] |
Initial value:
"Usage: iax2 show stats\n" " Display statistics on IAX channel driver.\n"
Definition at line 10025 of file chan_iax2.c.
char show_threads_usage[] [static] |
Initial value:
"Usage: iax2 show threads\n" " Lists status of IAX helper threads\n"
Definition at line 10065 of file chan_iax2.c.
char show_users_usage[] [static] |
Initial value:
"Usage: iax2 show users [like <pattern>]\n" " Lists all known IAX2 users.\n" " Optional regular expression pattern is used to filter the user list.\n"
Definition at line 10052 of file chan_iax2.c.
const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)" [static] |
Definition at line 141 of file chan_iax2.c.
int test_losspct = 0 [static] |
Definition at line 210 of file chan_iax2.c.
int timingfd = -1 [static] |
Definition at line 171 of file chan_iax2.c.
unsigned int tos = 0 [static] |
Definition at line 166 of file chan_iax2.c.
struct iax2_trunk_peer * tpeers [static] |
Referenced by find_tpeer(), and timing_read().
int trunkfreq = 20 [static] |
Definition at line 157 of file chan_iax2.c.
struct ast_firmware_list waresl [static] |
Referenced by __unload_module(), iax2_show_firmware(), iax_check_version(), iax_firmware_append(), load_module(), reload_firmware(), and try_firmware().