Thu Jul 9 13:41:10 2009

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <signal.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/netsock.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/cdr.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/dsp.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/threadstorage.h"
#include "asterisk/devicestate.h"
#include "asterisk/event.h"
#include <byteswap.h>

Go to the source code of this file.

Data Structures

struct  activate_call_plane_message
struct  alarm_message
struct  button_definition
struct  button_definition_template
struct  button_template_res_message
struct  call_info_message
struct  call_state_message
struct  capabilities_res_message
struct  clear_prompt_message
struct  close_receive_channel_message
struct  definetimedate_message
struct  dialed_number_message
struct  display_notify_message
struct  display_prompt_status_message
struct  displaytext_message
struct  enbloc_call_message
struct  forward_stat_message
struct  keypad_button_message
struct  line_stat_res_message
struct  line_state_req_message
struct  media_qualifier
struct  offhook_message
struct  onhook_message
struct  open_receive_channel_ack_message
struct  open_receive_channel_message
struct  register_ack_message
struct  register_message
struct  register_rej_message
struct  reset_message
struct  select_soft_keys_message
struct  server_identifier
struct  server_res_message
struct  set_lamp_message
struct  set_microphone_message
struct  set_ringer_message
struct  set_speaker_message
struct  skinny_addon
union  skinny_data
struct  skinny_device
struct  skinny_line
struct  skinny_paging_device
struct  skinny_req
struct  skinny_speeddial
struct  skinny_subchannel
struct  skinnysession
struct  soft_key_definitions
struct  soft_key_event_message
struct  soft_key_set_definition
struct  soft_key_set_res_message
struct  soft_key_template_definition
struct  soft_key_template_res_message
struct  speed_dial_stat_req_message
struct  speed_dial_stat_res_message
struct  start_media_transmission_message
struct  start_tone_message
struct  station_capabilities
struct  stimulus_message
struct  stop_media_transmission_message
struct  stop_tone_message
struct  version_res_message

Defines

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116
#define ALARM_MESSAGE   0x0020
#define BT_AUTOANSWER   STIMULUS_AUTOANSWER
#define BT_CALLPARK   STIMULUS_CALLPARK
#define BT_CALLPICKUP   STIMULUS_CALLPICKUP
#define BT_CONFERENCE   STIMULUS_CONFERENCE
#define BT_CUST_LINE   0xB1
#define BT_CUST_LINESPEEDDIAL   0xB0
#define BT_DISPLAY   STIMULUS_DISPLAY
#define BT_DND   STIMULUS_DND
#define BT_FORWARDALL   STIMULUS_FORWARDALL
#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY
#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER
#define BT_HOLD   STIMULUS_HOLD
#define BT_LINE   STIMULUS_LINE
#define BT_NONE   0x00
#define BT_REDIAL   STIMULUS_REDIAL
#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL
#define BT_TRANSFER   STIMULUS_TRANSFER
#define BT_VOICEMAIL   STIMULUS_VOICEMAIL
#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E
#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097
#define CALL_INFO_MESSAGE   0x008F
#define CALL_STATE_MESSAGE   0x0111
#define CAPABILITIES_REQ_MESSAGE   0x009B
#define CAPABILITIES_RES_MESSAGE   0x0010
#define CLEAR_DISPLAY_MESSAGE   0x009A
#define CLEAR_NOTIFY_MESSAGE   0x0115
#define CLEAR_PROMPT_MESSAGE   0x0113
#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106
#define CONTROL2STR_BUFSIZE   100
#define DEFAULT_SKINNY_BACKLOG   2
#define DEFAULT_SKINNY_PORT   2000
#define DEFINETIMEDATE_MESSAGE   0x0094
#define DEVICE2STR_BUFSIZE   15
#define DIALED_NUMBER_MESSAGE   0x011D
#define DISPLAY_NOTIFY_MESSAGE   0x0114
#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112
#define DISPLAYTEXT_MESSAGE   0x0099
#define ENBLOC_CALL_MESSAGE   0x0004
#define FORWARD_STAT_MESSAGE   0x0090
#define HEADSET_STATUS_MESSAGE   0x002B
#define htolel(x)   bswap_32(x)
#define htoles(x)   bswap_16(x)
#define IP_PORT_MESSAGE   0x0002
#define KEEP_ALIVE_ACK_MESSAGE   0x0100
#define KEEP_ALIVE_MESSAGE   0x0000
#define KEYDEF_CONNECTED   1
#define KEYDEF_CONNWITHCONF   7
#define KEYDEF_CONNWITHTRANS   5
#define KEYDEF_DADFD   6
#define KEYDEF_OFFHOOK   4
#define KEYDEF_OFFHOOKWITHFEAT   9
#define KEYDEF_ONHOLD   2
#define KEYDEF_ONHOOK   0
#define KEYDEF_RINGIN   3
#define KEYDEF_RINGOUT   8
#define KEYDEF_UNKNOWN   10
#define KEYPAD_BUTTON_MESSAGE   0x0003
#define letohl(x)   bswap_32(x)
#define letohs(x)   bswap_16(x)
#define LINE_STAT_RES_MESSAGE   0x0092
#define LINE_STATE_REQ_MESSAGE   0x000B
#define OFFHOOK_MESSAGE   0x0006
#define ONHOOK_MESSAGE   0x0007
#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022
#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105
#define REGISTER_ACK_MESSAGE   0x0081
#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D
#define REGISTER_MESSAGE   0x0001
#define REGISTER_REJ_MESSAGE   0x009D
#define RESET_MESSAGE   0x009F
#define SELECT_SOFT_KEYS_MESSAGE   0x0110
#define SERVER_REQUEST_MESSAGE   0x0012
#define SERVER_RES_MESSAGE   0x009E
#define SET_LAMP_MESSAGE   0x0086
#define SET_MICROPHONE_MESSAGE   0x0089
#define SET_RINGER_MESSAGE   0x0085
#define SET_SPEAKER_MESSAGE   0x0088
#define SKINNY_ALERT   0x24
#define SKINNY_BUSY   6
#define SKINNY_BUSYTONE   0x23
#define SKINNY_CALLREMOTEMULTILINE   13
#define SKINNY_CALLWAIT   9
#define SKINNY_CALLWAITTONE   0x2D
#define SKINNY_CFWD_ALL   (1 << 0)
#define SKINNY_CFWD_BUSY   (1 << 1)
#define SKINNY_CFWD_NOANSWER   (1 << 2)
#define SKINNY_CONGESTION   7
#define SKINNY_CONNECTED   5
#define SKINNY_CX_CONF   3
#define SKINNY_CX_CONFERENCE   3
#define SKINNY_CX_INACTIVE   4
#define SKINNY_CX_MUTE   4
#define SKINNY_CX_RECVONLY   1
#define SKINNY_CX_SENDONLY   0
#define SKINNY_CX_SENDRECV   2
#define SKINNY_DEVICE_12   4
#define SKINNY_DEVICE_12SP   3
#define SKINNY_DEVICE_12SPPLUS   2
#define SKINNY_DEVICE_30SPPLUS   1
#define SKINNY_DEVICE_30VIP   5
#define SKINNY_DEVICE_7902   30008
#define SKINNY_DEVICE_7905   20000
#define SKINNY_DEVICE_7906   369
#define SKINNY_DEVICE_7910   6
#define SKINNY_DEVICE_7911   307
#define SKINNY_DEVICE_7912   30007
#define SKINNY_DEVICE_7914   124
#define SKINNY_DEVICE_7920   30002
#define SKINNY_DEVICE_7921   365
#define SKINNY_DEVICE_7931   348
#define SKINNY_DEVICE_7935   9
#define SKINNY_DEVICE_7936   30019
#define SKINNY_DEVICE_7937   431
#define SKINNY_DEVICE_7940   8
#define SKINNY_DEVICE_7941   115
#define SKINNY_DEVICE_7941GE   309
#define SKINNY_DEVICE_7942   434
#define SKINNY_DEVICE_7945   435
#define SKINNY_DEVICE_7960   7
#define SKINNY_DEVICE_7961   30018
#define SKINNY_DEVICE_7961GE   308
#define SKINNY_DEVICE_7962   404
#define SKINNY_DEVICE_7965   436
#define SKINNY_DEVICE_7970   30006
#define SKINNY_DEVICE_7971   119
#define SKINNY_DEVICE_7975   437
#define SKINNY_DEVICE_7985   302
#define SKINNY_DEVICE_ATA186   12
#define SKINNY_DEVICE_CIPC   30016
#define SKINNY_DEVICE_NONE   0
#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027
#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028
#define SKINNY_DEVICE_UNKNOWN   -1
#define SKINNY_DIALTONE   0x21
#define SKINNY_HOLD   8
#define SKINNY_INVALID   14
#define SKINNY_LAMP_BLINK   5
#define SKINNY_LAMP_FLASH   4
#define SKINNY_LAMP_OFF   1
#define SKINNY_LAMP_ON   2
#define SKINNY_LAMP_WINK   3
#define SKINNY_MAX_CAPABILITIES   18
#define SKINNY_MAX_PACKET   1000
#define SKINNY_MICOFF   2
#define SKINNY_MICON   1
#define SKINNY_NOTONE   0x7F
#define SKINNY_OFFHOOK   1
#define SKINNY_ONHOOK   2
#define SKINNY_PARK   11
#define SKINNY_PROGRESS   12
#define SKINNY_REORDER   0x25
#define SKINNY_RING_FEATURE   4
#define SKINNY_RING_INSIDE   2
#define SKINNY_RING_OFF   1
#define SKINNY_RING_OUTSIDE   3
#define SKINNY_RINGIN   4
#define SKINNY_RINGOUT   3
#define SKINNY_SILENCE   0x00
#define SKINNY_SPEAKEROFF   2
#define SKINNY_SPEAKERON   1
#define SKINNY_TRANSFER   10
#define SOFT_KEY_EVENT_MESSAGE   0x0026
#define SOFT_KEY_SET_REQ_MESSAGE   0x0025
#define SOFT_KEY_SET_RES_MESSAGE   0x0109
#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028
#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108
#define SOFTKEY_ANSWER   0x0B
#define SOFTKEY_BKSPC   0x08
#define SOFTKEY_CFWDALL   0x05
#define SOFTKEY_CFWDBUSY   0x06
#define SOFTKEY_CFWDNOANSWER   0x07
#define SOFTKEY_CONFRN   0x0D
#define SOFTKEY_DND   0x13
#define SOFTKEY_ENDCALL   0x09
#define SOFTKEY_GPICKUP   0x12
#define SOFTKEY_HOLD   0x03
#define SOFTKEY_IDIVERT   0x14
#define SOFTKEY_INFO   0x0C
#define SOFTKEY_JOIN   0x0F
#define SOFTKEY_MEETME   0x10
#define SOFTKEY_NEWCALL   0x02
#define SOFTKEY_NONE   0x00
#define SOFTKEY_PARK   0x0E
#define SOFTKEY_PICKUP   0x11
#define SOFTKEY_REDIAL   0x01
#define SOFTKEY_RESUME   0x0A
#define SOFTKEY_TRNSFER   0x04
#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A
#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091
#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A
#define START_TONE_MESSAGE   0x0082
#define STIMULUS_AUTOANSWER   0x11
#define STIMULUS_CALLPARK   0x7E
#define STIMULUS_CALLPICKUP   0x7F
#define STIMULUS_CONFERENCE   0x7D
#define STIMULUS_DISPLAY   0x08
#define STIMULUS_DND   0x3F
#define STIMULUS_FORWARDALL   0x05
#define STIMULUS_FORWARDBUSY   0x06
#define STIMULUS_FORWARDNOANSWER   0x07
#define STIMULUS_HOLD   0x03
#define STIMULUS_LINE   0x09
#define STIMULUS_MESSAGE   0x0005
#define STIMULUS_NONE   0xFF
#define STIMULUS_REDIAL   0x01
#define STIMULUS_SPEEDDIAL   0x02
#define STIMULUS_TRANSFER   0x04
#define STIMULUS_VOICEMAIL   0x0F
#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B
#define STOP_TONE_MESSAGE   0x0083
#define TIME_DATE_REQ_MESSAGE   0x000D
#define TYPE_LINE   2
#define TYPE_TRUNK   1
#define UNREGISTER_MESSAGE   0x0027
#define VERSION_REQ_MESSAGE   0x000F
#define VERSION_RES_MESSAGE   0x0098

Enumerations

enum  skinny_codecs {
  SKINNY_CODEC_ALAW = 2, SKINNY_CODEC_ULAW = 4, SKINNY_CODEC_G723_1 = 9, SKINNY_CODEC_G729A = 12,
  SKINNY_CODEC_G726_32 = 82, SKINNY_CODEC_H261 = 100, SKINNY_CODEC_H263 = 101
}

Functions

static void __init_control2str_threadbuf (void)
static void __init_device2str_threadbuf (void)
static void __reg_module (void)
static void __unreg_module (void)
static void * accept_thread (void *ignore)
static struct ast_variableadd_var (const char *buf, struct ast_variable *list)
static struct skinny_devicebuild_device (const char *cat, struct ast_variable *v)
static void cleanup_stale_contexts (char *new, char *old)
static int codec_ast2skinny (int astcodec)
static int codec_skinny2ast (enum skinny_codecs skinnycodec)
static char * complete_skinny_devices (const char *word, int state)
static char * complete_skinny_reset (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_device (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_line (const char *line, const char *word, int pos, int state)
static char * control2str (int ind)
static void delete_devices (void)
static void destroy_session (struct skinnysession *s)
static char * device2str (int type)
static void do_housekeeping (struct skinnysession *s)
static void * do_monitor (void *data)
static struct skinny_linefind_line_by_instance (struct skinny_device *d, int instance)
static struct skinny_linefind_line_by_name (const char *dest)
static struct skinny_speeddialfind_speeddial_by_instance (struct skinny_device *d, int instance, int isHint)
static struct skinny_subchannelfind_subchannel_by_instance_reference (struct skinny_device *d, int instance, int reference)
static struct skinny_subchannelfind_subchannel_by_reference (struct skinny_device *d, int reference)
static void * get_button_template (struct skinnysession *s, struct button_definition_template *btn)
static int get_devicestate (struct skinny_line *l)
static int get_input (struct skinnysession *s)
static int handle_alarm_message (struct skinny_req *req, struct skinnysession *s)
static int handle_button_template_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_callforward_button (struct skinny_subchannel *sub, int cfwdtype)
static int handle_capabilities_res_message (struct skinny_req *req, struct skinnysession *s)
static int handle_enbloc_call_message (struct skinny_req *req, struct skinnysession *s)
static int handle_headset_status_message (struct skinny_req *req, struct skinnysession *s)
static int handle_ip_port_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keep_alive_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keypad_button_message (struct skinny_req *req, struct skinnysession *s)
static int handle_line_state_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_message (struct skinny_req *req, struct skinnysession *s)
static int handle_offhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_onhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_open_receive_channel_ack_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_available_lines_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_message (struct skinny_req *req, struct skinnysession *s)
static int handle_server_request_message (struct skinny_req *req, struct skinnysession *s)
static char * handle_skinny_reset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_set_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_show_device (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show device information.
static char * handle_skinny_show_devices (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_show_line (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 List line information.
static char * handle_skinny_show_lines (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 List global settings for the Skinny subsystem.
static int handle_soft_key_event_message (struct skinny_req *req, struct skinnysession *s)
static int handle_soft_key_set_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_soft_key_template_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_speed_dial_stat_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_stimulus_message (struct skinny_req *req, struct skinnysession *s)
static int handle_time_date_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_unregister_message (struct skinny_req *req, struct skinnysession *s)
static int handle_version_req_message (struct skinny_req *req, struct skinnysession *s)
static int has_voicemail (struct skinny_line *l)
static int load_module (void)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static void print_codec_to_cli (int fd, struct ast_codec_pref *pref)
 Print codec list from preference to CLI/manager.
static void register_exten (struct skinny_line *l)
static int reload_config (void)
static struct skinny_reqreq_alloc (size_t size, int response_message)
static int restart_monitor (void)
static int set_callforwards (struct skinny_line *l, const char *cfwd, int cfwdtype)
static int skinny_answer (struct ast_channel *ast)
static int skinny_call (struct ast_channel *ast, char *dest, int timeout)
static int skinny_devicestate (void *data)
static int skinny_extensionstate_cb (char *context, char *exten, int state, void *data)
static int skinny_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_get_result skinny_get_rtp_peer (struct ast_channel *c, struct ast_rtp **rtp)
static enum ast_rtp_get_result skinny_get_vrtp_peer (struct ast_channel *c, struct ast_rtp **rtp)
static int skinny_hangup (struct ast_channel *ast)
static int skinny_hold (struct skinny_subchannel *sub)
static int skinny_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct ast_channelskinny_new (struct skinny_line *l, int state)
static void * skinny_newcall (void *data)
static struct ast_frameskinny_read (struct ast_channel *ast)
static int skinny_register (struct skinny_req *req, struct skinnysession *s)
static struct skinny_reqskinny_req_parse (struct skinnysession *s)
static struct ast_channelskinny_request (const char *type, int format, void *data, int *cause)
static struct ast_frameskinny_rtp_read (struct skinny_subchannel *sub)
static int skinny_senddigit_begin (struct ast_channel *ast, char digit)
static int skinny_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void * skinny_session (void *data)
static int skinny_set_rtp_peer (struct ast_channel *c, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
static void * skinny_ss (void *data)
static int skinny_unhold (struct skinny_subchannel *sub)
static int skinny_unregister (struct skinny_req *req, struct skinnysession *s)
static int skinny_write (struct ast_channel *ast, struct ast_frame *frame)
static void start_rtp (struct skinny_subchannel *sub)
static void transmit_callinfo (struct skinnysession *s, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
static void transmit_callstate (struct skinnysession *s, int instance, int state, unsigned callid)
static void transmit_cfwdstate (struct skinnysession *s, struct skinny_line *l)
static void transmit_connect (struct skinnysession *s, struct skinny_subchannel *sub)
static void transmit_dialednumber (struct skinnysession *s, const char *text, int instance, int callid)
static void transmit_displaymessage (struct skinnysession *s, const char *text, int instance, int reference)
static void transmit_displaynotify (struct skinnysession *s, const char *text, int t)
static void transmit_displaypromptstatus (struct skinnysession *s, const char *text, int t, int instance, int callid)
static void transmit_lamp_indication (struct skinnysession *s, int stimulus, int instance, int indication)
static int transmit_response (struct skinnysession *s, struct skinny_req *req)
static void transmit_ringer_mode (struct skinnysession *s, int mode)
static void transmit_selectsoftkeys (struct skinnysession *s, int instance, int callid, int softkey)
static void transmit_speaker_mode (struct skinnysession *s, int mode)
static void transmit_tone (struct skinnysession *s, int tone, int instance, int reference)
static int unload_module (void)
static void unregister_exten (struct skinny_line *l)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Skinny Client Control Protocol (Skinny)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, }
static struct in_addr __ourip
static pthread_t accept_t
static char accountcode [AST_MAX_ACCOUNT_CODE] = ""
ast_hostent ahp
static int amaflags = 0
static const struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static int callnums = 1
static int callreturn = 0
static int callwaiting = 0
static int cancallforward = 0
static int canreinvite = 0
static char cid_name [AST_MAX_EXTENSION] = ""
static char cid_num [AST_MAX_EXTENSION] = ""
static struct ast_cli_entry cli_skinny []
static struct ast_cli_entry cli_skinny_set_debug_deprecated = { .handler = handle_skinny_set_debug_deprecated , .summary = "Enable/Disable Skinny debugging" ,__VA_ARGS__ }
static const char config [] = "skinny.conf"
static char context [AST_MAX_CONTEXT] = "default"
static struct ast_threadstorage control2str_threadbuf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_control2str_threadbuf , .custom_init = NULL , }
static unsigned int cos = 0
static unsigned int cos_audio = 0
static unsigned int cos_video = 0
static ast_group_t cur_callergroup = 0
static ast_group_t cur_pickupgroup = 0
static char date_format [6] = "D-M-Y"
static int default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW
static struct ast_jb_conf default_jbconf
static struct ast_codec_pref default_prefs
static struct ast_threadstorage device2str_threadbuf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_device2str_threadbuf , .custom_init = NULL , }
static ast_mutex_t devicelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct skinny_devicedevices
static int firstdigittimeout = 16000
static int gendigittimeout = 8000
static struct ast_jb_conf global_jbconf
hostent * hp
static int immediate = 0
static struct io_contextio
static int keep_alive = 120
static char language [MAX_LANGUAGE] = ""
static char linelabel [AST_MAX_EXTENSION] = ""
static char mailbox [AST_MAX_EXTENSION]
static int matchdigittimeout = 3000
static char mohinterpret [MAX_MUSICCLASS] = "default"
static char mohsuggest [MAX_MUSICCLASS] = ""
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int mwiblink = 0
static int nat = 0
static ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char ourhost [256]
static int ourport
static char regcontext [AST_MAX_CONTEXT]
static char regexten [AST_MAX_EXTENSION]
static struct sched_contextsched = NULL
static ast_mutex_t sessionlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct skinnysessionsessions
int skinny_header_size = 12
static struct ast_rtp_protocol skinny_rtp
static struct ast_channel_tech skinny_tech
static int skinnydebug = 0
static int skinnysock = -1
static const uint8_t soft_key_default_connected []
static const uint8_t soft_key_default_connwithconf []
static const uint8_t soft_key_default_connwithtrans []
static const uint8_t soft_key_default_dadfd []
static struct soft_key_definitions soft_key_default_definitions []
static const uint8_t soft_key_default_offhook []
static const uint8_t soft_key_default_offhookwithfeat []
static const uint8_t soft_key_default_onhold []
static const uint8_t soft_key_default_onhook []
static const uint8_t soft_key_default_ringin []
static const uint8_t soft_key_default_ringout []
static const uint8_t soft_key_default_unknown []
soft_key_template_definition soft_key_template_default []
static const char tdesc [] = "Skinny Client Control Protocol (Skinny)"
static int threewaycalling = 0
static unsigned int tos = 0
static unsigned int tos_audio = 0
static unsigned int tos_video = 0
static int transfer = 0
static char used_context [AST_MAX_EXTENSION]
static char version_id [16] = "P002F202"
static char vmexten [AST_MAX_EXTENSION]


Detailed Description

Implementation of the Skinny protocol.

Author:
Jeremy McNamara & Florian Overkamp & North Antara

Definition in file chan_skinny.c.


Define Documentation

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116

Definition at line 878 of file chan_skinny.c.

Referenced by skinny_hold(), skinny_unhold(), and transmit_callstate().

#define ALARM_MESSAGE   0x0020

Definition at line 247 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 454 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 457 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 458 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 456 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 465 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 464 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 451 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 455 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 448 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 449 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 450 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 446 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 452 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 459 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 444 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 445 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 447 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 453 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 243 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 414 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 352 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 850 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 487 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 215 of file chan_skinny.c.

Referenced by handle_message().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 485 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 484 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 866 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 523 of file chan_skinny.c.

Referenced by skinny_hold(), and transmit_callstate().

#define CONTROL2STR_BUFSIZE   100

Definition at line 162 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 91 of file chan_skinny.c.

Referenced by reload_config().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 90 of file chan_skinny.c.

Referenced by build_device(), and reload_config().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 401 of file chan_skinny.c.

Referenced by handle_time_date_req_message().

#define DEVICE2STR_BUFSIZE   15

Definition at line 159 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 883 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 872 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 858 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 479 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 191 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 374 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 274 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     bswap_32(x)

Definition at line 118 of file chan_skinny.c.

Referenced by get_input(), handle_button_template_req_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_server_request_message(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_time_date_req_message(), load_module(), req_alloc(), skinny_hold(), skinny_set_rtp_peer(), skinny_unhold(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_connect(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

#define htoles (  )     bswap_16(x)

Definition at line 119 of file chan_skinny.c.

#define IP_PORT_MESSAGE   0x0002

Definition at line 181 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 510 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 168 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

Definition at line 538 of file chan_skinny.c.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_answer().

#define KEYDEF_CONNWITHCONF   7

Definition at line 544 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 542 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 543 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

Definition at line 541 of file chan_skinny.c.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), and handle_stimulus_message().

#define KEYDEF_OFFHOOKWITHFEAT   9

Definition at line 546 of file chan_skinny.c.

#define KEYDEF_ONHOLD   2

Definition at line 539 of file chan_skinny.c.

#define KEYDEF_ONHOOK   0

Definition at line 537 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), and transmit_callstate().

#define KEYDEF_RINGIN   3

Definition at line 540 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

Definition at line 545 of file chan_skinny.c.

Referenced by handle_callforward_button(), handle_soft_key_event_message(), and handle_stimulus_message().

#define KEYDEF_UNKNOWN   10

Definition at line 547 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 183 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     bswap_32(x)

Definition at line 116 of file chan_skinny.c.

Referenced by get_input(), handle_capabilities_res_message(), handle_keypad_button_message(), handle_line_state_req_message(), handle_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_soft_key_event_message(), handle_speed_dial_stat_req_message(), handle_stimulus_message(), skinny_register(), skinny_req_parse(), and transmit_response().

#define letohs (  )     bswap_16(x)

Definition at line 117 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 393 of file chan_skinny.c.

Referenced by handle_line_state_req_message().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 237 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 203 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 209 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 255 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 512 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 277 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 275 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 171 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 489 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 505 of file chan_skinny.c.

Referenced by handle_skinny_reset().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 842 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 245 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 494 of file chan_skinny.c.

Referenced by handle_server_request_message().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 308 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 321 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 300 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 315 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1053 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1040 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1052 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1047 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1043 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1055 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CFWD_ALL   (1 << 0)

Definition at line 1069 of file chan_skinny.c.

Referenced by handle_skinny_show_line(), handle_soft_key_event_message(), handle_stimulus_message(), set_callforwards(), skinny_new(), and transmit_cfwdstate().

#define SKINNY_CFWD_BUSY   (1 << 1)

Definition at line 1070 of file chan_skinny.c.

Referenced by handle_skinny_show_line(), handle_soft_key_event_message(), handle_stimulus_message(), set_callforwards(), skinny_new(), and transmit_cfwdstate().

#define SKINNY_CFWD_NOANSWER   (1 << 2)

Definition at line 1071 of file chan_skinny.c.

Referenced by handle_skinny_show_line(), handle_soft_key_event_message(), handle_stimulus_message(), set_callforwards(), and transmit_cfwdstate().

#define SKINNY_CONGESTION   7

Definition at line 1041 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

Definition at line 1039 of file chan_skinny.c.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_answer().

#define SKINNY_CX_CONF   3

Definition at line 1080 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 1081 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1083 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1082 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1078 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1077 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1079 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 995 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 994 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 993 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 992 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 996 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1022 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1018 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1011 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 997 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1006 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1021 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1004 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1019 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1010 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1009 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1000 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1025 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1013 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 999 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1002 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1008 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1014 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1015 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 998 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1024 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1007 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1012 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1016 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1020 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1003 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1017 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1005 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1001 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1023 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 991 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1026 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1027 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 990 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DIALTONE   0x21

Definition at line 1051 of file chan_skinny.c.

Referenced by handle_callforward_button(), handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_ss().

#define SKINNY_HOLD   8

Definition at line 1042 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_INVALID   14

Definition at line 1048 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 1062 of file chan_skinny.c.

Referenced by do_housekeeping(), skinny_call(), and skinny_extensionstate_cb().

#define SKINNY_LAMP_FLASH   4

Definition at line 1061 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1

Definition at line 1058 of file chan_skinny.c.

Referenced by do_housekeeping(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_extensionstate_cb(), and skinny_hangup().

#define SKINNY_LAMP_ON   2

Definition at line 1059 of file chan_skinny.c.

Referenced by do_housekeeping(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_extensionstate_cb(), skinny_ss(), and skinny_unhold().

#define SKINNY_LAMP_WINK   3

Definition at line 1060 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 225 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 92 of file chan_skinny.c.

Referenced by skinny_req_parse(), and transmit_response().

#define SKINNY_MICOFF   2

Definition at line 1033 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 1032 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1056 of file chan_skinny.c.

Referenced by transmit_tone().

#define SKINNY_OFFHOOK   1

Definition at line 1035 of file chan_skinny.c.

Referenced by handle_callforward_button(), handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_call(), skinny_hangup(), and transmit_callstate().

#define SKINNY_ONHOOK   2

Definition at line 1036 of file chan_skinny.c.

Referenced by build_device(), get_devicestate(), handle_callforward_button(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_call(), skinny_extensionstate_cb(), skinny_hangup(), and transmit_callstate().

#define SKINNY_PARK   11

Definition at line 1045 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1046 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER   0x25

Definition at line 1054 of file chan_skinny.c.

Referenced by skinny_indicate(), skinny_newcall(), and skinny_ss().

#define SKINNY_RING_FEATURE   4

Definition at line 1067 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1065 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

Definition at line 1064 of file chan_skinny.c.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_hangup().

#define SKINNY_RING_OUTSIDE   3

Definition at line 1066 of file chan_skinny.c.

#define SKINNY_RINGIN   4

Definition at line 1038 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_extensionstate_cb().

#define SKINNY_RINGOUT   3

Definition at line 1037 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE   0x00

Definition at line 1050 of file chan_skinny.c.

Referenced by handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_answer(), skinny_hangup(), skinny_indicate(), and skinny_ss().

#define SKINNY_SPEAKEROFF   2

Definition at line 1030 of file chan_skinny.c.

Referenced by handle_callforward_button(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_hangup(), and transmit_callstate().

#define SKINNY_SPEAKERON   1

Definition at line 1029 of file chan_skinny.c.

Referenced by handle_callforward_button(), handle_soft_key_event_message(), and handle_stimulus_message().

#define SKINNY_TRANSFER   10

Definition at line 1044 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 265 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 263 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 827 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 273 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 530 of file chan_skinny.c.

Referenced by handle_soft_key_template_req_message().

#define SOFTKEY_ANSWER   0x0B

Definition at line 560 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 557 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 554 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 555 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 556 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 562 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 568 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 558 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 567 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 552 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 569 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 561 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 564 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 565 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 551 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 549 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 563 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 566 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 550 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 559 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 553 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 232 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 386 of file chan_skinny.c.

Referenced by handle_speed_dial_stat_req_message().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 326 of file chan_skinny.c.

Referenced by handle_open_receive_channel_ack_message(), and skinny_set_rtp_peer().

#define START_TONE_MESSAGE   0x0082

Definition at line 286 of file chan_skinny.c.

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 436 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 439 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 440 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 438 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 433 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 437 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 430 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 431 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 432 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 428 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

Definition at line 434 of file chan_skinny.c.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_call(), skinny_extensionstate_cb(), skinny_hangup(), skinny_hold(), and skinny_unhold().

#define STIMULUS_MESSAGE   0x0005

Definition at line 196 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 441 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 426 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 427 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 429 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 435 of file chan_skinny.c.

Referenced by do_housekeeping(), and handle_stimulus_message().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 345 of file chan_skinny.c.

Referenced by skinny_hold(), skinny_set_rtp_peer(), and transmit_callstate().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 294 of file chan_skinny.c.

Referenced by transmit_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 242 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_LINE   2

Definition at line 1074 of file chan_skinny.c.

#define TYPE_TRUNK   1

Definition at line 1073 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 272 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 244 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

Definition at line 474 of file chan_skinny.c.

Referenced by handle_version_req_message().


Enumeration Type Documentation

enum skinny_codecs

Enumerator:
SKINNY_CODEC_ALAW 
SKINNY_CODEC_ULAW 
SKINNY_CODEC_G723_1 
SKINNY_CODEC_G729A 
SKINNY_CODEC_G726_32 
SKINNY_CODEC_H261 
SKINNY_CODEC_H263 

Definition at line 80 of file chan_skinny.c.

00080                    {
00081    SKINNY_CODEC_ALAW = 2,
00082    SKINNY_CODEC_ULAW = 4,
00083    SKINNY_CODEC_G723_1 = 9,
00084    SKINNY_CODEC_G729A = 12,
00085    SKINNY_CODEC_G726_32 = 82, /* XXX Which packing order does this translate to? */
00086    SKINNY_CODEC_H261 = 100,
00087    SKINNY_CODEC_H263 = 101
00088 };


Function Documentation

static void __init_control2str_threadbuf ( void   )  [static]

Definition at line 161 of file chan_skinny.c.

00172 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 158 of file chan_skinny.c.

00172 {

static void __reg_module ( void   )  [static]

Definition at line 6209 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

Definition at line 6209 of file chan_skinny.c.

static void* accept_thread ( void *  ignore  )  [static]

Definition at line 5716 of file chan_skinny.c.

References ast_calloc, ast_debug, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, destroy_session(), errno, LOG_NOTICE, LOG_WARNING, s, sessionlock, skinny_session(), skinnydebug, and skinnysock.

Referenced by reload_config().

05717 {
05718    int as;
05719    struct sockaddr_in sin;
05720    socklen_t sinlen;
05721    struct skinnysession *s;
05722    struct protoent *p;
05723    int arg = 1;
05724    pthread_t tcp_thread;
05725 
05726    for (;;) {
05727       sinlen = sizeof(sin);
05728       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
05729       if (as < 0) {
05730          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
05731          continue;
05732       }
05733       p = getprotobyname("tcp");
05734       if(p) {
05735          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
05736             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
05737          }
05738       }
05739       if (!(s = ast_calloc(1, sizeof(struct skinnysession))))
05740          continue;
05741 
05742       memcpy(&s->sin, &sin, sizeof(sin));
05743       ast_mutex_init(&s->lock);
05744       s->fd = as;
05745       ast_mutex_lock(&sessionlock);
05746       s->next = sessions;
05747       sessions = s;
05748       ast_mutex_unlock(&sessionlock);
05749 
05750       if (ast_pthread_create(&tcp_thread, NULL, skinny_session, s)) {
05751          destroy_session(s);
05752       }
05753    }
05754    if (skinnydebug)
05755       ast_debug(1, "killing accept thread\n");
05756    close(as);
05757    return 0;
05758 }

static struct ast_variable* add_var ( const char *  buf,
struct ast_variable list 
) [static]

implement the setvar config line

Definition at line 1521 of file chan_skinny.c.

References ast_strdupa, ast_variable_new(), and ast_variable::next.

01522 {
01523    struct ast_variable *tmpvar = NULL;
01524    char *varname = ast_strdupa(buf), *varval = NULL;
01525 
01526    if ((varval = strchr(varname,'='))) {
01527       *varval++ = '\0';
01528       if ((tmpvar = ast_variable_new(varname, varval, ""))) {
01529          tmpvar->next = list;
01530          list = tmpvar;
01531       }
01532    }
01533    return list;
01534 }

static struct skinny_device* build_device ( const char *  cat,
struct ast_variable v 
) [static]

Definition at line 2959 of file chan_skinny.c.

References __ourip, accountcode, add_var(), amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free, ast_get_group(), ast_get_ip(), ast_log(), AST_MAX_EXTENSION, ast_mutex_init(), ast_ouraddrfor(), ast_parse_allow_disallow(), ast_strdupa, ast_strlen_zero(), ast_true(), ast_verb, buf, callreturn, callwaiting, cancallforward, canreinvite, cid_name, cid_num, context, cur_callergroup, cur_pickupgroup, default_capability, default_prefs, DEFAULT_SKINNY_PORT, exten, immediate, language, linelabel, ast_variable::lineno, LOG_ERROR, LOG_WARNING, mailbox, mohinterpret, mohsuggest, mwi_event_cb(), mwiblink, ast_variable::name, nat, ast_variable::next, regexten, S_OR, set_callforwards(), SKINNY_ONHOOK, strsep(), threewaycalling, transfer, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and vmexten.

02960 {
02961    struct skinny_device *d;
02962    struct skinny_line *l;
02963    struct skinny_speeddial *sd;
02964    struct skinny_addon *a;
02965    char device_vmexten[AST_MAX_EXTENSION];
02966    struct ast_variable *chanvars = NULL;
02967    int lineInstance = 1;
02968    int speeddialInstance = 1;
02969    int y = 0;
02970 
02971    if (!(d = ast_calloc(1, sizeof(*d)))) {
02972       return NULL;
02973    } else {
02974       ast_copy_string(d->name, cat, sizeof(d->name));
02975       d->lastlineinstance = 1;
02976       d->capability = default_capability;
02977       d->prefs = default_prefs;
02978       if (!ast_strlen_zero(vmexten))
02979          ast_copy_string(device_vmexten, vmexten, sizeof(device_vmexten));
02980       else
02981          memset(device_vmexten, 0, sizeof(device_vmexten));
02982 
02983       d->earlyrtp = 1;
02984       while(v) {
02985          if (!strcasecmp(v->name, "host")) {
02986             if (ast_get_ip(&d->addr, v->value)) {
02987                ast_free(d);
02988                return NULL;
02989             }
02990          } else if (!strcasecmp(v->name, "port")) {
02991             d->addr.sin_port = htons(atoi(v->value));
02992          } else if (!strcasecmp(v->name, "device")) {
02993             ast_copy_string(d->id, v->value, sizeof(d->id));
02994          } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
02995             d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
02996          } else if (!strcasecmp(v->name, "vmexten")) {
02997             ast_copy_string(device_vmexten, v->value, sizeof(device_vmexten));
02998          } else if (!strcasecmp(v->name, "context")) {
02999             ast_copy_string(context, v->value, sizeof(context));
03000          } else if (!strcasecmp(v->name, "regexten")) {
03001             ast_copy_string(regexten, v->value, sizeof(regexten));
03002          } else if (!strcasecmp(v->name, "allow")) {
03003             ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 1);
03004          } else if (!strcasecmp(v->name, "disallow")) {
03005             ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 0);
03006          } else if (!strcasecmp(v->name, "version")) {
03007             ast_copy_string(d->version_id, v->value, sizeof(d->version_id));
03008          } else if (!strcasecmp(v->name, "canreinvite")) {
03009             canreinvite = ast_true(v->value);
03010          } else if (!strcasecmp(v->name, "earlyrtp")) {
03011             d->earlyrtp = ast_true(v->value);
03012          } else if (!strcasecmp(v->name, "nat")) {
03013             nat = ast_true(v->value);
03014          } else if (!strcasecmp(v->name, "callerid")) {
03015             if (!strcasecmp(v->value, "asreceived")) {
03016                cid_num[0] = '\0';
03017                cid_name[0] = '\0';
03018             } else {
03019                ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
03020             }
03021          } else if (!strcasecmp(v->name, "language")) {
03022             ast_copy_string(language, v->value, sizeof(language));
03023          } else if (!strcasecmp(v->name, "accountcode")) {
03024             ast_copy_string(accountcode, v->value, sizeof(accountcode));
03025          } else if (!strcasecmp(v->name, "amaflags")) {
03026             y = ast_cdr_amaflags2int(v->value);
03027             if (y < 0) {
03028                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
03029             } else {
03030                amaflags = y;
03031             }
03032          } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) {
03033             ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
03034          } else if (!strcasecmp(v->name, "mohsuggest")) {
03035             ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest));
03036          } else if (!strcasecmp(v->name, "callgroup")) {
03037             cur_callergroup = ast_get_group(v->value);
03038          } else if (!strcasecmp(v->name, "pickupgroup")) {
03039             cur_pickupgroup = ast_get_group(v->value);
03040          } else if (!strcasecmp(v->name, "immediate")) {
03041             immediate = ast_true(v->value);
03042          } else if (!strcasecmp(v->name, "cancallforward")) {
03043             cancallforward = ast_true(v->value);
03044          } else if (!strcasecmp(v->name, "mailbox")) {
03045             ast_copy_string(mailbox, v->value, sizeof(mailbox));
03046          } else if (!strcasecmp(v->name, "hasvoicemail")) {
03047             if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
03048                ast_copy_string(mailbox, cat, sizeof(mailbox));
03049             }
03050          } else if (!strcasecmp(v->name, "callreturn")) {
03051             callreturn = ast_true(v->value);
03052          } else if (!strcasecmp(v->name, "callwaiting")) {
03053             callwaiting = ast_true(v->value);
03054          } else if (!strcasecmp(v->name, "transfer")) {
03055             transfer = ast_true(v->value);
03056          } else if (!strcasecmp(v->name, "threewaycalling")) {
03057             threewaycalling = ast_true(v->value);
03058          } else if (!strcasecmp(v->name, "mwiblink")) {
03059             mwiblink = ast_true(v->value);
03060          } else if (!strcasecmp(v->name, "linelabel")) {
03061             ast_copy_string(linelabel, v->value, sizeof(linelabel));
03062          } else if (!strcasecmp(v->name, "setvar")) {
03063             chanvars = add_var(v->value, chanvars);
03064          } else if (!strcasecmp(v->name, "speeddial")) {
03065             if (!(sd = ast_calloc(1, sizeof(*sd)))) {
03066                return NULL;
03067             } else {
03068                char buf[256];
03069                char *stringp = buf, *exten, *context, *label;
03070 
03071                ast_copy_string(buf, v->value, sizeof(buf));
03072                exten = strsep(&stringp, ",");
03073                if ((context = strchr(exten, '@'))) {
03074                   *context++ = '\0';
03075                }
03076                label = stringp;
03077                ast_mutex_init(&sd->lock);
03078                ast_copy_string(sd->exten, exten, sizeof(sd->exten));
03079                if (!ast_strlen_zero(context)) {
03080                   sd->isHint = 1;
03081                   sd->instance = lineInstance++;
03082                   ast_copy_string(sd->context, context, sizeof(sd->context));
03083                } else {
03084                   sd->isHint = 0;
03085                   sd->instance = speeddialInstance++;
03086                   sd->context[0] = '\0';
03087                }
03088                ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
03089 
03090                sd->parent = d;
03091 
03092                sd->next = d->speeddials;
03093                d->speeddials = sd;
03094             }
03095          } else if (!strcasecmp(v->name, "addon")) {
03096             if (!(a = ast_calloc(1, sizeof(*a)))) {
03097                return NULL;
03098             } else {
03099                ast_mutex_init(&a->lock);
03100                ast_copy_string(a->type, v->value, sizeof(a->type));
03101 
03102                a->next = d->addons;
03103                d->addons = a;
03104             }
03105          } else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) {
03106             if (!(l = ast_calloc(1, sizeof(*l)))) {
03107                return NULL;
03108             } else {
03109                ast_mutex_init(&l->lock);
03110                ast_copy_string(l->name, v->value, sizeof(l->name));
03111 
03112                /* XXX Should we check for uniqueness?? XXX */
03113                ast_copy_string(l->context, context, sizeof(l->context));
03114                ast_copy_string(l->cid_num, cid_num, sizeof(l->cid_num));
03115                ast_copy_string(l->cid_name, cid_name, sizeof(l->cid_name));
03116                ast_copy_string(l->label, linelabel, sizeof(l->label));
03117                ast_copy_string(l->language, language, sizeof(l->language));
03118                ast_copy_string(l->mohinterpret, mohinterpret, sizeof(l->mohinterpret));
03119                ast_copy_string(l->mohsuggest, mohsuggest, sizeof(l->mohsuggest));
03120                ast_copy_string(l->regexten, regexten, sizeof(l->regexten));
03121                ast_copy_string(l->mailbox, mailbox, sizeof(l->mailbox));
03122                if (!ast_strlen_zero(mailbox)) {
03123                   char *cfg_mailbox, *cfg_context;
03124                   cfg_context = cfg_mailbox = ast_strdupa(l->mailbox);
03125                   ast_verb(3, "Setting mailbox '%s' on %s@%s\n", cfg_mailbox, d->name, l->name);
03126                   strsep(&cfg_context, "@");
03127                   if (ast_strlen_zero(cfg_context))
03128                       cfg_context = "default";
03129                   l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
03130                      AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
03131                      AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
03132                      AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
03133                      AST_EVENT_IE_END);
03134                }
03135                ast_copy_string(l->vmexten, device_vmexten, sizeof(vmexten));
03136                l->chanvars = chanvars;
03137                l->msgstate = -1;
03138                l->capability = d->capability;
03139                l->prefs = d->prefs;
03140                l->parent = d;
03141                if (!strcasecmp(v->name, "trunk")) {
03142                   l->type = TYPE_TRUNK;
03143                } else {
03144                   l->type = TYPE_LINE;
03145                }
03146                l->immediate = immediate;
03147                l->callgroup = cur_callergroup;
03148                l->pickupgroup = cur_pickupgroup;
03149                l->callreturn = callreturn;
03150                l->cancallforward = cancallforward;
03151                l->getforward = 0;
03152                set_callforwards(l, NULL, 0);
03153                l->callwaiting = callwaiting;
03154                l->transfer = transfer;
03155                l->threewaycalling = threewaycalling;
03156                l->mwiblink = mwiblink;
03157                l->onhooktime = time(NULL);
03158                l->instance = lineInstance++;
03159                /* ASSUME we're onhook at this point */
03160                l->hookstate = SKINNY_ONHOOK;
03161                l->nat = nat;
03162                l->canreinvite = canreinvite;
03163 
03164                l->next = d->lines;
03165                d->lines = l;
03166             }
03167          } else {
03168             ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
03169          }
03170          v = v->next;
03171       }
03172 
03173       if (!d->lines) {
03174          ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
03175          return NULL;
03176       }
03177       if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
03178          d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
03179       }
03180 #if 0
03181       /* I don't think we need this anymore at all, since d->ourip is set in skinny_register now */
03182       if (d->addr.sin_addr.s_addr) {
03183          /* XXX See note above, in 'host' option. */
03184          if (ast_ouraddrfor(&d->addr.sin_addr, &d->ourip)) {
03185             d->ourip = __ourip;
03186          }
03187       } else {
03188          d->ourip = __ourip;
03189       }
03190 #endif
03191    }
03192    return d;
03193 }

static void cleanup_stale_contexts ( char *  new,
char *  old 
) [static]

Definition at line 1682 of file chan_skinny.c.

References ast_context_destroy(), ast_context_find(), ast_copy_string(), AST_MAX_CONTEXT, and strsep().

01683 {
01684    char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT];
01685 
01686    while ((oldcontext = strsep(&old, "&"))) {
01687       stalecontext = '\0';
01688       ast_copy_string(newlist, new, sizeof(newlist));
01689       stringp = newlist;
01690       while ((newcontext = strsep(&stringp, "&"))) {
01691          if (strcmp(newcontext, oldcontext) == 0) {
01692             /* This is not the context you're looking for */
01693             stalecontext = '\0';
01694             break;
01695          } else if (strcmp(newcontext, oldcontext)) {
01696             stalecontext = oldcontext;
01697          }
01698          
01699       }
01700       if (stalecontext)
01701          ast_context_destroy(ast_context_find(stalecontext), "Skinny");
01702    }
01703 }

static int codec_ast2skinny ( int  astcodec  )  [static]

Definition at line 1625 of file chan_skinny.c.

References AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726_AAL2, AST_FORMAT_G729A, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_ULAW, SKINNY_CODEC_ALAW, SKINNY_CODEC_G723_1, SKINNY_CODEC_G726_32, SKINNY_CODEC_G729A, SKINNY_CODEC_H261, SKINNY_CODEC_H263, and SKINNY_CODEC_ULAW.

Referenced by handle_open_receive_channel_ack_message(), skinny_set_rtp_peer(), and transmit_connect().

01626 {
01627    switch (astcodec) {
01628    case AST_FORMAT_ALAW:
01629       return SKINNY_CODEC_ALAW;
01630    case AST_FORMAT_ULAW:
01631       return SKINNY_CODEC_ULAW;
01632    case AST_FORMAT_G723_1:
01633       return SKINNY_CODEC_G723_1;
01634    case AST_FORMAT_G729A:
01635       return SKINNY_CODEC_G729A;
01636    case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
01637       return SKINNY_CODEC_G726_32;
01638    case AST_FORMAT_H261:
01639       return SKINNY_CODEC_H261;
01640    case AST_FORMAT_H263:
01641       return SKINNY_CODEC_H263;
01642    default:
01643       return 0;
01644    }
01645 }

static int codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

Definition at line 1603 of file chan_skinny.c.

References AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726_AAL2, AST_FORMAT_G729A, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_ULAW, SKINNY_CODEC_ALAW, SKINNY_CODEC_G723_1, SKINNY_CODEC_G726_32, SKINNY_CODEC_G729A, SKINNY_CODEC_H261, SKINNY_CODEC_H263, and SKINNY_CODEC_ULAW.

Referenced by handle_capabilities_res_message().

01604 {
01605    switch (skinnycodec) {
01606    case SKINNY_CODEC_ALAW:
01607       return AST_FORMAT_ALAW;
01608    case SKINNY_CODEC_ULAW:
01609       return AST_FORMAT_ULAW;
01610    case SKINNY_CODEC_G723_1:
01611       return AST_FORMAT_G723_1;
01612    case SKINNY_CODEC_G729A:
01613       return AST_FORMAT_G729A;
01614    case SKINNY_CODEC_G726_32:
01615       return AST_FORMAT_G726_AAL2; /* XXX Is this right? */
01616    case SKINNY_CODEC_H261:
01617       return AST_FORMAT_H261;
01618    case SKINNY_CODEC_H263:
01619       return AST_FORMAT_H263;
01620    default:
01621       return 0;
01622    }
01623 }

static char* complete_skinny_devices ( const char *  word,
int  state 
) [static]

Definition at line 2495 of file chan_skinny.c.

References ast_strdup, devices, skinny_device::id, and skinny_device::next.

Referenced by complete_skinny_reset(), and complete_skinny_show_device().

02496 {
02497    struct skinny_device *d;
02498    char *result = NULL;
02499    int wordlen = strlen(word), which = 0;
02500 
02501    for (d = devices; d && !result; d = d->next) {
02502       if (!strncasecmp(word, d->id, wordlen) && ++which > state)
02503          result = ast_strdup(d->id);
02504    }
02505 
02506    return result;
02507 }

static char* complete_skinny_reset ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 2514 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

02515 {
02516    return (pos == 2 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02517 }

static char* complete_skinny_show_device ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 2509 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

02510 {
02511    return (pos == 3 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02512 }

static char* complete_skinny_show_line ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 2519 of file chan_skinny.c.

References ast_strdup, devices, skinny_device::lines, skinny_line::name, skinny_line::next, and skinny_device::next.

Referenced by handle_skinny_show_line().

02520 {
02521    struct skinny_device *d;
02522    struct skinny_line *l;
02523    char *result = NULL;
02524    int wordlen = strlen(word), which = 0;
02525 
02526    if (pos != 3)
02527       return NULL;
02528    
02529    for (d = devices; d && !result; d = d->next) {
02530       for (l = d->lines; l && !result; l = l->next) {
02531          if (!strncasecmp(word, l->name, wordlen) && ++which > state)
02532             result = ast_strdup(l->name);
02533       }
02534    }
02535 
02536    return result;
02537 }

static char* control2str ( int  ind  )  [static]

Definition at line 3635 of file chan_skinny.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, AST_CONTROL_WINK, ast_threadstorage_get(), CONTROL2STR_BUFSIZE, and control2str_threadbuf.

03635                                   {
03636    char *tmp;
03637 
03638    switch (ind) {
03639    case AST_CONTROL_HANGUP:
03640       return "Other end has hungup";
03641    case AST_CONTROL_RING:
03642       return "Local ring";
03643    case AST_CONTROL_RINGING:
03644       return "Remote end is ringing";
03645    case AST_CONTROL_ANSWER:
03646       return "Remote end has answered";
03647    case AST_CONTROL_BUSY:
03648       return "Remote end is busy";
03649    case AST_CONTROL_TAKEOFFHOOK:
03650       return "Make it go off hook";
03651    case AST_CONTROL_OFFHOOK:
03652       return "Line is off hook";
03653    case AST_CONTROL_CONGESTION:
03654       return "Congestion (circuits busy)";
03655    case AST_CONTROL_FLASH:
03656       return "Flash hook";
03657    case AST_CONTROL_WINK:
03658       return "Wink";
03659    case AST_CONTROL_OPTION:
03660       return "Set a low-level option";
03661    case AST_CONTROL_RADIO_KEY:
03662       return "Key Radio";
03663    case AST_CONTROL_RADIO_UNKEY:
03664       return "Un-Key Radio";
03665    case AST_CONTROL_PROGRESS:
03666       return "Remote end is making Progress";
03667    case AST_CONTROL_PROCEEDING:
03668       return "Remote end is proceeding";
03669    case AST_CONTROL_HOLD:
03670       return "Hold";
03671    case AST_CONTROL_UNHOLD:
03672       return "Unhold";
03673    case -1:
03674       return "Stop tone";
03675    default:
03676       if (!(tmp = ast_threadstorage_get(&control2str_threadbuf, CONTROL2STR_BUFSIZE)))
03677                         return "Unknown";
03678       snprintf(tmp, CONTROL2STR_BUFSIZE, "UNKNOWN-%d", ind);
03679       return tmp;
03680    }
03681 }

static void delete_devices ( void   )  [static]

Definition at line 6044 of file chan_skinny.c.

References ast_free, ast_mutex_destroy(), ast_mutex_lock(), devicelock, devices, skinny_device::lines, skinny_speeddial::lock, skinny_line::lock, skinny_speeddial::next, skinny_line::next, and skinny_device::speeddials.

Referenced by unload_module().

06045 {
06046    struct skinny_device *d, *dlast;
06047    struct skinny_line *l, *llast;
06048    struct skinny_speeddial *sd, *sdlast;
06049    struct skinny_addon *a, *alast;
06050 
06051    ast_mutex_lock(&devicelock);
06052 
06053    /* Delete all devices */
06054    for (d=devices;d;) {
06055       /* Delete all lines for this device */
06056       for (l=d->lines;l;) {
06057          llast = l;
06058          l = l->next;
06059          ast_mutex_destroy(&llast->lock);
06060          ast_free(llast);
06061       }
06062       /* Delete all speeddials for this device */
06063       for (sd=d->speeddials;sd;) {
06064          sdlast = sd;
06065          sd = sd->next;
06066          ast_mutex_destroy(&sdlast->lock);
06067          ast_free(sdlast);
06068       }
06069       /* Delete all addons for this device */
06070       for (a=d->addons;a;) {
06071          alast = a;
06072          a = a->next;
06073          ast_mutex_destroy(&alast->lock);
06074          ast_free(alast);
06075       }
06076       dlast = d;
06077       d = d->next;
06078       ast_free(dlast);
06079    }
06080    devices=NULL;
06081    ast_mutex_unlock(&devicelock);
06082 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 5554 of file chan_skinny.c.

References ast_free, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, skinnysession::next, s, and sessionlock.

05555 {
05556    struct skinnysession *cur, *prev = NULL;
05557    ast_mutex_lock(&sessionlock);
05558    cur = sessions;
05559    while(cur) {
05560       if (cur == s) {
05561          break;
05562       }
05563       prev = cur;
05564       cur = cur->next;
05565    }
05566    if (cur) {
05567       if (prev) {
05568          prev->next = cur->next;
05569       } else {
05570          sessions = cur->next;
05571       }
05572       if (s->fd > -1) {
05573          close(s->fd);
05574       }
05575       ast_mutex_destroy(&s->lock);
05576       ast_free(s);
05577    } else {
05578       ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
05579    }
05580    ast_mutex_unlock(&sessionlock);
05581 }

static char* device2str ( int  type  )  [static]

Definition at line 2585 of file chan_skinny.c.

References ast_threadstorage_get(), DEVICE2STR_BUFSIZE, device2str_threadbuf, SKINNY_DEVICE_12, SKINNY_DEVICE_12SP, SKINNY_DEVICE_12SPPLUS, SKINNY_DEVICE_30SPPLUS, SKINNY_DEVICE_30VIP, SKINNY_DEVICE_7902, SKINNY_DEVICE_7905, SKINNY_DEVICE_7906, SKINNY_DEVICE_7910, SKINNY_DEVICE_7911, SKINNY_DEVICE_7912, SKINNY_DEVICE_7914, SKINNY_DEVICE_7920, SKINNY_DEVICE_7921, SKINNY_DEVICE_7931, SKINNY_DEVICE_7935, SKINNY_DEVICE_7936, SKINNY_DEVICE_7937, SKINNY_DEVICE_7940, SKINNY_DEVICE_7941, SKINNY_DEVICE_7941GE, SKINNY_DEVICE_7942, SKINNY_DEVICE_7945, SKINNY_DEVICE_7960, SKINNY_DEVICE_7961, SKINNY_DEVICE_7961GE, SKINNY_DEVICE_7962, SKINNY_DEVICE_7965, SKINNY_DEVICE_7970, SKINNY_DEVICE_7971, SKINNY_DEVICE_7975, SKINNY_DEVICE_7985, SKINNY_DEVICE_ATA186, SKINNY_DEVICE_CIPC, SKINNY_DEVICE_NONE, SKINNY_DEVICE_SCCPGATEWAY_AN, SKINNY_DEVICE_SCCPGATEWAY_BRI, and SKINNY_DEVICE_UNKNOWN.

Referenced by handle_skinny_show_device(), and handle_skinny_show_devices().

02586 {
02587    char *tmp;
02588 
02589    switch (type) {
02590    case SKINNY_DEVICE_NONE:
02591       return "No Device";
02592    case SKINNY_DEVICE_30SPPLUS:
02593       return "30SP Plus";
02594    case SKINNY_DEVICE_12SPPLUS:
02595       return "12SP Plus";
02596    case SKINNY_DEVICE_12SP:
02597       return "12SP";
02598    case SKINNY_DEVICE_12:
02599       return "12";
02600    case SKINNY_DEVICE_30VIP:
02601       return "30VIP";
02602    case SKINNY_DEVICE_7910:
02603       return "7910";
02604    case SKINNY_DEVICE_7960:
02605       return "7960";
02606    case SKINNY_DEVICE_7940:
02607       return "7940";
02608    case SKINNY_DEVICE_7935:
02609       return "7935";
02610    case SKINNY_DEVICE_ATA186:
02611       return "ATA186";
02612    case SKINNY_DEVICE_7941:
02613       return "7941";
02614    case SKINNY_DEVICE_7971:
02615       return "7971";
02616    case SKINNY_DEVICE_7914:
02617       return "7914";
02618    case SKINNY_DEVICE_7985:
02619       return "7985";
02620    case SKINNY_DEVICE_7911:
02621       return "7911";
02622    case SKINNY_DEVICE_7961GE:
02623       return "7961GE";
02624    case SKINNY_DEVICE_7941GE:
02625       return "7941GE";
02626    case SKINNY_DEVICE_7931:
02627       return "7931";
02628    case SKINNY_DEVICE_7921:
02629       return "7921";
02630    case SKINNY_DEVICE_7906:
02631       return "7906";
02632    case SKINNY_DEVICE_7962:
02633       return "7962";
02634    case SKINNY_DEVICE_7937:
02635       return "7937";
02636    case SKINNY_DEVICE_7942:
02637       return "7942";
02638    case SKINNY_DEVICE_7945:
02639       return "7945";
02640    case SKINNY_DEVICE_7965:
02641       return "7965";
02642    case SKINNY_DEVICE_7975:
02643       return "7975";
02644    case SKINNY_DEVICE_7905:
02645       return "7905";
02646    case SKINNY_DEVICE_7920:
02647       return "7920";
02648    case SKINNY_DEVICE_7970:
02649       return "7970";
02650    case SKINNY_DEVICE_7912:
02651       return "7912";
02652    case SKINNY_DEVICE_7902:
02653       return "7902";
02654    case SKINNY_DEVICE_CIPC:
02655       return "IP Communicator";
02656    case SKINNY_DEVICE_7961:
02657       return "7961";
02658    case SKINNY_DEVICE_7936:
02659       return "7936";
02660    case SKINNY_DEVICE_SCCPGATEWAY_AN:
02661       return "SCCPGATEWAY_AN";
02662    case SKINNY_DEVICE_SCCPGATEWAY_BRI:
02663       return "SCCPGATEWAY_BRI";
02664    case SKINNY_DEVICE_UNKNOWN:
02665       return "Unknown";
02666    default:
02667       if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE)))
02668          return "Unknown";
02669       snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type);
02670       return tmp;
02671    }
02672 }

static void do_housekeeping ( struct skinnysession s  )  [static]

Definition at line 2280 of file chan_skinny.c.

References ast_debug, handle_time_date_req_message(), has_voicemail(), skinny_line::instance, skinny_device::lines, skinny_line::mwiblink, skinny_device::name, skinny_line::name, skinny_line::next, s, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinnydebug, STIMULUS_VOICEMAIL, and transmit_lamp_indication().

Referenced by handle_keep_alive_message(), handle_onhook_message(), handle_soft_key_event_message(), and skinny_hangup().

02281 {
02282    int device_lamp = 0;
02283    struct skinny_device *d = s->device;
02284    struct skinny_line *l;
02285 
02286    /* Update time on device */
02287    handle_time_date_req_message(NULL, s);
02288 
02289    /* Set MWI on individual lines */
02290    for (l = d->lines; l; l = l->next) {
02291       if (has_voicemail(l)) {
02292          if (skinnydebug)
02293             ast_debug(1, "Checking for voicemail Skinny %s@%s\n", l->name, d->name);
02294          if (skinnydebug)
02295             ast_debug(1, "Skinny %s@%s has voicemail!\n", l->name, d->name);
02296          transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
02297          device_lamp++;
02298       } else {
02299          transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
02300       }
02301    }
02302    /* If at least one line has VM, turn the device level lamp on */
02303    if (device_lamp)
02304       transmit_lamp_indication(s, STIMULUS_VOICEMAIL, 0, SKINNY_LAMP_ON);
02305    else
02306       transmit_lamp_indication(s, STIMULUS_VOICEMAIL, 0, SKINNY_LAMP_OFF);
02307 }

static void* do_monitor ( void *  data  )  [static]

Definition at line 5760 of file chan_skinny.c.

References ast_io_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), io, and monlock.

05761 {
05762    int res;
05763 
05764    /* This thread monitors all the interfaces which are not yet in use
05765       (and thus do not have a separate thread) indefinitely */
05766    /* From here on out, we die whenever asked */
05767    for(;;) {
05768       pthread_testcancel();
05769       /* Wait for sched or io */
05770       res = ast_sched_wait(sched);
05771       if ((res < 0) || (res > 1000)) {
05772          res = 1000;
05773       }
05774       res = ast_io_wait(io, res);
05775       ast_mutex_lock(&monlock);
05776       if (res >= 0) {
05777          ast_sched_runq(sched);
05778       }
05779       ast_mutex_unlock(&monlock);
05780    }
05781    /* Never reached */
05782    return NULL;
05783 
05784 }

static struct skinny_line* find_line_by_instance ( struct skinny_device d,
int  instance 
) [static]

Definition at line 1449 of file chan_skinny.c.

References ast_log(), skinny_line::instance, skinny_device::lines, LOG_WARNING, skinny_device::name, and skinny_line::next.

Referenced by find_subchannel_by_instance_reference(), handle_enbloc_call_message(), handle_line_state_req_message(), handle_offhook_message(), handle_soft_key_event_message(), and handle_stimulus_message().

01450 {
01451    struct skinny_line *l;
01452 
01453    /*Dialing from on hook or on a 7920 uses instance 0 in requests
01454      but we need to start looking at instance 1 */
01455 
01456    if (!instance)
01457       instance = 1;
01458 
01459    for (l = d->lines; l; l = l->next) {
01460       if (l->instance == instance)
01461          break;
01462    }
01463 
01464    if (!l) {
01465       ast_log(LOG_WARNING, "Could not find line with instance '%d' on device '%s'\n", instance, d->name);
01466    }
01467    return l;
01468 }

static struct skinny_line* find_line_by_name ( const char *  dest  )  [static]

Definition at line 1470 of file chan_skinny.c.

References ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_verb, devicelock, devices, skinny_device::lines, skinny_line::name, skinny_device::name, skinny_line::next, and skinny_device::next.

Referenced by skinny_devicestate(), and skinny_request().

01471 {
01472    struct skinny_line *l;
01473    struct skinny_line *tmpl = NULL;
01474    struct skinny_device *d;
01475    char line[256];
01476    char *at;
01477    char *device;
01478    int checkdevice = 0;
01479 
01480    ast_copy_string(line, dest, sizeof(line));
01481    at = strchr(line, '@');
01482    if (at)
01483       *at++ = '\0';
01484    device = at;
01485 
01486    if (!ast_strlen_zero(device))
01487       checkdevice = 1;
01488 
01489    ast_mutex_lock(&devicelock);
01490    for (d = devices; d; d = d->next) {
01491       if (checkdevice && tmpl)
01492          break;
01493       else if (!checkdevice) {
01494          /* This is a match, since we're checking for line on every device. */
01495       } else if (!strcasecmp(d->name, device)) {
01496          if (skinnydebug)
01497             ast_verb(2, "Found device: %s\n", d->name);
01498       } else
01499          continue;
01500 
01501       /* Found the device (or we don't care which device) */
01502       for (l = d->lines; l; l = l->next) {
01503          /* Search for the right line */
01504          if (!strcasecmp(l->name, line)) {
01505             if (tmpl) {
01506                ast_verb(2, "Ambiguous line name: %s\n", line);
01507                ast_mutex_unlock(&devicelock);
01508                return NULL;
01509             } else
01510                tmpl = l;
01511          }
01512       }
01513    }
01514    ast_mutex_unlock(&devicelock);
01515    return tmpl;
01516 }

static struct skinny_speeddial* find_speeddial_by_instance ( struct skinny_device d,
int  instance,
int  isHint 
) [static]

Definition at line 1588 of file chan_skinny.c.

References ast_log(), skinny_speeddial::instance, skinny_speeddial::isHint, LOG_WARNING, skinny_device::name, skinny_speeddial::next, and skinny_device::speeddials.

Referenced by handle_line_state_req_message(), handle_speed_dial_stat_req_message(), and handle_stimulus_message().

01589 {
01590    struct skinny_speeddial *sd;
01591 
01592    for (sd = d->speeddials; sd; sd = sd->next) {
01593       if (sd->isHint == isHint && sd->instance == instance)
01594          break;
01595    }
01596 
01597    if (!sd) {
01598       ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
01599    }
01600    return sd;
01601 }

static struct skinny_subchannel* find_subchannel_by_instance_reference ( struct skinny_device d,
int  instance,
int  reference 
) [static]

Definition at line 1537 of file chan_skinny.c.

References ast_log(), skinny_subchannel::callid, find_line_by_instance(), LOG_WARNING, skinny_device::name, skinny_subchannel::next, and skinny_line::sub.

Referenced by handle_enbloc_call_message(), handle_keypad_button_message(), handle_message(), handle_offhook_message(), handle_onhook_message(), handle_soft_key_event_message(), and handle_stimulus_message().

01538 {
01539    struct skinny_line *l = find_line_by_instance(d, instance);
01540    struct skinny_subchannel *sub;
01541 
01542    if (!l) {
01543       return NULL;
01544    }
01545 
01546    /* 7920 phones set call reference to 0, so use the first
01547       sub-channel on the list.
01548            This MIGHT need more love to be right */
01549    if (!reference)
01550       sub = l->sub;
01551    else {
01552       for (sub = l->sub; sub; sub = sub->next) {
01553          if (sub->callid == reference)
01554             break;
01555       }
01556    }
01557    if (!sub) {
01558       ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s'\n", reference, d->name);
01559    }
01560    return sub;
01561 }

static struct skinny_subchannel* find_subchannel_by_reference ( struct skinny_device d,
int  reference 
) [static]

Definition at line 1564 of file chan_skinny.c.

References ast_log(), skinny_subchannel::callid, skinny_device::lines, LOG_WARNING, skinny_line::name, skinny_device::name, skinny_subchannel::next, skinny_line::next, and skinny_line::sub.

Referenced by handle_open_receive_channel_ack_message().

01565 {
01566    struct skinny_line *l;
01567    struct skinny_subchannel *sub = NULL;
01568 
01569    for (l = d->lines; l; l = l->next) {
01570       for (sub = l->sub; sub; sub = sub->next) {
01571          if (sub->callid == reference)
01572             break;
01573       }
01574       if (sub)
01575          break;
01576    }
01577 
01578    if (!l) {
01579       ast_log(LOG_WARNING, "Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
01580    } else {
01581       if (!sub) {
01582          ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
01583       }
01584    }
01585    return sub;
01586 }

static void* get_button_template ( struct skinnysession s,
struct button_definition_template btn 
) [static]

Definition at line 1300 of file chan_skinny.c.

References skinny_device::addons, ast_log(), BT_CALLPARK, BT_CONFERENCE, BT_CUST_LINE, BT_CUST_LINESPEEDDIAL, BT_DISPLAY, BT_FORWARDALL, BT_HOLD, BT_LINE, BT_NONE, BT_REDIAL, BT_SPEEDDIAL, BT_TRANSFER, BT_VOICEMAIL, LOG_WARNING, skinny_addon::next, s, SKINNY_DEVICE_12, SKINNY_DEVICE_12SP, SKINNY_DEVICE_12SPPLUS, SKINNY_DEVICE_30SPPLUS, SKINNY_DEVICE_30VIP, SKINNY_DEVICE_7902, SKINNY_DEVICE_7905, SKINNY_DEVICE_7906, SKINNY_DEVICE_7910, SKINNY_DEVICE_7911, SKINNY_DEVICE_7912, SKINNY_DEVICE_7914, SKINNY_DEVICE_7920, SKINNY_DEVICE_7921, SKINNY_DEVICE_7931, SKINNY_DEVICE_7935, SKINNY_DEVICE_7936, SKINNY_DEVICE_7937, SKINNY_DEVICE_7940, SKINNY_DEVICE_7941, SKINNY_DEVICE_7941GE, SKINNY_DEVICE_7942, SKINNY_DEVICE_7945, SKINNY_DEVICE_7960, SKINNY_DEVICE_7961, SKINNY_DEVICE_7961GE, SKINNY_DEVICE_7962, SKINNY_DEVICE_7965, SKINNY_DEVICE_7970, SKINNY_DEVICE_7971, SKINNY_DEVICE_7975, SKINNY_DEVICE_7985, SKINNY_DEVICE_ATA186, SKINNY_DEVICE_CIPC, SKINNY_DEVICE_SCCPGATEWAY_AN, SKINNY_DEVICE_SCCPGATEWAY_BRI, skinny_addon::type, and skinny_device::type.

Referenced by handle_button_template_req_message().

01301 {
01302    struct skinny_device *d = s->device;
01303    struct skinny_addon *a = d->addons;
01304    int i;
01305 
01306    switch (d->type) {
01307       case SKINNY_DEVICE_30SPPLUS:
01308       case SKINNY_DEVICE_30VIP:
01309          /* 13 rows, 2 columns */
01310          for (i = 0; i < 4; i++)
01311             (btn++)->buttonDefinition = BT_CUST_LINE;
01312          (btn++)->buttonDefinition = BT_REDIAL;
01313          (btn++)->buttonDefinition = BT_VOICEMAIL;
01314          (btn++)->buttonDefinition = BT_CALLPARK;
01315          (btn++)->buttonDefinition = BT_FORWARDALL;
01316          (btn++)->buttonDefinition = BT_CONFERENCE;
01317          for (i = 0; i < 4; i++)
01318             (btn++)->buttonDefinition = BT_NONE;
01319          for (i = 0; i < 13; i++)
01320             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01321          
01322          break;
01323       case SKINNY_DEVICE_12SPPLUS:
01324       case SKINNY_DEVICE_12SP:
01325       case SKINNY_DEVICE_12:
01326          /* 6 rows, 2 columns */
01327          for (i = 0; i < 2; i++)
01328             (btn++)->buttonDefinition = BT_CUST_LINE;
01329          for (i = 0; i < 4; i++)
01330             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01331          (btn++)->buttonDefinition = BT_HOLD;
01332          (btn++)->buttonDefinition = BT_REDIAL;
01333          (btn++)->buttonDefinition = BT_TRANSFER;
01334          (btn++)->buttonDefinition = BT_FORWARDALL;
01335          (btn++)->buttonDefinition = BT_CALLPARK;
01336          (btn++)->buttonDefinition = BT_VOICEMAIL;
01337          break;
01338       case SKINNY_DEVICE_7910:
01339          (btn++)->buttonDefinition = BT_LINE;
01340          (btn++)->buttonDefinition = BT_HOLD;
01341          (btn++)->buttonDefinition = BT_TRANSFER;
01342          (btn++)->buttonDefinition = BT_DISPLAY;
01343          (btn++)->buttonDefinition = BT_VOICEMAIL;
01344          (btn++)->buttonDefinition = BT_CONFERENCE;
01345          (btn++)->buttonDefinition = BT_FORWARDALL;
01346          for (i = 0; i < 2; i++)
01347             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01348          (btn++)->buttonDefinition = BT_REDIAL;
01349          break;
01350       case SKINNY_DEVICE_7960:
01351       case SKINNY_DEVICE_7961:
01352       case SKINNY_DEVICE_7961GE:
01353       case SKINNY_DEVICE_7962:
01354       case SKINNY_DEVICE_7965:
01355          for (i = 0; i < 6; i++)
01356             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01357          break;
01358       case SKINNY_DEVICE_7940:
01359       case SKINNY_DEVICE_7941:
01360       case SKINNY_DEVICE_7941GE:
01361       case SKINNY_DEVICE_7942:
01362       case SKINNY_DEVICE_7945:
01363          for (i = 0; i < 2; i++)
01364             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01365          break;
01366       case SKINNY_DEVICE_7935:
01367       case SKINNY_DEVICE_7936:
01368          for (i = 0; i < 2; i++)
01369             (btn++)->buttonDefinition = BT_LINE;
01370          break;
01371       case SKINNY_DEVICE_ATA186:
01372          (btn++)->buttonDefinition = BT_LINE;
01373          break;
01374       case SKINNY_DEVICE_7970:
01375       case SKINNY_DEVICE_7971:
01376       case SKINNY_DEVICE_7975:
01377       case SKINNY_DEVICE_CIPC:
01378          for (i = 0; i < 8; i++)
01379             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01380          break;
01381       case SKINNY_DEVICE_7985:
01382          /* XXX I have no idea what the buttons look like on these. */
01383          ast_log(LOG_WARNING, "Unsupported device type '%d (7985)' found.\n", d->type);
01384          break;
01385       case SKINNY_DEVICE_7912:
01386       case SKINNY_DEVICE_7911:
01387       case SKINNY_DEVICE_7905:
01388          (btn++)->buttonDefinition = BT_LINE;
01389          (btn++)->buttonDefinition = BT_HOLD;
01390          break;
01391       case SKINNY_DEVICE_7920:
01392          /* XXX I don't know if this is right. */
01393          for (i = 0; i < 4; i++)
01394             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01395          break;
01396       case SKINNY_DEVICE_7921:
01397          for (i = 0; i < 6; i++)
01398             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01399          break;
01400       case SKINNY_DEVICE_7902:
01401          ast_log(LOG_WARNING, "Unsupported device type '%d (7902)' found.\n", d->type);
01402          break;
01403       case SKINNY_DEVICE_7906:
01404          ast_log(LOG_WARNING, "Unsupported device type '%d (7906)' found.\n", d->type);
01405          break;
01406       case SKINNY_DEVICE_7931:
01407          ast_log(LOG_WARNING, "Unsupported device type '%d (7931)' found.\n", d->type);
01408          break;
01409       case SKINNY_DEVICE_7937:
01410          ast_log(LOG_WARNING, "Unsupported device type '%d (7937)' found.\n", d->type);
01411          break;
01412       case SKINNY_DEVICE_7914:
01413          ast_log(LOG_WARNING, "Unsupported device type '%d (7914)' found.  Expansion module registered by itself?\n", d->type);
01414          break;
01415       case SKINNY_DEVICE_SCCPGATEWAY_AN:
01416       case SKINNY_DEVICE_SCCPGATEWAY_BRI:
01417          ast_log(LOG_WARNING, "Unsupported device type '%d (SCCP gateway)' found.\n", d->type);
01418          break;
01419       default:
01420          ast_log(LOG_WARNING, "Unknown device type '%d' found.\n", d->type);
01421          break;
01422    }
01423 
01424    for (a = d->addons; a; a = a->next) {
01425       if (!strcasecmp(a->type, "7914")) {
01426          for (i = 0; i < 14; i++)
01427             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01428       } else {
01429          ast_log(LOG_WARNING, "Unknown addon type '%s' found.  Skipping.\n", a->type);
01430       }
01431    }
01432 
01433    return btn;
01434 }

static int get_devicestate ( struct skinny_line l  )  [static]

Definition at line 3606 of file chan_skinny.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, skinny_line::dnd, skinny_line::hookstate, skinny_subchannel::next, skinny_subchannel::onhold, skinny_line::parent, SKINNY_ONHOOK, and skinny_line::sub.

Referenced by skinny_devicestate(), and skinny_new().

03607 {
03608    struct skinny_subchannel *sub;
03609    int res = AST_DEVICE_UNKNOWN;
03610 
03611    if (!l)
03612       res = AST_DEVICE_INVALID;
03613    else if (!l->parent)
03614       res = AST_DEVICE_UNAVAILABLE;
03615    else if (l->dnd)
03616       res = AST_DEVICE_BUSY;
03617    else {
03618       if (l->hookstate == SKINNY_ONHOOK) {
03619          res = AST_DEVICE_NOT_INUSE;
03620       } else {
03621          res = AST_DEVICE_INUSE;
03622       }
03623 
03624       for (sub = l->sub; sub; sub = sub->next) {
03625          if (sub->onhold) {
03626             res = AST_DEVICE_ONHOLD;
03627             break;
03628          }
03629       }
03630    }
03631 
03632    return res;
03633 }

static int get_input ( struct skinnysession s  )  [static]

Definition at line 5583 of file chan_skinny.c.

References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_poll, errno, htolel, keep_alive, letohl, LOG_WARNING, s, skinny_unregister(), and skinnydebug.

05584 {
05585    int res;
05586    int dlen = 0;
05587    struct pollfd fds[1];
05588 
05589    fds[0].fd = s->fd;
05590    fds[0].events = POLLIN;
05591    fds[0].revents = 0;
05592    res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
05593                    /* we add 10% to the keep_alive to deal */
05594                    /* with network delays, etc */
05595    if (res < 0) {
05596       if (errno != EINTR) {
05597          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
05598          return res;
05599       }
05600    } else if (res == 0) {
05601       if (skinnydebug)
05602          ast_debug(1, "Skinny Client was lost, unregistering\n");
05603       skinny_unregister(NULL, s);
05604       return -1;
05605    }
05606            
05607    if (fds[0].revents) {
05608       ast_mutex_lock(&s->lock);
05609       memset(s->inbuf,0,sizeof(s->inbuf));
05610       res = read(s->fd, s->inbuf, 4);
05611       if (res < 0) {
05612          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
05613 
05614          if (skinnydebug)
05615             ast_debug(1, "Skinny Client was lost, unregistering\n");
05616          
05617          skinny_unregister(NULL,s);
05618          ast_mutex_unlock(&s->lock);
05619          return res;
05620       } else if (res != 4) {
05621          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
05622          ast_mutex_unlock(&s->lock);
05623          
05624          if (res == 0) {
05625             if (skinnydebug)
05626                ast_debug(1, "Skinny Client was lost, unregistering\n");
05627             skinny_unregister(NULL, s);
05628          }
05629            
05630          return -1;
05631       }
05632       
05633       dlen = letohl(*(int *)s->inbuf);
05634       if (dlen < 4) {
05635          ast_debug(1, "Skinny Client sent invalid data.\n");
05636          ast_mutex_unlock(&s->lock);
05637          return -1;
05638       }
05639       if (dlen+8 > sizeof(s->inbuf)) {
05640          dlen = sizeof(s->inbuf) - 8;
05641       }
05642       *(int *)s->inbuf = htolel(dlen);
05643 
05644       res = read(s->fd, s->inbuf+4, dlen+4);
05645       ast_mutex_unlock(&s->lock);
05646       if (res < 0) {
05647          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
05648          return res;
05649       } else if (res != (dlen+4)) {
05650          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
05651          return -1;
05652       }
05653       return res;
05654    }
05655    return 0;
05656 }

static int handle_alarm_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4877 of file chan_skinny.c.

References skinny_data::alarm, ast_debug, skinny_req::data, alarm_message::displayMessage, and skinnydebug.

Referenced by handle_message().

04878 {
04879    /* no response necessary */
04880    if (skinnydebug)
04881       ast_debug(1, "Received Alarm Message: %s\n", req->data.alarm.displayMessage);
04882 
04883    return 1;
04884 }

static int handle_button_template_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4704 of file chan_skinny.c.

References ast_verb, BT_CUST_LINE, BT_CUST_LINESPEEDDIAL, BT_LINE, BT_NONE, BT_SPEEDDIAL, BUTTON_TEMPLATE_RES_MESSAGE, button_definition::buttonDefinition, button_definition_template::buttonDefinition, skinny_data::buttontemplate, skinny_req::data, button_template_res_message::definition, get_button_template(), htolel, skinny_speeddial::instance, skinny_line::instance, button_definition::instanceNumber, skinny_speeddial::isHint, skinny_device::lines, skinny_speeddial::next, skinny_line::next, req_alloc(), s, and skinny_device::speeddials.

Referenced by handle_message().

04705 {
04706    struct skinny_device *d = s->device;
04707    struct skinny_line *l;
04708    int i;
04709 
04710    struct skinny_speeddial *sd;
04711    struct button_definition_template btn[42];
04712    int lineInstance = 1;
04713    int speeddialInstance = 1;
04714    int buttonCount = 0;
04715 
04716    if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
04717       return -1;
04718 
04719    memset(&btn, 0, sizeof(btn));
04720 
04721    get_button_template(s, btn);
04722 
04723    for (i=0; i<42; i++) {
04724       int btnSet = 0;
04725       switch (btn[i].buttonDefinition) {
04726          case BT_CUST_LINE:
04727             /* assume failure */
04728             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
04729             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
04730 
04731             for (l = d->lines; l; l = l->next) {
04732                if (l->instance == lineInstance) {
04733                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
04734                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
04735                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
04736                   lineInstance++;
04737                   buttonCount++;
04738                   btnSet = 1;
04739                   break;
04740                }
04741             }
04742 
04743             if (!btnSet) {
04744                for (sd = d->speeddials; sd; sd = sd->next) {
04745                   if (sd->isHint && sd->instance == lineInstance) {
04746                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
04747                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
04748                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
04749                      lineInstance++;
04750                      buttonCount++;
04751                      btnSet = 1;
04752                      break;
04753                   }
04754                }
04755             }
04756             break;
04757          case BT_CUST_LINESPEEDDIAL:
04758             /* assume failure */
04759             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
04760             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
04761 
04762             for (l = d->lines; l; l = l->next) {
04763                if (l->instance == lineInstance) {
04764                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
04765                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
04766                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
04767                   lineInstance++;
04768                   buttonCount++;
04769                   btnSet = 1;
04770                   break;
04771                }
04772             }
04773 
04774             if (!btnSet) {
04775                for (sd = d->speeddials; sd; sd = sd->next) {
04776                   if (sd->isHint && sd->instance == lineInstance) {
04777                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
04778                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
04779                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
04780                      lineInstance++;
04781                      buttonCount++;
04782                      btnSet = 1;
04783                      break;
04784                   } else if (!sd->isHint && sd->instance == speeddialInstance) {
04785                      ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
04786                      req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
04787                      req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance);
04788                      speeddialInstance++;
04789                      buttonCount++;
04790                      btnSet = 1;
04791                      break;
04792                   }
04793                }
04794             }
04795             break;
04796          case BT_LINE:
04797             req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
04798             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
04799 
04800             for (l = d->lines; l; l = l->next) {
04801                if (l->instance == lineInstance) {
04802                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
04803                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
04804                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
04805                   lineInstance++;
04806                   buttonCount++;
04807                   btnSet = 1;
04808                   break;
04809                }
04810             }
04811             break;
04812          case BT_SPEEDDIAL:
04813             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
04814             req->data.buttontemplate.definition[i].instanceNumber = 0;
04815 
04816             for (sd = d->speeddials; sd; sd = sd->next) {
04817                if (!sd->isHint && sd->instance == speeddialInstance) {
04818                   ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
04819                   req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
04820                   req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance - 1);
04821                   speeddialInstance++;
04822                   buttonCount++;
04823                   btnSet = 1;
04824                   break;
04825                }
04826             }
04827             break;
04828          case BT_NONE:
04829             break;
04830          default:
04831             ast_verb(0, "Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
04832             req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
04833             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
04834             buttonCount++;
04835             btnSet = 1;
04836             break;
04837       }
04838    }
04839 
04840    req->data.buttontemplate.buttonOffset = htolel(0);
04841    req->data.buttontemplate.buttonCount = htolel(buttonCount);
04842    req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
04843 
04844    if (skinnydebug)
04845       ast_debug(1, "Sending %d template to %s\n",
04846                d->type,
04847                d->name);
04848    transmit_response(s, req);
04849    return 1;
04850 }

static int handle_callforward_button ( struct skinny_subchannel sub,
int  cfwdtype 
) [static]

Definition at line 4002 of file chan_skinny.c.

References ast_channel::_state, ast_debug, ast_hangup(), ast_indicate(), ast_log(), ast_pthread_create, ast_safe_sleep(), AST_STATE_UP, skinny_subchannel::callid, skinny_line::cfwdtype, errno, skinny_line::getforward, skinny_line::hookstate, skinny_line::instance, KEYDEF_RINGOUT, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, s, skinny_device::session, set_callforwards(), SKINNY_DIALTONE, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), skinnydebug, skinny_line::sub, transmit_callstate(), transmit_cfwdstate(), transmit_displaymessage(), transmit_displaynotify(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

04003 {
04004    struct skinny_line *l = sub->parent;
04005    struct skinny_device *d = l->parent;
04006    struct skinnysession *s = d->session;
04007    struct ast_channel *c = sub->owner;
04008    pthread_t t;
04009 
04010    if (l->hookstate == SKINNY_ONHOOK) {
04011       l->hookstate = SKINNY_OFFHOOK;
04012       transmit_speaker_mode(s, SKINNY_SPEAKERON);
04013       transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04014    }
04015    if (skinnydebug)
04016       ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04017    transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04018 
04019    if (l->cfwdtype & cfwdtype) {
04020       set_callforwards(l, NULL, cfwdtype);
04021       ast_safe_sleep(c, 500);
04022       transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
04023       transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
04024       transmit_displaynotify(s, "CFwd disabled", 10);
04025       if (sub->owner && sub->owner->_state != AST_STATE_UP) {
04026          ast_indicate(c, -1);
04027          ast_hangup(c);
04028       }
04029       transmit_cfwdstate(s, l);
04030    } else {
04031       l->getforward = cfwdtype;
04032       transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04033       transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
04034       if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04035          ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04036          ast_hangup(c);
04037       }
04038    }
04039    return 0;
04040 }

static int handle_capabilities_res_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4584 of file chan_skinny.c.

References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, skinny_line::capability, skinny_device::capability, capabilities_res_message::caps, skinny_data::caps, station_capabilities::codec, codec_skinny2ast(), capabilities_res_message::count, skinny_req::data, letohl, skinny_device::lines, skinny_line::lock, LOG_WARNING, skinny_line::next, s, SKINNY_MAX_CAPABILITIES, and skinnydebug.

Referenced by handle_message().

04585 {
04586    struct skinny_device *d = s->device;
04587    struct skinny_line *l;
04588    uint32_t count = 0;
04589    int codecs = 0;
04590    int i;
04591 
04592    count = letohl(req->data.caps.count);
04593    if (count > SKINNY_MAX_CAPABILITIES) {
04594       count = SKINNY_MAX_CAPABILITIES;
04595       ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
04596    }
04597 
04598    for (i = 0; i < count; i++) {
04599       int acodec = 0;
04600       int scodec = 0;
04601       scodec = letohl(req->data.caps.caps[i].codec);
04602       acodec = codec_skinny2ast(scodec);
04603       if (skinnydebug)
04604          ast_debug(1, "Adding codec capability '%d (%d)'\n", acodec, scodec);
04605       codecs |= acodec;
04606    }
04607 
04608    d->capability &= codecs;
04609    ast_verb(0, "Device capability set to '%d'\n", d->capability);
04610    for (l = d->lines; l; l = l->next) {
04611       ast_mutex_lock(&l->lock);
04612       l->capability = d->capability;
04613       ast_mutex_unlock(&l->lock);
04614    }
04615 
04616    return 1;
04617 }

static int handle_enbloc_call_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4953 of file chan_skinny.c.

References ast_copy_string(), ast_debug, ast_hangup(), ast_ignore_pattern(), ast_log(), ast_pthread_create, AST_STATE_DOWN, enbloc_call_message::calledParty, skinny_subchannel::callid, ast_channel::context, skinny_req::data, skinny_data::enbloccallmessage, errno, ast_channel::exten, find_line_by_instance(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, skinny_device::lastcallreference, skinny_device::lastlineinstance, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::parent, s, SKINNY_DIALTONE, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_SILENCE, skinnydebug, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), and transmit_tone().

Referenced by handle_message().

04954 {
04955    struct skinny_device *d = s->device;
04956    struct skinny_line *l;
04957    struct skinny_subchannel *sub = NULL;
04958    struct ast_channel *c;
04959    pthread_t t;
04960 
04961    if (skinnydebug)
04962       ast_debug(1, "Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
04963 
04964    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04965 
04966    if (!sub) {
04967       l = find_line_by_instance(d, d->lastlineinstance);
04968       if (!l) {
04969          return 0;
04970       }
04971    } else {
04972       l = sub->parent;
04973    }
04974 
04975    c = skinny_new(l, AST_STATE_DOWN);
04976 
04977    if(!c) {
04978       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04979    } else {
04980       l->hookstate = SKINNY_OFFHOOK;
04981 
04982       sub = c->tech_pvt;
04983       transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04984       if (skinnydebug)
04985          ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04986       transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04987       transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04988 
04989       if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
04990          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04991       }
04992       ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
04993       if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04994          ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04995          ast_hangup(c);
04996       }
04997    }
04998    
04999    return 1;
05000 }

static int handle_headset_status_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5377 of file chan_skinny.c.

Referenced by handle_message().

05378 {
05379    /* XXX umm...okay?  Why do I care? */
05380    return 1;
05381 }

static int handle_ip_port_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4041 of file chan_skinny.c.

Referenced by handle_message().

04042 {
04043    /* no response necessary */
04044    return 1;
04045 }

static int handle_keep_alive_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 3951 of file chan_skinny.c.

References do_housekeeping(), KEEP_ALIVE_ACK_MESSAGE, req_alloc(), s, and transmit_response().

Referenced by handle_message().

03952 {
03953    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
03954       return -1;
03955 
03956    transmit_response(s, req);
03957    do_housekeeping(s);
03958    return 1;
03959 }

static int handle_keypad_button_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4047 of file chan_skinny.c.

References ast_channel::_state, ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), keypad_button_message::button, keypad_button_message::callReference, skinny_req::data, f, find_subchannel_by_instance_reference(), skinny_data::keypad, skinny_device::lastcallreference, skinny_device::lastlineinstance, letohl, keypad_button_message::lineInstance, LOG_WARNING, skinny_line::name, skinny_subchannel::next, skinny_subchannel::owner, skinny_subchannel::parent, s, and skinnydebug.

Referenced by handle_message().

04048 {
04049    struct skinny_subchannel *sub = NULL;
04050    struct skinny_line *l;
04051    struct skinny_device *d = s->device;
04052    struct ast_frame f = { 0, };
04053    char dgt;
04054    int digit;
04055    int lineInstance;
04056    int callReference;
04057 
04058    digit = letohl(req->data.keypad.button);
04059    lineInstance = letohl(req->data.keypad.lineInstance);
04060    callReference = letohl(req->data.keypad.callReference);
04061 
04062    if (digit == 14) {
04063       dgt = '*';
04064    } else if (digit == 15) {
04065       dgt = '#';
04066    } else if (digit >= 0 && digit <= 9) {
04067       dgt = '0' + digit;
04068    } else {
04069       /* digit=10-13 (A,B,C,D ?), or
04070        * digit is bad value
04071        *
04072        * probably should not end up here, but set
04073        * value for backward compatibility, and log
04074        * a warning.
04075        */
04076       dgt = '0' + digit;
04077       ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
04078    }
04079 
04080    f.subclass = dgt;
04081 
04082    f.src = "skinny";
04083 
04084    if (lineInstance && callReference)
04085       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
04086    else
04087       sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04088 
04089    if (!sub)
04090       return 0;
04091 
04092    l = sub->parent;
04093    if (sub->owner) {
04094       if (sub->owner->_state == 0) {
04095          f.frametype = AST_FRAME_DTMF_BEGIN;
04096          ast_queue_frame(sub->owner, &f);
04097       }
04098       /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
04099       f.frametype = AST_FRAME_DTMF_END;
04100       ast_queue_frame(sub->owner, &f);
04101       /* XXX This seriously needs to be fixed */
04102       if (sub->next && sub->next->owner) {
04103          if (sub->owner->_state == 0) {
04104             f.frametype = AST_FRAME_DTMF_BEGIN;
04105             ast_queue_frame(sub->next->owner, &f);
04106          }
04107          f.frametype = AST_FRAME_DTMF_END;
04108          ast_queue_frame(sub->next->owner, &f);
04109       }
04110    } else {
04111       if (skinnydebug)
04112          ast_debug(1, "No owner: %s\n", l->name);
04113    }
04114    return 1;
04115 }

static int handle_line_state_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4644 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), skinny_req::data, devicelock, find_line_by_instance(), find_speeddial_by_instance(), skinny_speeddial::instance, skinny_line::label, skinny_speeddial::label, letohl, skinny_data::line, LINE_STAT_RES_MESSAGE, line_stat_res_message::lineDirNumber, line_stat_res_message::lineDisplayName, line_stat_res_message::lineNumber, line_state_req_message::lineNumber, skinny_data::linestat, skinny_line::name, req_alloc(), s, and transmit_response().

Referenced by handle_message().

04645 {
04646    struct skinny_device *d = s->device;
04647    struct skinny_line *l;
04648    struct skinny_speeddial *sd = NULL;
04649    int instance;
04650 
04651    instance = letohl(req->data.line.lineNumber);
04652 
04653    ast_mutex_lock(&devicelock);
04654 
04655    l = find_line_by_instance(d, instance);
04656 
04657    if (!l) {
04658       sd = find_speeddial_by_instance(d, instance, 1);
04659    }
04660 
04661    if (!l && !sd) {
04662       return 0;
04663    }
04664 
04665    ast_mutex_unlock(&devicelock);
04666 
04667    if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
04668       return -1;
04669 
04670    req->data.linestat.lineNumber = letohl(instance);
04671    if (!l) {
04672       memcpy(req->data.linestat.lineDirNumber, sd->label, sizeof(req->data.linestat.lineDirNumber));
04673       memcpy(req->data.linestat.lineDisplayName, sd->label, sizeof(req->data.linestat.lineDisplayName));
04674    } else {
04675       memcpy(req->data.linestat.lineDirNumber, l->name, sizeof(req->data.linestat.lineDirNumber));
04676       memcpy(req->data.linestat.lineDisplayName, l->label, sizeof(req->data.linestat.lineDisplayName));
04677    }
04678    transmit_response(s,req);
04679    return 1;
04680 }

static int handle_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5389 of file chan_skinny.c.

References ast_channel::_state, ALARM_MESSAGE, ast_debug, ast_free, ast_log(), AST_STATE_UP, keypad_button_message::button, BUTTON_TEMPLATE_REQ_MESSAGE, keypad_button_message::callReference, CAPABILITIES_RES_MESSAGE, skinny_req::data, skinny_req::e, ENBLOC_CALL_MESSAGE, skinny_device::exten, find_subchannel_by_instance_reference(), handle_alarm_message(), handle_button_template_req_message(), handle_capabilities_res_message(), handle_enbloc_call_message(), handle_headset_status_message(), handle_ip_port_message(), handle_keep_alive_message(), handle_keypad_button_message(), handle_line_state_req_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_register_available_lines_message(), handle_register_message(), handle_server_request_message(), handle_soft_key_event_message(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_stimulus_message(), handle_time_date_req_message(), handle_unregister_message(), handle_version_req_message(), HEADSET_STATUS_MESSAGE, IP_PORT_MESSAGE, KEEP_ALIVE_MESSAGE, skinny_data::keypad, KEYPAD_BUTTON_MESSAGE, letohl, LINE_STATE_REQ_MESSAGE, keypad_button_message::lineInstance, LOG_WARNING, register_message::name, OFFHOOK_MESSAGE, ONHOOK_MESSAGE, OPEN_RECEIVE_CHANNEL_ACK_MESSAGE, skinny_subchannel::owner, skinny_data::reg, REGISTER_AVAILABLE_LINES_MESSAGE, REGISTER_MESSAGE, s, SERVER_REQUEST_MESSAGE, skinnydebug, SOFT_KEY_EVENT_MESSAGE, SOFT_KEY_SET_REQ_MESSAGE, SOFT_KEY_TEMPLATE_REQ_MESSAGE, SPEED_DIAL_STAT_REQ_MESSAGE, STIMULUS_MESSAGE, TIME_DATE_REQ_MESSAGE, UNREGISTER_MESSAGE, and VERSION_REQ_MESSAGE.

Referenced by skinny_session().

05390 {
05391    int res = 0;
05392 
05393    if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
05394       ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
05395       ast_free(req);
05396       return 0;
05397    }
05398 
05399    switch(letohl(req->e))  {
05400    case KEEP_ALIVE_MESSAGE:
05401       res = handle_keep_alive_message(req, s);
05402       break;
05403    case REGISTER_MESSAGE:
05404       if (skinnydebug)
05405          ast_debug(1, "Device %s is attempting to register\n", req->data.reg.name);
05406 
05407       res = handle_register_message(req, s);
05408       break;
05409    case IP_PORT_MESSAGE:
05410       res = handle_ip_port_message(req, s);
05411       break;
05412    case KEYPAD_BUTTON_MESSAGE:
05413        {
05414       struct skinny_device *d = s->device;
05415       struct skinny_subchannel *sub;
05416       int lineInstance;
05417       int callReference;
05418 
05419       if (skinnydebug)
05420          ast_debug(1, "Collected digit: [%d]\n", letohl(req->data.keypad.button));
05421 
05422       lineInstance = letohl(req->data.keypad.lineInstance);
05423       callReference = letohl(req->data.keypad.callReference);
05424 
05425       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
05426 
05427       if (sub && (sub->owner && sub->owner->_state <  AST_STATE_UP)) {
05428          char dgt;
05429          int digit = letohl(req->data.keypad.button);
05430    
05431          if (digit == 14) {
05432             dgt = '*';
05433          } else if (digit == 15) {
05434             dgt = '#';
05435          } else if (digit >= 0 && digit <= 9) {
05436             dgt = '0' + digit;
05437          } else {
05438             /* digit=10-13 (A,B,C,D ?), or
05439             * digit is bad value
05440             *
05441             * probably should not end up here, but set
05442             * value for backward compatibility, and log
05443             * a warning.
05444             */
05445             dgt = '0' + digit;
05446             ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
05447          }
05448 
05449          d->exten[strlen(d->exten)] = dgt;
05450          d->exten[strlen(d->exten)+1] = '\0';
05451       } else
05452          res = handle_keypad_button_message(req, s);
05453        }
05454       break;
05455    case ENBLOC_CALL_MESSAGE:
05456       res = handle_enbloc_call_message(req, s);
05457       break;
05458    case STIMULUS_MESSAGE:
05459       res = handle_stimulus_message(req, s);
05460       break;
05461    case OFFHOOK_MESSAGE:
05462       res = handle_offhook_message(req, s);
05463       break;
05464    case ONHOOK_MESSAGE:
05465       res = handle_onhook_message(req, s);
05466       break;
05467    case CAPABILITIES_RES_MESSAGE:
05468       if (skinnydebug)
05469          ast_debug(1, "Received CapabilitiesRes\n");
05470 
05471       res = handle_capabilities_res_message(req, s);
05472       break;
05473    case SPEED_DIAL_STAT_REQ_MESSAGE:
05474       if (skinnydebug)
05475          ast_debug(1, "Received SpeedDialStatRequest\n");
05476 
05477       res = handle_speed_dial_stat_req_message(req, s);
05478       break;
05479    case LINE_STATE_REQ_MESSAGE:
05480       if (skinnydebug)
05481          ast_debug(1, "Received LineStatRequest\n");
05482       res = handle_line_state_req_message(req, s);
05483       break;
05484    case TIME_DATE_REQ_MESSAGE:
05485       if (skinnydebug)
05486          ast_debug(1, "Received Time/Date Request\n");
05487 
05488       res = handle_time_date_req_message(req, s);
05489       break;
05490    case BUTTON_TEMPLATE_REQ_MESSAGE:
05491       if (skinnydebug)
05492          ast_debug(1, "Buttontemplate requested\n");
05493 
05494       res = handle_button_template_req_message(req, s);
05495       break;
05496    case VERSION_REQ_MESSAGE:
05497       if (skinnydebug)
05498          ast_debug(1, "Version Request\n");
05499 
05500       res = handle_version_req_message(req, s);
05501       break;
05502    case SERVER_REQUEST_MESSAGE:
05503       if (skinnydebug)
05504          ast_debug(1, "Received Server Request\n");
05505 
05506       res = handle_server_request_message(req, s);
05507       break;
05508    case ALARM_MESSAGE:
05509       res = handle_alarm_message(req, s);
05510       break;
05511    case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
05512       if (skinnydebug)
05513          ast_debug(1, "Received Open Receive Channel Ack\n");
05514 
05515       res = handle_open_receive_channel_ack_message(req, s);
05516       break;
05517    case SOFT_KEY_SET_REQ_MESSAGE:
05518       if (skinnydebug)
05519          ast_debug(1, "Received SoftKeySetReq\n");
05520 
05521       res = handle_soft_key_set_req_message(req, s);
05522       break;
05523    case SOFT_KEY_EVENT_MESSAGE:
05524       res = handle_soft_key_event_message(req, s);
05525       break;
05526    case UNREGISTER_MESSAGE:
05527       if (skinnydebug)
05528          ast_debug(1, "Received Unregister Request\n");
05529 
05530       res = handle_unregister_message(req, s);
05531       break;
05532    case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
05533       if (skinnydebug)
05534          ast_debug(1, "Received SoftKey Template Request\n");
05535 
05536       res = handle_soft_key_template_req_message(req, s);
05537       break;
05538    case HEADSET_STATUS_MESSAGE:
05539       res = handle_headset_status_message(req, s);
05540       break;
05541    case REGISTER_AVAILABLE_LINES_MESSAGE:
05542       res = handle_register_available_lines_message(req, s);
05543       break;
05544    default:
05545       if (skinnydebug)
05546          ast_debug(1, "RECEIVED UNKNOWN MESSAGE TYPE:  %x\n", letohl(req->e));
05547       break;
05548    }
05549    if (res >= 0 && req)
05550       ast_free(req);
05551    return res;
05552 }

static int handle_offhook_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4447 of file chan_skinny.c.

References AST_CONTROL_ANSWER, ast_debug, ast_device_state_changed(), ast_hangup(), ast_log(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, skinny_subchannel::callid, skinny_req::data, errno, find_line_by_instance(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, skinny_device::lastcallreference, skinny_device::lastlineinstance, letohl, LOG_WARNING, ast_channel::name, skinny_device::name, skinny_line::name, skinny_data::offhook, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, s, SKINNY_CONNECTED, SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, skinny_ss(), skinnydebug, start_rtp(), STIMULUS_LINE, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_tone(), offhook_message::unknown1, and offhook_message::unknown2.

Referenced by handle_message().

04448 {
04449    struct skinny_device *d = s->device;
04450    struct skinny_line *l;
04451    struct skinny_subchannel *sub;
04452    struct ast_channel *c;
04453    pthread_t t;
04454    int unknown1;
04455    int unknown2;
04456 
04457    unknown1 = letohl(req->data.offhook.unknown1);
04458    unknown2 = letohl(req->data.offhook.unknown2);
04459 
04460    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04461 
04462    if (!sub) {
04463       l = find_line_by_instance(d, d->lastlineinstance);
04464       if (!l) {
04465          return 0;
04466       }
04467    } else {
04468       l = sub->parent;
04469    }
04470 
04471    transmit_ringer_mode(s, SKINNY_RING_OFF);
04472    l->hookstate = SKINNY_OFFHOOK;
04473 
04474    ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
04475 
04476    if (sub && sub->onhold) {
04477       return 1;
04478    }
04479 
04480    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04481 
04482    if (sub && sub->outgoing) {
04483       /* We're answering a ringing call */
04484       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
04485       transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04486       transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04487       transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
04488       transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
04489       start_rtp(sub);
04490       ast_setstate(sub->owner, AST_STATE_UP);
04491    } else {
04492       if (sub && sub->owner) {
04493          ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
04494       } else {
04495          c = skinny_new(l, AST_STATE_DOWN);
04496          if (c) {
04497             sub = c->tech_pvt;
04498             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04499             if (skinnydebug)
04500                ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04501             transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04502             transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04503             transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK);
04504 
04505             /* start the switch thread */
04506             if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04507                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04508                ast_hangup(c);
04509             }
04510          } else {
04511             ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04512          }
04513       }
04514    }
04515    return 1;
04516 }

static int handle_onhook_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4518 of file chan_skinny.c.

References skinny_subchannel::alreadygone, ast_debug, ast_device_state_changed(), ast_log(), ast_queue_hangup(), attempt_transfer(), skinny_subchannel::callid, skinny_subchannel::cxmode, skinny_req::data, do_housekeeping(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, skinny_device::lastcallreference, skinny_device::lastlineinstance, letohl, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::next, skinny_subchannel::onhold, skinny_data::onhook, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, skinny_subchannel::rtp, s, SKINNY_CX_RECVONLY, SKINNY_ONHOOK, skinnydebug, skinny_line::transfer, transmit_callstate(), onhook_message::unknown1, and onhook_message::unknown2.

Referenced by handle_message().

04519 {
04520    struct skinny_device *d = s->device;
04521    struct skinny_line *l;
04522    struct skinny_subchannel *sub;
04523    int unknown1;
04524    int unknown2;
04525 
04526    unknown1 = letohl(req->data.onhook.unknown1);
04527    unknown2 = letohl(req->data.onhook.unknown2);
04528 
04529    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04530 
04531    if (!sub) {
04532       return 0;
04533    }
04534    l = sub->parent;
04535 
04536    if (l->hookstate == SKINNY_ONHOOK) {
04537       /* Something else already put us back on hook */
04538       return 0;
04539    }
04540    l->hookstate = SKINNY_ONHOOK;
04541 
04542    ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
04543 
04544    if (sub->onhold) {
04545       return 0;
04546    }
04547 
04548    sub->cxmode = SKINNY_CX_RECVONLY;
04549    transmit_callstate(s, l->instance, l->hookstate, sub->callid);
04550    if (skinnydebug)
04551       ast_debug(1, "Skinny %s@%s went on hook\n", l->name, d->name);
04552    if (l->transfer && (sub->owner && sub->next && sub->next->owner) && ((!sub->outgoing) || (sub->next && !sub->next->outgoing))) {
04553       /* We're allowed to transfer, we have two active calls and
04554          we made at least one of the calls.  Let's try and transfer */
04555 
04556 #if 0
04557       if ((res = attempt_transfer(p)) < 0) {
04558          if (sub->next && sub->next->owner) {
04559             sub->next->alreadygone = 1;
04560             ast_queue_hangup(sub->next->owner,1);
04561          }
04562       } else if (res) {
04563          ast_log(LOG_WARNING, "Transfer attempt failed\n");
04564          return 0;
04565       }
04566 #endif
04567    } else {
04568       /* Hangup the current call */
04569       /* If there is another active call, skinny_hangup will ring the phone with the other call */
04570       if (sub->owner) {
04571          sub->alreadygone = 1;
04572          ast_queue_hangup(sub->owner);
04573       } else {
04574          ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
04575             l->name, d->name, sub->callid);
04576       }
04577    }
04578    if ((l->hookstate == SKINNY_ONHOOK) && (sub->next && !sub->next->rtp)) {
04579       do_housekeeping(s);
04580    }
04581    return 1;
04582 }

static int handle_open_receive_channel_ack_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4886 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), ast_debug, ast_inet_ntoa(), ast_log(), ast_rtp_get_us(), ast_rtp_set_peer(), media_qualifier::bitRate, ast_format_list::bits, skinny_subchannel::callid, skinny_line::capability, codec_ast2skinny(), start_media_transmission_message::conferenceId, ast_format_list::cur_ms, skinny_req::data, find_subchannel_by_reference(), htolel, open_receive_channel_ack_message::ipAddr, letohl, LOG_ERROR, skinny_data::openreceivechannelack, skinny_device::ourip, media_qualifier::packets, start_media_transmission_message::packetSize, skinny_subchannel::parent, open_receive_channel_ack_message::passThruId, start_media_transmission_message::passThruPartyId, start_media_transmission_message::payloadType, open_receive_channel_ack_message::port, media_qualifier::precedence, skinny_line::prefs, start_media_transmission_message::qualifier, start_media_transmission_message::remoteIp, start_media_transmission_message::remotePort, req_alloc(), skinny_subchannel::rtp, s, skinnydebug, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, open_receive_channel_ack_message::status, status, transmit_response(), and media_qualifier::vad.

Referenced by handle_message().

04887 {
04888    struct skinny_device *d = s->device;
04889    struct skinny_line *l;
04890    struct skinny_subchannel *sub;
04891    struct ast_format_list fmt;
04892    struct sockaddr_in sin;
04893    struct sockaddr_in us;
04894    uint32_t addr;
04895    int port;
04896    int status;
04897    int passthruid;
04898 
04899    status = letohl(req->data.openreceivechannelack.status);
04900    if (status) {
04901       ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
04902       return 0;
04903    }
04904    addr = letohl(req->data.openreceivechannelack.ipAddr);
04905    port = letohl(req->data.openreceivechannelack.port);
04906    passthruid = letohl(req->data.openreceivechannelack.passThruId);
04907 
04908    sin.sin_family = AF_INET;
04909    sin.sin_addr.s_addr = addr;
04910    sin.sin_port = htons(port);
04911 
04912    sub = find_subchannel_by_reference(d, passthruid);
04913 
04914    if (!sub)
04915       return 0;
04916 
04917    l = sub->parent;
04918 
04919    if (sub->rtp) {
04920       ast_rtp_set_peer(sub->rtp, &sin);
04921       ast_rtp_get_us(sub->rtp, &us);
04922    } else {
04923       ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
04924       return 0;
04925    }
04926 
04927    if (skinnydebug)
04928       ast_debug(1, "ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
04929 
04930    if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
04931       return -1;
04932 
04933    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
04934 
04935    if (skinnydebug)
04936       ast_debug(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
04937 
04938    req->data.startmedia.conferenceId = htolel(sub->callid);
04939    req->data.startmedia.passThruPartyId = htolel(sub->callid);
04940    req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
04941    req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
04942    req->data.startmedia.packetSize = htolel(fmt.cur_ms);
04943    req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
04944    req->data.startmedia.qualifier.precedence = htolel(127);
04945    req->data.startmedia.qualifier.vad = htolel(0);
04946    req->data.startmedia.qualifier.packets = htolel(0);
04947    req->data.startmedia.qualifier.bitRate = htolel(0);
04948    transmit_response(s, req);
04949 
04950    return 1;
04951 }

static int handle_register_available_lines_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5383 of file chan_skinny.c.

Referenced by handle_message().

05384 {
05385    /* XXX I have no clue what this is for, but my phone was sending it, so... */
05386    return 1;
05387 }

static int handle_register_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 3961 of file chan_skinny.c.

References ast_debug, ast_log(), ast_verb, CAPABILITIES_REQ_MESSAGE, skinny_req::data, date_format, register_ack_message::dateTemplate, register_rej_message::errMsg, htolel, keep_alive, register_ack_message::keepAlive, LOG_ERROR, register_message::name, name, skinny_data::reg, skinny_data::regack, REGISTER_ACK_MESSAGE, REGISTER_REJ_MESSAGE, skinny_data::regrej, req_alloc(), register_ack_message::res, skinny_req::res, register_ack_message::res2, s, register_ack_message::secondaryKeepAlive, skinny_register(), skinnydebug, and transmit_response().

Referenced by handle_message().

03962 {
03963    char name[16];
03964    int res;
03965 
03966    memcpy(&name, req->data.reg.name, sizeof(name));
03967 
03968    res = skinny_register(req, s);
03969    if (!res) {
03970       ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
03971       if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
03972          return -1;
03973 
03974       snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
03975       transmit_response(s, req);
03976       return 0;
03977    }
03978    ast_verb(3, "Device '%s' successfully registered\n", name);
03979 
03980    if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
03981       return -1;
03982 
03983    req->data.regack.res[0] = '0';
03984    req->data.regack.res[1] = '\0';
03985    req->data.regack.keepAlive = htolel(keep_alive);
03986    memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
03987    req->data.regack.res2[0] = '0';
03988    req->data.regack.res2[1] = '\0';
03989    req->data.regack.secondaryKeepAlive = htolel(keep_alive);
03990    transmit_response(s, req);
03991    if (skinnydebug)
03992       ast_debug(1, "Requesting capabilities\n");
03993 
03994    if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
03995       return -1;
03996 
03997    transmit_response(s, req);
03998 
03999    return res;
04000 }

static int handle_server_request_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4863 of file chan_skinny.c.

References skinny_req::data, htolel, ourhost, skinny_device::ourip, ourport, req_alloc(), s, server_res_message::server, SERVER_RES_MESSAGE, server_res_message::serverIpAddr, server_res_message::serverListenPort, server_identifier::serverName, skinny_data::serverres, and transmit_response().

Referenced by handle_message().

04864 {
04865    struct skinny_device *d = s->device;
04866    if (!(req = req_alloc(sizeof(struct server_res_message), SERVER_RES_MESSAGE)))
04867       return -1;
04868 
04869    memcpy(req->data.serverres.server[0].serverName, ourhost,
04870          sizeof(req->data.serverres.server[0].serverName));
04871    req->data.serverres.serverListenPort[0] = htolel(ourport);
04872    req->data.serverres.serverIpAddr[0] = htolel(d->ourip.s_addr);
04873    transmit_response(s, req);
04874    return 1;
04875 }

static char* handle_skinny_reset ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2539 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock(), ast_verb, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, complete_skinny_reset(), skinny_req::data, devicelock, devices, skinny_req::e, skinny_device::id, ast_cli_args::line, ast_cli_args::n, skinny_device::name, skinny_device::next, ast_cli_args::pos, req_alloc(), skinny_data::reset, RESET_MESSAGE, reset_message::resetType, skinny_device::session, transmit_response(), and ast_cli_args::word.

02540 {
02541    struct skinny_device *d;
02542    struct skinny_req *req;
02543 
02544    switch (cmd) {
02545    case CLI_INIT:
02546       e->command = "skinny reset";
02547       e->usage =
02548          "Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
02549          "       Causes a Skinny device to reset itself, optionally with a full restart\n";
02550       return NULL;
02551    case CLI_GENERATE:
02552       return complete_skinny_reset(a->line, a->word, a->pos, a->n);
02553    }
02554 
02555    if (a->argc < 3 || a->argc > 4)
02556       return CLI_SHOWUSAGE;
02557 
02558    ast_mutex_lock(&devicelock);
02559 
02560    for (d = devices; d; d = d->next) {
02561       int fullrestart = 0;
02562       if (!strcasecmp(a->argv[2], d->id) || !strcasecmp(a->argv[2], d->name) || !strcasecmp(a->argv[2], "all")) {
02563          if (!(d->session))
02564             continue;
02565 
02566          if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
02567             continue;
02568 
02569          if (a->argc == 4 && !strcasecmp(a->argv[3], "restart"))
02570             fullrestart = 1;
02571 
02572          if (fullrestart)
02573             req->data.reset.resetType = 2;
02574          else
02575             req->data.reset.resetType = 1;
02576 
02577          ast_verb(3, "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id);
02578          transmit_response(d->session, req);
02579       }
02580    }
02581    ast_mutex_unlock(&devicelock);
02582    return CLI_SUCCESS;
02583 }

static char* handle_skinny_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2466 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, skinnydebug, and ast_cli_entry::usage.

02467 {
02468    switch (cmd) {
02469    case CLI_INIT:
02470       e->command = "skinny set debug {on|off}";
02471       e->usage =
02472          "Usage: skinny set debug {on|off}\n"
02473          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02474       return NULL;
02475    case CLI_GENERATE:
02476       return NULL;
02477    }
02478    
02479    if (a->argc != e->args)
02480       return CLI_SHOWUSAGE;
02481 
02482    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
02483       skinnydebug = 1;
02484       ast_cli(a->fd, "Skinny Debugging Enabled\n");
02485       return CLI_SUCCESS;
02486    } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
02487       skinnydebug = 0;
02488       ast_cli(a->fd, "Skinny Debugging Disabled\n");
02489       return CLI_SUCCESS;
02490    } else {
02491       return CLI_SHOWUSAGE;
02492    }
02493 }

static char* handle_skinny_set_debug_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2437 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, skinnydebug, and ast_cli_entry::usage.

02438 {
02439    switch (cmd) {
02440    case CLI_INIT:
02441       e->command = "skinny set debug [off]";
02442       e->usage =
02443          "Usage: skinny set debug [off]\n"
02444          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02445       return NULL;
02446    case CLI_GENERATE:
02447       return NULL;
02448    }
02449    
02450    if (a->argc < 3 || a->argc > 4)
02451       return CLI_SHOWUSAGE;
02452 
02453    if (a->argc == 3) {
02454       skinnydebug = 1;
02455       ast_cli(a->fd, "Skinny Debugging Enabled\n");
02456       return CLI_SUCCESS;
02457    } else if (!strncasecmp(a->argv[3], "off", 3)) {
02458       skinnydebug = 0;
02459       ast_cli(a->fd, "Skinny Debugging Disabled\n");
02460       return CLI_SUCCESS;
02461    } else {
02462       return CLI_SHOWUSAGE;
02463    }
02464 }

static char* handle_skinny_show_device ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Show device information.

Definition at line 2737 of file chan_skinny.c.

References skinny_device::addons, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_skinny_show_device(), device2str(), devicelock, devices, skinny_speeddial::exten, ast_cli_args::fd, skinny_device::id, skinny_speeddial::isHint, skinny_speeddial::label, skinny_line::label, ast_cli_args::line, skinny_device::lines, ast_cli_args::n, skinny_line::name, skinny_device::name, skinny_speeddial::next, skinny_addon::next, skinny_line::next, skinny_device::next, ast_cli_args::pos, skinny_device::registered, S_OR, skinny_device::session, skinnysession::sin, skinny_device::speeddials, skinny_addon::type, skinny_device::type, ast_cli_entry::usage, skinny_device::version_id, and ast_cli_args::word.

02738 {
02739    struct skinny_device *d;
02740    struct skinny_line *l;
02741    struct skinny_speeddial *sd;
02742    struct skinny_addon *sa;
02743 
02744    switch (cmd) {
02745    case CLI_INIT:
02746       e->command = "skinny show device";
02747       e->usage =
02748          "Usage: skinny show device <DeviceId|DeviceName>\n"
02749          "       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
02750       return NULL;
02751    case CLI_GENERATE:
02752       return complete_skinny_show_device(a->line, a->word, a->pos, a->n);
02753    }
02754 
02755    if (a->argc < 4)
02756       return CLI_SHOWUSAGE;
02757 
02758    ast_mutex_lock(&devicelock);
02759    for (d = devices; d; d = d->next) {
02760       if (!strcasecmp(a->argv[3], d->id) || !strcasecmp(a->argv[3], d->name)) {
02761          int numlines = 0, numaddons = 0, numspeeddials = 0;
02762 
02763          for (l = d->lines; l; l = l->next)
02764             numlines++;
02765 
02766          ast_cli(a->fd, "Name:        %s\n", d->name);
02767          ast_cli(a->fd, "Id:          %s\n", d->id);
02768          ast_cli(a->fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
02769          ast_cli(a->fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
02770          ast_cli(a->fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
02771          ast_cli(a->fd, "Device Type: %s\n", device2str(d->type));
02772          ast_cli(a->fd, "Registered:  %s\n", (d->registered ? "Yes" : "No"));
02773          ast_cli(a->fd, "Lines:       %d\n", numlines);
02774          for (l = d->lines; l; l = l->next)
02775             ast_cli(a->fd, "  %s (%s)\n", l->name, l->label);
02776          for (sa = d->addons; sa; sa = sa->next)
02777             numaddons++;
02778          ast_cli(a->fd, "Addons:      %d\n", numaddons);
02779          for (sa = d->addons; sa; sa = sa->next)
02780             ast_cli(a->fd, "  %s\n", sa->type);
02781          for (sd = d->speeddials; sd; sd = sd->next)
02782             numspeeddials++;
02783          ast_cli(a->fd, "Speeddials:  %d\n", numspeeddials);
02784          for (sd = d->speeddials; sd; sd = sd->next)
02785             ast_cli(a->fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
02786       }
02787    }
02788    ast_mutex_unlock(&devicelock);
02789    return CLI_SUCCESS;
02790 }

static char* handle_skinny_show_devices ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2692 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, device2str(), devicelock, devices, ast_cli_args::fd, skinny_device::id, skinny_device::lines, skinny_device::name, skinny_line::next, skinny_device::next, skinny_device::registered, skinny_device::session, skinnysession::sin, skinny_device::type, and ast_cli_entry::usage.

02693 {
02694    struct skinny_device *d;
02695    struct skinny_line *l;
02696 
02697    switch (cmd) {
02698    case CLI_INIT:
02699       e->command = "skinny show devices";
02700       e->usage =
02701          "Usage: skinny show devices\n"
02702          "       Lists all devices known to the Skinny subsystem.\n";
02703       return NULL;
02704    case CLI_GENERATE:
02705       return NULL;
02706    }
02707 
02708    if (a->argc != 3)
02709       return CLI_SHOWUSAGE;
02710 
02711    ast_mutex_lock(&devicelock);
02712 
02713    ast_cli(a->fd, "Name                 DeviceId         IP              Type            R NL\n");
02714    ast_cli(a->fd, "-------------------- ---------------- --------------- --------------- - --\n");
02715 
02716    for (d = devices; d; d = d->next) {
02717       int numlines = 0;
02718 
02719       for (l = d->lines; l; l = l->next)
02720          numlines++;
02721       
02722       ast_cli(a->fd, "%-20s %-16s %-15s %-15s %c %2d\n",
02723          d->name,
02724          d->id,
02725          d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
02726          device2str(d->type),
02727          d->registered?'Y':'N',
02728          numlines);
02729    }
02730 
02731    ast_mutex_unlock(&devicelock);
02732 
02733    return CLI_SUCCESS;
02734 }

static char* handle_skinny_show_line ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

List line information.

Definition at line 2830 of file chan_skinny.c.

References skinny_line::accountcode, skinny_line::amaflags, ast_cli_args::argc, ast_cli_args::argv, ast_cdr_flags2str(), ast_cli(), ast_getformatname_multiple(), ast_mutex_lock(), ast_print_group(), skinny_line::call_forward_all, skinny_line::call_forward_busy, skinny_line::call_forward_noanswer, skinny_line::callgroup, skinny_line::callwaiting, skinny_line::cancallforward, skinny_line::capability, skinny_line::cfwdtype, skinny_line::cid_name, skinny_line::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_skinny_show_line(), skinny_line::context, devicelock, devices, skinny_line::dnd, skinny_line::exten, ast_cli_args::fd, skinny_line::group, skinny_line::hidecallerid, skinny_device::id, skinny_line::immediate, skinny_line::label, skinny_line::language, skinny_line::lastcallerid, skinny_line::lastnumberdialed, ast_cli_args::line, skinny_device::lines, skinny_line::mailbox, skinny_line::mohinterpret, skinny_line::mohsuggest, skinny_line::mwiblink, ast_cli_args::n, skinny_line::name, skinny_device::name, skinny_line::nat, skinny_line::next, skinny_device::next, skinny_line::pickupgroup, ast_cli_args::pos, skinny_line::prefs, print_codec_to_cli(), skinny_line::regcontext, skinny_line::regexten, S_COR, S_OR, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, skinny_line::threewaycalling, skinny_line::transfer, ast_cli_entry::usage, skinny_line::vmexten, and ast_cli_args::word.

02831 {
02832    struct skinny_device *d;
02833    struct skinny_line *l;
02834    char codec_buf[512];
02835    char group_buf[256];
02836 
02837    switch (cmd) {
02838    case CLI_INIT:
02839       e->command = "skinny show line";
02840       e->usage =
02841          "Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
02842          "       List all lineinformation of a specific line known to the Skinny subsystem.\n";
02843       return NULL;
02844    case CLI_GENERATE:
02845       return complete_skinny_show_line(a->line, a->word, a->pos, a->n);
02846    }
02847 
02848    if (a->argc < 4)
02849       return CLI_SHOWUSAGE;
02850    
02851    ast_mutex_lock(&devicelock);
02852 
02853    /* Show all lines matching the one supplied */
02854    for (d = devices; d; d = d->next) {
02855       if (a->argc == 6 && (strcasecmp(a->argv[5], d->id) && strcasecmp(a->argv[5], d->name)))
02856          continue;
02857       for (l = d->lines; l; l = l->next) {
02858          if (strcasecmp(a->argv[3], l->name))
02859             continue;
02860          ast_cli(a->fd, "Line:             %s\n", l->name);
02861          ast_cli(a->fd, "On Device:        %s\n", d->name);
02862          ast_cli(a->fd, "Line Label:       %s\n", l->label);
02863          ast_cli(a->fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
02864          ast_cli(a->fd, "Context:          %s\n", l->context);
02865          ast_cli(a->fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
02866          ast_cli(a->fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
02867          ast_cli(a->fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
02868          ast_cli(a->fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
02869          ast_cli(a->fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
02870          ast_cli(a->fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
02871          ast_cli(a->fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
02872          ast_cli(a->fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
02873          ast_cli(a->fd, "CFwdAll:          %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
02874          ast_cli(a->fd, "CFwdBusy:         %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
02875          ast_cli(a->fd, "CFwdNoAnswer:     %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
02876          ast_cli(a->fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
02877          ast_cli(a->fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
02878          ast_cli(a->fd, "MWIblink:         %d\n", l->mwiblink);
02879          ast_cli(a->fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
02880          ast_cli(a->fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
02881          ast_cli(a->fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
02882          ast_cli(a->fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
02883          ast_cli(a->fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
02884          ast_cli(a->fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
02885          ast_cli(a->fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
02886          ast_cli(a->fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
02887          ast_cli(a->fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
02888          ast_cli(a->fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
02889          ast_cli(a->fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
02890          ast_cli(a->fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
02891          ast_cli(a->fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
02892          ast_cli(a->fd, "Group:            %d\n", l->group);
02893          ast_cli(a->fd, "Codecs:           ");
02894          ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->capability);
02895          ast_cli(a->fd, "%s\n", codec_buf);
02896          ast_cli(a->fd, "Codec Order:      (");
02897          print_codec_to_cli(a->fd, &l->prefs);
02898          ast_cli(a->fd, ")\n");
02899          ast_cli(a->fd, "\n");
02900       }
02901    }
02902    
02903    ast_mutex_unlock(&devicelock);
02904    return CLI_SUCCESS;
02905 }

static char* handle_skinny_show_lines ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2792 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli(), ast_mutex_lock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, devicelock, devices, ast_cli_args::fd, skinny_line::instance, skinny_line::label, skinny_device::lines, skinny_line::name, skinny_device::name, skinny_line::next, skinny_device::next, and ast_cli_entry::usage.

02793 {
02794    struct skinny_device *d;
02795    struct skinny_line *l;
02796 
02797    switch (cmd) {
02798    case CLI_INIT:
02799       e->command = "skinny show lines";
02800       e->usage =
02801          "Usage: skinny show lines\n"
02802          "       Lists all lines known to the Skinny subsystem.\n";
02803       return NULL;
02804    case CLI_GENERATE:
02805       return NULL;
02806    }
02807 
02808    if (a->argc != 3)
02809       return CLI_SHOWUSAGE;
02810    
02811    ast_mutex_lock(&devicelock);
02812    
02813    ast_cli(a->fd, "Device Name          Instance Name                 Label               \n");
02814    ast_cli(a->fd, "-------------------- -------- -------------------- --------------------\n");
02815    for (d = devices; d; d = d->next) {
02816       for (l = d->lines; l; l = l->next) {
02817          ast_cli(a->fd, "%-20s %8d %-20s %-20s\n",
02818             d->name,
02819             l->instance,
02820             l->name,
02821             l->label);
02822       }
02823    }
02824    
02825    ast_mutex_unlock(&devicelock);
02826    return CLI_SUCCESS;
02827 }

static char* handle_skinny_show_settings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

List global settings for the Skinny subsystem.

Definition at line 2908 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, ast_test_flag, bindaddr, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, date_format, ast_cli_args::fd, global_jbconf, ast_jb_conf::impl, keep_alive, ast_jb_conf::max_size, regcontext, ast_jb_conf::resync_threshold, S_OR, ast_cli_entry::usage, and vmexten.

02909 {
02910    switch (cmd) {
02911    case CLI_INIT:
02912       e->command = "skinny show settings";
02913       e->usage =
02914          "Usage: skinny show settings\n"
02915          "       Lists all global configuration settings of the Skinny subsystem.\n";
02916       return NULL;
02917    case CLI_GENERATE:
02918       return NULL;
02919    }  
02920 
02921    if (a->argc != 3)
02922       return CLI_SHOWUSAGE;
02923 
02924    ast_cli(a->fd, "\nGlobal Settings:\n");
02925    ast_cli(a->fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
02926    ast_cli(a->fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
02927    ast_cli(a->fd, "  KeepAlive:              %d\n", keep_alive);
02928    ast_cli(a->fd, "  Date Format:            %s\n", date_format);
02929    ast_cli(a->fd, "  Voice Mail Extension:   %s\n", S_OR(vmexten, "(not set)"));
02930    ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
02931    ast_cli(a->fd, "  Jitterbuffer enabled:   %s\n", (ast_test_flag(&global_jbconf, AST_JB_ENABLED) ? "Yes" : "No"));
02932    ast_cli(a->fd, "  Jitterbuffer forced:    %s\n", (ast_test_flag(&global_jbconf, AST_JB_FORCED) ? "Yes" : "No"));
02933    ast_cli(a->fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
02934    ast_cli(a->fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
02935    ast_cli(a->fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
02936    ast_cli(a->fd, "  Jitterbuffer log:       %s\n", (ast_test_flag(&global_jbconf, AST_JB_LOG) ? "Yes" : "No"));
02937 
02938    return CLI_SUCCESS;
02939 }

static int handle_soft_key_event_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5035 of file chan_skinny.c.

References skinny_subchannel::alreadygone, AST_CONTROL_ANSWER, ast_copy_string(), ast_debug, ast_device_state_changed(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_pthread_create, ast_queue_control(), ast_queue_hangup(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_verb, attempt_transfer(), skinny_subchannel::callid, soft_key_event_message::callreference, ast_channel::context, skinny_subchannel::cxmode, skinny_req::data, skinny_line::dnd, do_housekeeping(), errno, ast_channel::exten, find_line_by_instance(), find_subchannel_by_instance_reference(), handle_callforward_button(), skinny_line::hookstate, skinny_line::instance, soft_key_event_message::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_RINGOUT, skinny_device::lastcallreference, skinny_device::lastlineinstance, skinny_line::lastnumberdialed, letohl, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::next, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::rtp, s, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_CONNECTED, SKINNY_CX_RECVONLY, SKINNY_DIALTONE, skinny_hold(), SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), skinny_unhold(), skinnydebug, SOFTKEY_ANSWER, SOFTKEY_BKSPC, SOFTKEY_CFWDALL, SOFTKEY_CFWDBUSY, SOFTKEY_CFWDNOANSWER, SOFTKEY_CONFRN, SOFTKEY_DND, SOFTKEY_ENDCALL, SOFTKEY_GPICKUP, SOFTKEY_HOLD, SOFTKEY_INFO, SOFTKEY_JOIN, SOFTKEY_MEETME, SOFTKEY_NEWCALL, SOFTKEY_NONE, SOFTKEY_PARK, SOFTKEY_PICKUP, SOFTKEY_REDIAL, SOFTKEY_RESUME, SOFTKEY_TRNSFER, soft_key_event_message::softKeyEvent, skinny_data::softkeyeventmessage, start_rtp(), STIMULUS_DND, STIMULUS_LINE, ast_channel::tech_pvt, skinny_line::transfer, transmit_callstate(), transmit_displaymessage(), transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

Referenced by handle_message().

05036 {
05037    struct skinny_device *d = s->device;
05038    struct skinny_line *l;
05039    struct skinny_subchannel *sub = NULL;
05040    struct ast_channel *c;
05041    pthread_t t;
05042    int event;
05043    int instance;
05044    int callreference;
05045 
05046    event = letohl(req->data.softkeyeventmessage.softKeyEvent);
05047    instance = letohl(req->data.softkeyeventmessage.instance);
05048    callreference = letohl(req->data.softkeyeventmessage.callreference);
05049 
05050    if (instance) {
05051       l = find_line_by_instance(d, instance);
05052       if (callreference) {
05053          sub = find_subchannel_by_instance_reference(d, instance, callreference);
05054       } else {
05055          sub = find_subchannel_by_instance_reference(d, instance, d->lastcallreference);
05056       }
05057    } else {
05058       l = find_line_by_instance(d, d->lastlineinstance);
05059    }
05060 
05061    if (!l) {
05062       if (skinnydebug)
05063          ast_debug(1, "Received Softkey Event: %d(%d/%d)\n", event, instance, callreference);
05064       return 0;
05065    }
05066 
05067    ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
05068 
05069    switch(event) {
05070    case SOFTKEY_NONE:
05071       if (skinnydebug)
05072          ast_debug(1, "Received Softkey Event: None(%d/%d)\n", instance, callreference);
05073       break;
05074    case SOFTKEY_REDIAL:
05075       if (skinnydebug)
05076          ast_debug(1, "Received Softkey Event: Redial(%d/%d)\n", instance, callreference);
05077 
05078       if (ast_strlen_zero(l->lastnumberdialed)) {
05079          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
05080          l->hookstate = SKINNY_ONHOOK;
05081          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
05082          transmit_callstate(s, l->instance, SKINNY_ONHOOK, instance);
05083          break;
05084       }
05085 
05086       if (!sub || !sub->owner) {
05087          c = skinny_new(l, AST_STATE_DOWN);
05088       } else {
05089          c = sub->owner;
05090       }
05091 
05092       if (!c) {
05093          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05094       } else {
05095          sub = c->tech_pvt;
05096          if (l->hookstate == SKINNY_ONHOOK) {
05097             l->hookstate = SKINNY_OFFHOOK;
05098             transmit_speaker_mode(s, SKINNY_SPEAKERON);
05099             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
05100          }
05101          if (skinnydebug)
05102             ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05103          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
05104          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
05105          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
05106 
05107          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
05108             transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
05109          }
05110          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
05111          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05112             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05113             ast_hangup(c);
05114          }
05115       }
05116       break;
05117    case SOFTKEY_NEWCALL:  /* Actually the DIAL softkey */
05118       if (skinnydebug)
05119          ast_debug(1, "Received Softkey Event: New Call(%d/%d)\n", instance, callreference);
05120 
05121       if (!sub || !sub->owner) {
05122          c = skinny_new(l, AST_STATE_DOWN);
05123       } else {
05124          c = sub->owner;
05125       }
05126 
05127       /* transmit_ringer_mode(s,SKINNY_RING_OFF);
05128       transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON); */
05129 
05130       /* l->hookstate = SKINNY_OFFHOOK; */
05131 
05132       if (!c) {
05133          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05134       } else {
05135          sub = c->tech_pvt;
05136          if (l->hookstate == SKINNY_ONHOOK) {
05137             l->hookstate = SKINNY_OFFHOOK;
05138             transmit_speaker_mode(s, SKINNY_SPEAKERON);
05139             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
05140          }
05141 
05142          if (skinnydebug)
05143             ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05144          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
05145          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
05146          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK);
05147 
05148          /* start the switch thread */
05149          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05150             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05151             ast_hangup(c);
05152          }
05153       }
05154       break;
05155    case SOFTKEY_HOLD:
05156       if (skinnydebug)
05157          ast_debug(1, "Received Softkey Event: Hold(%d/%d)\n", instance, callreference);
05158 
05159       if (sub) {
05160          if (sub->onhold) {
05161             skinny_unhold(sub);
05162          } else {
05163             skinny_hold(sub);
05164          }
05165       }
05166             
05167       break;
05168    case SOFTKEY_TRNSFER:
05169       if (skinnydebug)
05170          ast_debug(1, "Received Softkey Event: Transfer(%d/%d)\n", instance, callreference);
05171       /* XXX figure out how to transfer */
05172       break;
05173    case SOFTKEY_DND:
05174       if (skinnydebug)
05175          ast_debug(1, "Received Softkey Event: DND(%d/%d)\n", instance, callreference);
05176 
05177       /* Do not disturb */
05178       if (l->dnd != 0){
05179          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
05180          l->dnd = 0;
05181          transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_ON);
05182          transmit_displaynotify(s, "DnD disabled", 10);
05183       } else {
05184          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
05185          l->dnd = 1;
05186          transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
05187          transmit_displaynotify(s, "DnD enabled", 10);
05188       }
05189       break;
05190    case SOFTKEY_CFWDALL:
05191       if (skinnydebug)
05192          ast_debug(1, "Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
05193 
05194       if (!sub || !sub->owner) {
05195          c = skinny_new(l, AST_STATE_DOWN);
05196       } else {
05197          c = sub->owner;
05198       }
05199 
05200       if (!c) {
05201          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05202       } else {
05203          sub = c->tech_pvt;
05204          handle_callforward_button(sub, SKINNY_CFWD_ALL);
05205       }
05206       break;
05207    case SOFTKEY_CFWDBUSY:
05208       if (skinnydebug)
05209          ast_debug(1, "Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
05210 
05211       if (!sub || !sub->owner) {
05212          c = skinny_new(l, AST_STATE_DOWN);
05213       } else {
05214          c = sub->owner;
05215       }
05216 
05217       if (!c) {
05218          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05219       } else {
05220          sub = c->tech_pvt;
05221          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
05222       }
05223       break;
05224    case SOFTKEY_CFWDNOANSWER:
05225       if (skinnydebug)
05226          ast_debug(1, "Received Softkey Event: Forward No Answer (%d/%d)\n", instance, callreference);
05227 
05228 #if 0 /* Not sure how to handle this yet */
05229       if (!sub || !sub->owner) {
05230          c = skinny_new(l, AST_STATE_DOWN);
05231       } else {
05232          c = sub->owner;
05233       }
05234 
05235       if (!c) {
05236          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05237       } else {
05238          sub = c->tech_pvt;
05239          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
05240       }
05241 #endif
05242       break;
05243    case SOFTKEY_BKSPC:
05244       if (skinnydebug)
05245          ast_debug(1, "Received Softkey Event: Backspace(%d/%d)\n", instance, callreference);
05246       break;
05247    case SOFTKEY_ENDCALL:
05248       if (skinnydebug)
05249          ast_debug(1, "Received Softkey Event: End Call(%d/%d)\n", instance, callreference);
05250 
05251       if (l->hookstate == SKINNY_ONHOOK) {
05252          /* Something else already put us back on hook */
05253          break;
05254       }
05255       if (sub) {
05256          sub->cxmode = SKINNY_CX_RECVONLY;
05257          l->hookstate = SKINNY_ONHOOK;
05258          transmit_callstate(s, l->instance, l->hookstate, sub->callid);
05259          if (skinnydebug)
05260             ast_debug(1, "Skinny %s@%s went on hook\n", l->name, d->name);
05261          if (l->transfer && (sub->owner && sub->next && sub->next->owner) && ((!sub->outgoing) || (sub->next && !sub->next->outgoing))) {
05262             /* We're allowed to transfer, we have two active calls and
05263                we made at least one of the calls.  Let's try and transfer */
05264 
05265 #if 0
05266             if ((res = attempt_transfer(p)) < 0) {
05267                if (sub->next && sub->next->owner) {
05268                   sub->next->alreadygone = 1;
05269                   ast_queue_hangup(sub->next->owner, 1);
05270                }
05271             } else if (res) {
05272                ast_log(LOG_WARNING, "Transfer attempt failed\n");
05273                break;
05274             }
05275 #endif
05276          } else {
05277             /* Hangup the current call */
05278             /* If there is another active call, skinny_hangup will ring the phone with the other call */
05279             if (sub->owner) {
05280                sub->alreadygone = 1;
05281                ast_queue_hangup(sub->owner);
05282             } else {
05283                ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
05284                   l->name, d->name, sub->callid);
05285             }
05286          }
05287          if ((l->hookstate == SKINNY_ONHOOK) && (sub->next && !sub->next->rtp)) {
05288             do_housekeeping(s);
05289          }
05290       }
05291       break;
05292    case SOFTKEY_RESUME:
05293       if (skinnydebug)
05294          ast_debug(1, "Received Softkey Event: Resume(%d/%d)\n", instance, callreference);
05295       break;
05296    case SOFTKEY_ANSWER:
05297       if (skinnydebug)
05298          ast_debug(1, "Received Softkey Event: Answer(%d/%d)\n", instance, callreference);
05299 
05300       transmit_ringer_mode(s,SKINNY_RING_OFF);
05301       transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05302 
05303       l->hookstate = SKINNY_OFFHOOK;
05304 
05305       if (sub && sub->outgoing) {
05306          /* We're answering a ringing call */
05307          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05308          transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
05309          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
05310          transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
05311          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
05312          start_rtp(sub);
05313          ast_setstate(sub->owner, AST_STATE_UP);
05314       }
05315       break;
05316    case SOFTKEY_INFO:
05317       if (skinnydebug)
05318          ast_debug(1, "Received Softkey Event: Info(%d/%d)\n", instance, callreference);
05319       break;
05320    case SOFTKEY_CONFRN:
05321       if (skinnydebug)
05322          ast_debug(1, "Received Softkey Event: Conference(%d/%d)\n", instance, callreference);
05323       /* XXX determine the best way to pull off a conference.  Meetme? */
05324       break;
05325    case SOFTKEY_PARK:
05326       if (skinnydebug)
05327          ast_debug(1, "Received Softkey Event: Park Call(%d/%d)\n", instance, callreference);
05328       /* XXX Park the call */
05329       break;
05330    case SOFTKEY_JOIN:
05331       if (skinnydebug)
05332          ast_debug(1, "Received Softkey Event: Join(%d/%d)\n", instance, callreference);
05333       break;
05334    case SOFTKEY_MEETME:
05335       /* XXX How is this different from CONFRN? */
05336       if (skinnydebug)
05337          ast_debug(1, "Received Softkey Event: Meetme(%d/%d)\n", instance, callreference);
05338       break;
05339    case SOFTKEY_PICKUP:
05340       if (skinnydebug)
05341          ast_debug(1, "Received Softkey Event: Pickup(%d/%d)\n", instance, callreference);
05342       break;
05343    case SOFTKEY_GPICKUP:
05344       if (skinnydebug)
05345          ast_debug(1, "Received Softkey Event: Group Pickup(%d/%d)\n", instance, callreference);
05346       break;
05347    default:
05348       if (skinnydebug)
05349          ast_debug(1, "Received unknown Softkey Event: %d(%d/%d)\n", event, instance, callreference);
05350       break;
05351    }
05352    ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
05353 
05354    return 1;
05355 }

static int handle_soft_key_set_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5003 of file chan_skinny.c.

References soft_key_definitions::count, skinny_req::data, soft_key_definitions::defaults, htolel, KEYDEF_ONHOOK, soft_key_definitions::mode, req_alloc(), s, soft_key_default_definitions, SOFT_KEY_SET_RES_MESSAGE, soft_key_template_default, soft_key_set_definition::softKeyInfoIndex, soft_key_set_res_message::softKeySetCount, soft_key_set_res_message::softKeySetDefinition, soft_key_set_res_message::softKeySetOffset, skinny_data::softkeysets, soft_key_set_res_message::totalSoftKeySetCount, transmit_response(), and transmit_selectsoftkeys().

Referenced by handle_message().

05004 {
05005    int i;
05006    int x;
05007    int y;
05008    const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
05009 
05010    if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
05011       return -1;
05012 
05013    req->data.softkeysets.softKeySetOffset = htolel(0);
05014    req->data.softkeysets.softKeySetCount = htolel(11);
05015    req->data.softkeysets.totalSoftKeySetCount = htolel(11);
05016    for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
05017       const uint8_t *defaults = softkeymode->defaults;
05018       /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
05019          This will have to do for now. */
05020       for (y = 0; y < softkeymode->count; y++) {
05021          for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
05022             if (defaults[y] == i+1) {
05023                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = htolel(i+1);
05024                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htolel(i+301);
05025             }
05026          }
05027       }
05028       softkeymode++;
05029    }
05030    transmit_response(s,req);
05031    transmit_selectsoftkeys(s, 0, 0, KEYDEF_ONHOOK);
05032    return 1;
05033 }

static int handle_soft_key_template_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5362 of file chan_skinny.c.

References skinny_req::data, htolel, req_alloc(), s, soft_key_template_default, SOFT_KEY_TEMPLATE_RES_MESSAGE, soft_key_template_res_message::softKeyCount, soft_key_template_res_message::softKeyOffset, skinny_data::softkeytemplate, soft_key_template_res_message::softKeyTemplateDefinition, soft_key_template_res_message::totalSoftKeyCount, and transmit_response().

Referenced by handle_message().

05363 {
05364    if (!(req = req_alloc(sizeof(struct soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
05365       return -1;
05366 
05367    req->data.softkeytemplate.softKeyOffset = htolel(0);
05368    req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
05369    req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
05370    memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
05371       soft_key_template_default,
05372       sizeof(soft_key_template_default));
05373    transmit_response(s,req);
05374    return 1;
05375 }

static int handle_speed_dial_stat_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4619 of file chan_skinny.c.

References ast_copy_string(), skinny_req::data, skinny_speeddial::exten, find_speeddial_by_instance(), htolel, skinny_speeddial::instance, skinny_speeddial::label, letohl, req_alloc(), s, SPEED_DIAL_STAT_RES_MESSAGE, skinny_data::speeddial, speed_dial_stat_res_message::speedDialDirNumber, speed_dial_stat_res_message::speedDialDisplayName, speed_dial_stat_req_message::speedDialNumber, skinny_data::speeddialreq, and transmit_response().

Referenced by handle_message().

04620 {
04621    struct skinny_device *d = s->device;
04622    struct skinny_speeddial *sd;
04623    int instance;
04624 
04625    instance = letohl(req->data.speeddialreq.speedDialNumber);
04626 
04627    sd = find_speeddial_by_instance(d, instance, 0);
04628 
04629    if (!sd) {
04630       return 0;
04631    }
04632 
04633    if (!(req = req_alloc(sizeof(struct speed_dial_stat_res_message), SPEED_DIAL_STAT_RES_MESSAGE)))
04634       return -1;
04635 
04636    req->data.speeddialreq.speedDialNumber = htolel(instance);
04637    ast_copy_string(req->data.speeddial.speedDialDirNumber, sd->exten, sizeof(req->data.speeddial.speedDialDirNumber));
04638    ast_copy_string(req->data.speeddial.speedDialDisplayName, sd->label, sizeof(req->data.speeddial.speedDialDisplayName));
04639 
04640    transmit_response(s, req);
04641    return 1;
04642 }

static int handle_stimulus_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4117 of file chan_skinny.c.

References AST_CONTROL_ANSWER, ast_copy_string(), ast_debug, ast_device_state_changed(), ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::callid, stimulus_message::callreference, skinny_line::cid_num, ast_channel::context, skinny_req::data, skinny_line::dnd, errno, skinny_speeddial::exten, ast_channel::exten, find_line_by_instance(), find_speeddial_by_instance(), find_subchannel_by_instance_reference(), handle_callforward_button(), skinny_line::hookstate, skinny_line::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_RINGOUT, skinny_device::lastcallreference, skinny_device::lastlineinstance, skinny_line::lastnumberdialed, letohl, LOG_WARNING, ast_channel::name, skinny_device::name, skinny_line::name, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, s, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_CONNECTED, SKINNY_DIALTONE, skinny_hold(), SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), skinny_unhold(), skinnydebug, start_rtp(), stimulus_message::stimulus, skinny_data::stimulus, STIMULUS_CALLPARK, STIMULUS_CONFERENCE, STIMULUS_DISPLAY, STIMULUS_DND, STIMULUS_FORWARDALL, STIMULUS_FORWARDBUSY, STIMULUS_FORWARDNOANSWER, STIMULUS_HOLD, STIMULUS_LINE, STIMULUS_REDIAL, STIMULUS_SPEEDDIAL, STIMULUS_TRANSFER, STIMULUS_VOICEMAIL, stimulus_message::stimulusInstance, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_tone(), vmexten, and skinny_line::vmexten.

Referenced by handle_message().

04118 {
04119    struct skinny_device *d = s->device;
04120    struct skinny_line *l;
04121    struct skinny_subchannel *sub;
04122    /*struct skinny_speeddial *sd;*/
04123    struct ast_channel *c;
04124    pthread_t t;
04125    int event;
04126    int instance;
04127    int callreference;
04128    /*int res = 0;*/
04129 
04130    event = letohl(req->data.stimulus.stimulus);
04131    instance = letohl(req->data.stimulus.stimulusInstance);
04132    callreference = letohl(req->data.stimulus.callreference); 
04133    if (skinnydebug)
04134       ast_debug(1, "callreference in handle_stimulus_message is '%d'\n", callreference);
04135 
04136    /*  Note that this call should be using the passed in instance and callreference */
04137    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04138 
04139    if (!sub) {
04140       l = find_line_by_instance(d, d->lastlineinstance);
04141       if (!l) {
04142          return 0;
04143       }
04144    } else {
04145       l = sub->parent;
04146    }
04147 
04148    switch(event) {
04149    case STIMULUS_REDIAL:
04150       if (skinnydebug)
04151          ast_debug(1, "Received Stimulus: Redial(%d/%d)\n", instance, callreference);
04152 
04153       if (ast_strlen_zero(l->lastnumberdialed)) {
04154          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
04155          l->hookstate = SKINNY_ONHOOK;
04156          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
04157          transmit_callstate(s, l->instance, SKINNY_ONHOOK, instance);
04158          break;
04159       }
04160 
04161       c = skinny_new(l, AST_STATE_DOWN);
04162       if (!c) {
04163          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04164       } else {
04165          sub = c->tech_pvt;
04166          l = sub->parent;
04167          if (l->hookstate == SKINNY_ONHOOK) {
04168             l->hookstate = SKINNY_OFFHOOK;
04169             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04170          }
04171          if (skinnydebug)
04172             ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04173          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04174          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04175          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
04176 
04177          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
04178             transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04179          }
04180          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
04181          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04182             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04183             ast_hangup(c);
04184          }
04185       }
04186       break;
04187    case STIMULUS_SPEEDDIAL:
04188        {
04189       struct skinny_speeddial *sd;
04190 
04191       if (skinnydebug)
04192          ast_debug(1, "Received Stimulus: SpeedDial(%d/%d)\n", instance, callreference);
04193       if (!(sd = find_speeddial_by_instance(d, instance, 0))) {
04194          return 0;
04195       }
04196 
04197       if (!sub || !sub->owner)
04198          c = skinny_new(l, AST_STATE_DOWN);
04199       else
04200          c = sub->owner;
04201 
04202       if (!c) {
04203          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04204       } else {
04205          sub = c->tech_pvt;
04206          l = sub->parent;
04207          if (l->hookstate == SKINNY_ONHOOK) {
04208             l->hookstate = SKINNY_OFFHOOK;
04209             transmit_speaker_mode(s, SKINNY_SPEAKERON);
04210             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04211          }
04212          if (skinnydebug)
04213             ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04214          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04215          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04216          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
04217 
04218          if (!ast_ignore_pattern(c->context, sd->exten)) {
04219             transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04220          }
04221          if (ast_exists_extension(c, c->context, sd->exten, 1, l->cid_num)) {
04222             ast_copy_string(c->exten, sd->exten, sizeof(c->exten));
04223             ast_copy_string(l->lastnumberdialed, sd->exten, sizeof(l->lastnumberdialed));
04224 
04225             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04226                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04227                ast_hangup(c);
04228             }
04229             break;
04230          }
04231       }
04232        }
04233       break;
04234    case STIMULUS_HOLD:
04235       if (skinnydebug)
04236          ast_debug(1, "Received Stimulus: Hold(%d/%d)\n", instance, callreference);
04237 
04238       if (!sub)
04239          break;
04240 
04241       if (sub->onhold) {
04242          skinny_unhold(sub);
04243       } else {
04244          skinny_hold(sub);
04245       }
04246       break;
04247    case STIMULUS_TRANSFER:
04248       if (skinnydebug)
04249          ast_debug(1, "Received Stimulus: Transfer(%d/%d)\n", instance, callreference);
04250       /* XXX figure out how to transfer */
04251       break;
04252    case STIMULUS_CONFERENCE:
04253       if (skinnydebug)
04254          ast_debug(1, "Received Stimulus: Conference(%d/%d)\n", instance, callreference);
04255       /* XXX determine the best way to pull off a conference.  Meetme? */
04256       break;
04257    case STIMULUS_VOICEMAIL:
04258       if (skinnydebug)
04259          ast_debug(1, "Received Stimulus: Voicemail(%d/%d)\n", instance, callreference);
04260 
04261       if (!sub || !sub->owner) {
04262          c = skinny_new(l, AST_STATE_DOWN);
04263       } else {
04264          c = sub->owner;
04265       }
04266       if (!c) {
04267          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04268       } else {
04269          sub = c->tech_pvt;
04270          l = sub->parent;
04271 
04272          if (ast_strlen_zero(l->vmexten))  /* Exit the call if no VM pilot */
04273             break;
04274 
04275          if (l->hookstate == SKINNY_ONHOOK){
04276             l->hookstate = SKINNY_OFFHOOK;
04277             transmit_speaker_mode(s, SKINNY_SPEAKERON);
04278             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04279          }
04280 
04281          if (skinnydebug)
04282             ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04283 
04284          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04285          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04286          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
04287 
04288          if (!ast_ignore_pattern(c->context, vmexten)) {
04289             transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04290          }
04291 
04292          if (ast_exists_extension(c, c->context, l->vmexten, 1, l->cid_num)) {
04293             ast_copy_string(c->exten, l->vmexten, sizeof(c->exten));
04294             ast_copy_string(l->lastnumberdialed, l->vmexten, sizeof(l->lastnumberdialed));
04295             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04296                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04297                ast_hangup(c);
04298             }
04299             break;
04300          }
04301       }
04302       break;
04303    case STIMULUS_CALLPARK:
04304       if (skinnydebug)
04305          ast_debug(1, "Received Stimulus: Park Call(%d/%d)\n", instance, callreference);
04306       /* XXX Park the call */
04307       break;
04308    case STIMULUS_DND:
04309       if (skinnydebug)
04310          ast_debug(1, "Received Stimulus: DND (%d/%d)\n", instance, callreference);
04311 
04312       /* Do not disturb */
04313       if (l->dnd != 0){
04314          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
04315          l->dnd = 0;
04316          transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_ON);
04317          transmit_displaynotify(s, "DnD disabled", 10);
04318       } else {
04319          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
04320          l->dnd = 1;
04321          transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
04322          transmit_displaynotify(s, "DnD enabled", 10);
04323       }
04324       break;
04325    case STIMULUS_FORWARDALL:
04326       if (skinnydebug)
04327          ast_debug(1, "Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
04328 
04329       if (!sub || !sub->owner) {
04330          c = skinny_new(l, AST_STATE_DOWN);
04331       } else {
04332          c = sub->owner;
04333       }
04334 
04335       if (!c) {
04336          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04337       } else {
04338          sub = c->tech_pvt;
04339          handle_callforward_button(sub, SKINNY_CFWD_ALL);
04340       }
04341       break;
04342    case STIMULUS_FORWARDBUSY:
04343       if (skinnydebug)
04344          ast_debug(1, "Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
04345 
04346       if (!sub || !sub->owner) {
04347          c = skinny_new(l, AST_STATE_DOWN);
04348       } else {
04349          c = sub->owner;
04350       }
04351 
04352       if (!c) {
04353          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04354       } else {
04355          sub = c->tech_pvt;
04356          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
04357       }
04358       break;
04359    case STIMULUS_FORWARDNOANSWER:
04360       if (skinnydebug)
04361          ast_debug(1, "Received Stimulus: Forward No Answer (%d/%d)\n", instance, callreference);
04362 
04363 #if 0 /* Not sure how to handle this yet */
04364       if (!sub || !sub->owner) {
04365          c = skinny_new(l, AST_STATE_DOWN);
04366       } else {
04367          c = sub->owner;
04368       }
04369 
04370       if (!c) {
04371          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04372       } else {
04373          sub = c->tech_pvt;
04374          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
04375       }
04376 #endif
04377       break;
04378    case STIMULUS_DISPLAY:
04379       /* Not sure what this is */
04380       if (skinnydebug)
04381          ast_debug(1, "Received Stimulus: Display(%d/%d)\n", instance, callreference);
04382       break;
04383    case STIMULUS_LINE:
04384       if (skinnydebug)
04385          ast_debug(1, "Received Stimulus: Line(%d/%d)\n", instance, callreference);
04386 
04387       l = find_line_by_instance(d, instance);
04388 
04389       if (!l) {
04390          return 0;
04391       }
04392 
04393       /* turn the speaker on */
04394       transmit_speaker_mode(s, SKINNY_SPEAKERON);
04395       transmit_ringer_mode(s, SKINNY_RING_OFF);
04396       transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04397 
04398       l->hookstate = SKINNY_OFFHOOK;
04399 
04400       ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
04401 
04402       if (sub && sub->outgoing) {
04403          /* We're answering a ringing call */
04404          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
04405          transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04406          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04407          transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
04408          transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
04409          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
04410          start_rtp(sub);
04411          ast_setstate(sub->owner, AST_STATE_UP);
04412       } else {
04413          if (sub && sub->owner) {
04414             ast_debug(1, "Current subchannel [%s] already has owner\n", sub->owner->name);
04415          } else {
04416             c = skinny_new(l, AST_STATE_DOWN);
04417             if (c) {
04418                sub = c->tech_pvt;
04419                transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04420                if (skinnydebug)
04421                   ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04422                transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04423                transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04424                transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK);
04425 
04426                /* start the switch thread */
04427                if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04428                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04429                   ast_hangup(c);
04430                }
04431             } else {
04432                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04433             }
04434          }
04435       }
04436       break;
04437    default:
04438       if (skinnydebug)
04439          ast_debug(1, "RECEIVED UNKNOWN STIMULUS:  %d(%d/%d)\n", event, instance, callreference);
04440       break;
04441    }
04442    ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
04443 
04444    return 1;
04445 }

static int handle_time_date_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4682 of file chan_skinny.c.

References ast_localtime(), ast_tvnow(), skinny_req::data, definetimedate_message::day, definetimedate_message::dayofweek, skinny_data::definetimedate, DEFINETIMEDATE_MESSAGE, definetimedate_message::hour, htolel, definetimedate_message::milliseconds, definetimedate_message::minute, definetimedate_message::month, req_alloc(), s, definetimedate_message::seconds, definetimedate_message::timestamp, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, ast_tm::tm_wday, ast_tm::tm_year, transmit_response(), and definetimedate_message::year.

Referenced by do_housekeeping(), and handle_message().

04683 {
04684    struct timeval tv = ast_tvnow();
04685    struct ast_tm cmtime;
04686 
04687    if (!(req = req_alloc(sizeof(struct definetimedate_message), DEFINETIMEDATE_MESSAGE)))
04688       return -1;
04689 
04690    ast_localtime(&tv, &cmtime, NULL);
04691    req->data.definetimedate.year = htolel(cmtime.tm_year+1900);
04692    req->data.definetimedate.month = htolel(cmtime.tm_mon+1);
04693    req->data.definetimedate.dayofweek = htolel(cmtime.tm_wday);
04694    req->data.definetimedate.day = htolel(cmtime.tm_mday);
04695    req->data.definetimedate.hour = htolel(cmtime.tm_hour);
04696    req->data.definetimedate.minute = htolel(cmtime.tm_min);
04697    req->data.definetimedate.seconds = htolel(cmtime.tm_sec);
04698    req->data.definetimedate.milliseconds = htolel(cmtime.tm_usec / 1000);
04699    req->data.definetimedate.timestamp = htolel(tv.tv_sec);
04700    transmit_response(s, req);
04701    return 1;
04702 }

static int handle_unregister_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5357 of file chan_skinny.c.

References s, and skinny_unregister().

Referenced by handle_message().

05358 {
05359    return skinny_unregister(req, s);
05360 }

static int handle_version_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 4852 of file chan_skinny.c.

References ast_copy_string(), skinny_req::data, req_alloc(), s, transmit_response(), version_res_message::version, skinny_data::version, skinny_device::version_id, and VERSION_RES_MESSAGE.

Referenced by handle_message().

04853 {
04854    struct skinny_device *d = s->device;
04855    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
04856       return -1;
04857 
04858    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
04859    transmit_response(s, req);
04860    return 1;
04861 }

static int has_voicemail ( struct skinny_line l  )  [static]

Definition at line 2254 of file chan_skinny.c.

References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), context, skinny_line::mailbox, mailbox, and strsep().

02255 {
02256    int new_msgs;
02257    struct ast_event *event;
02258    char *mailbox, *context;
02259 
02260    context = mailbox = ast_strdupa(l->mailbox);
02261    strsep(&context, "@");
02262    if (ast_strlen_zero(context))
02263       context = "default";
02264 
02265    event = ast_event_get_cached(AST_EVENT_MWI,
02266       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02267       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02268       AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
02269       AST_EVENT_IE_END);
02270 
02271    if (event) {
02272       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02273       ast_event_destroy(event);
02274    } else
02275       new_msgs = ast_app_has_voicemail(l->mailbox, NULL);
02276 
02277    return new_msgs;
02278 }

static int load_module ( void   )  [static]

Definition at line 6098 of file chan_skinny.c.

References ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_rtp_proto_register(), cli_skinny, htolel, io, io_context_create(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), skinny_rtp, skinny_tech, and soft_key_template_default.

06099 {
06100    int res = 0;
06101 
06102    for (; res < ARRAY_LEN(soft_key_template_default); res++) {
06103       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
06104    }
06105    /* load and parse config */
06106    res = reload_config();
06107    if (res == -1) {
06108       return AST_MODULE_LOAD_DECLINE;
06109    }
06110 
06111    /* Make sure we can register our skinny channel type */
06112    if (ast_channel_register(&skinny_tech)) {
06113       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
06114       return -1;
06115    }
06116 
06117    ast_rtp_proto_register(&skinny_rtp);
06118    ast_cli_register_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
06119    sched = sched_context_create();
06120    if (!sched) {
06121       ast_log(LOG_WARNING, "Unable to create schedule context\n");
06122    }
06123    io = io_context_create();
06124    if (!io) {
06125       ast_log(LOG_WARNING, "Unable to create I/O context\n");
06126    }
06127    /* And start the monitor for the first time */
06128    restart_monitor();
06129 
06130    return res;
06131 }

static void mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 2246 of file chan_skinny.c.

02247 {
02248    /* This module does not handle MWI in an event-based manner.  However, it
02249     * subscribes to MWI for each mailbox that is configured so that the core
02250     * knows that we care about it.  Then, chan_zap will get the MWI from the
02251     * event cache instead of checking the mailbox directly. */
02252 }

static void print_codec_to_cli ( int  fd,
struct ast_codec_pref pref 
) [static]

Print codec list from preference to CLI/manager.

Definition at line 2675 of file chan_skinny.c.

References ast_cli(), ast_codec_pref_index(), ast_getformatname(), and ast_codec_pref::framing.

02676 {
02677    int x, codec;
02678 
02679    for(x = 0; x < 32 ; x++) {
02680       codec = ast_codec_pref_index(pref, x);
02681       if (!codec)
02682          break;
02683       ast_cli(fd, "%s", ast_getformatname(codec));
02684       ast_cli(fd, ":%d", pref->framing[x]);
02685       if (x < 31 && ast_codec_pref_index(pref, x + 1))
02686          ast_cli(fd, ",");
02687    }
02688    if (!x)
02689       ast_cli(fd, "none");
02690 }

static void register_exten ( struct skinny_line l  )  [static]

Definition at line 1705 of file chan_skinny.c.

References ast_add_extension(), ast_context_find(), ast_copy_string(), ast_free_ptr, ast_log(), ast_strdup, ast_strlen_zero(), context, ext, LOG_WARNING, skinny_line::name, regcontext, skinny_line::regexten, S_OR, and strsep().

01706 {
01707    char multi[256];
01708    char *stringp, *ext, *context;
01709 
01710    if (ast_strlen_zero(regcontext))
01711       return;
01712 
01713    ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
01714    stringp = multi;
01715    while ((ext = strsep(&stringp, "&"))) {
01716       if ((context = strchr(ext, '@'))) {
01717          *context++ = '\0';   /* split ext@context */
01718          if (!ast_context_find(context)) {
01719             ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
01720             continue;
01721          }
01722       } else {
01723          context = regcontext;
01724       }
01725       ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
01726           ast_strdup(l->name), ast_free_ptr, "Skinny");
01727    }
01728 }

static int reload_config ( void   )  [static]

Definition at line 5860 of file chan_skinny.c.

References __ourip, accept_t, accept_thread(), ahp, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_context_find_or_create(), ast_copy_string(), ast_gethostbyname(), ast_inet_ntoa(), ast_jb_read_conf(), ast_log(), AST_MAX_CONTEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_set_qos(), ast_parse_allow_disallow(), ast_pthread_create_background, ast_str2cos(), ast_str2tos(), ast_variable_browse(), ast_verb, bindaddr, build_device(), cleanup_stale_contexts(), config, context, cos, cos_audio, cos_video, date_format, default_capability, default_jbconf, default_prefs, DEFAULT_SKINNY_BACKLOG, DEFAULT_SKINNY_PORT, devicelock, devices, errno, global_jbconf, hp, keep_alive, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, skinny_device::name, ast_variable::name, netlock, skinny_device::next, ast_variable::next, ourhost, ourport, regcontext, skinnysock, strsep(), tos, tos_audio, tos_video, used_context, ast_variable::value, and vmexten.

05861 {
05862    int on = 1;
05863    struct ast_config *cfg;
05864    struct ast_variable *v;
05865    char *cat;
05866    struct skinny_device *d;
05867    int oldport = ntohs(bindaddr.sin_port);
05868    char *stringp, *context, *oldregcontext;
05869    char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT];
05870    struct ast_flags config_flags = { 0 };
05871 
05872    if (gethostname(ourhost, sizeof(ourhost))) {
05873       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled\n");
05874       return 0;
05875    }
05876    cfg = ast_config_load(config, config_flags);
05877 
05878    /* We *must* have a config file otherwise stop immediately */
05879    if (!cfg) {
05880       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled\n", config);
05881       return -1;
05882    }
05883    memset(&bindaddr, 0, sizeof(bindaddr));
05884    memset(&default_prefs, 0, sizeof(default_prefs));
05885 
05886    /* Initialize copy of current global_regcontext for later use in removing stale contexts */
05887    ast_copy_string(oldcontexts, regcontext, sizeof(oldcontexts));
05888    oldregcontext = oldcontexts;
05889 
05890    /* Copy the default jb config over global_jbconf */
05891    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
05892 
05893    /* load the general section */
05894    v = ast_variable_browse(cfg, "general");
05895    while (v) {
05896       /* handle jb conf */
05897       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
05898          v = v->next;
05899          continue;
05900       }
05901 
05902       /* Create the interface list */
05903       if (!strcasecmp(v->name, "bindaddr")) {
05904          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
05905             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
05906          } else {
05907             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
05908          }
05909       } else if (!strcasecmp(v->name, "keepalive")) {
05910          keep_alive = atoi(v->value);
05911       } else if (!strcasecmp(v->name, "vmexten")) {
05912          ast_copy_string(vmexten, v->value, sizeof(vmexten));
05913       } else if (!strcasecmp(v->name, "regcontext")) {
05914          ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
05915          stringp = newcontexts;
05916          /* Let's remove any contexts that are no longer defined in regcontext */
05917          cleanup_stale_contexts(stringp, oldregcontext);
05918          /* Create contexts if they don't exist already */
05919          while ((context = strsep(&stringp, "&"))) {
05920             ast_copy_string(used_context, context, sizeof(used_context));
05921             ast_context_find_or_create(NULL, NULL, context, "Skinny");
05922          }
05923          ast_copy_string(regcontext, v->value, sizeof(regcontext));
05924       } else if (!strcasecmp(v->name, "dateformat")) {
05925          memcpy(date_format, v->value, sizeof(date_format));
05926                 } else if (!strcasecmp(v->name, "tos")) {
05927                         if (ast_str2tos(v->value, &tos))
05928                         ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
05929                 } else if (!strcasecmp(v->name, "tos_audio")) {
05930                         if (ast_str2tos(v->value, &tos_audio))
05931                         ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05932                 } else if (!strcasecmp(v->name, "tos_video")) {
05933                         if (ast_str2tos(v->value, &tos_video))
05934                         ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno);
05935       } else if (!strcasecmp(v->name, "cos")) {
05936               if (ast_str2cos(v->value, &cos))
05937                       ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
05938       } else if (!strcasecmp(v->name, "cos_audio")) {
05939               if (ast_str2cos(v->value, &cos_audio))
05940                       ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05941       } else if (!strcasecmp(v->name, "cos_video")) {
05942               if (ast_str2cos(v->value, &cos_video))
05943                       ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
05944       } else if (!strcasecmp(v->name, "allow")) {
05945          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
05946       } else if (!strcasecmp(v->name, "disallow")) {
05947          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
05948       } else if (!strcasecmp(v->name, "bindport")) {
05949          if (sscanf(v->value, "%d", &ourport) == 1) {
05950             bindaddr.sin_port = htons(ourport);
05951          } else {
05952             ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
05953          }
05954       }
05955       v = v->next;
05956    }
05957 
05958    if (ntohl(bindaddr.sin_addr.s_addr)) {
05959       __ourip = bindaddr.sin_addr;
05960    } else {
05961       hp = ast_gethostbyname(ourhost, &ahp);
05962       if (!hp) {
05963          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
05964          ast_config_destroy(cfg);
05965          return 0;
05966       }
05967       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
05968    }
05969    if (!ntohs(bindaddr.sin_port)) {
05970       bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
05971    }
05972    bindaddr.sin_family = AF_INET;
05973 
05974    /* load the device sections */
05975    cat = ast_category_browse(cfg, NULL);
05976    while(cat) {
05977       if (!strcasecmp(cat, "general")) {
05978          /* Nothing to do */
05979 #if 0
05980       } else if (!strncasecmp(cat, "paging-", 7)) {
05981          p = build_paging_device(cat, ast_variable_browse(cfg, cat));
05982          if (p) {
05983          }
05984 #endif
05985       } else {
05986          d = build_device(cat, ast_variable_browse(cfg, cat));
05987          if (d) {
05988             ast_verb(3, "Added device '%s'\n", d->name);
05989             ast_mutex_lock(&devicelock);
05990             d->next = devices;
05991             devices = d;
05992             ast_mutex_unlock(&devicelock);
05993          }
05994       }
05995       cat = ast_category_browse(cfg, cat);
05996    }
05997    ast_mutex_lock(&netlock);
05998    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
05999       close(skinnysock);
06000       skinnysock = -1;
06001    }
06002    if (skinnysock < 0) {
06003       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
06004       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
06005          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
06006          ast_config_destroy(cfg);
06007          ast_mutex_unlock(&netlock);
06008          return 0;
06009       }
06010       if (skinnysock < 0) {
06011          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
06012       } else {
06013          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
06014             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
06015                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
06016                      strerror(errno));
06017             close(skinnysock);
06018             skinnysock = -1;
06019             ast_config_destroy(cfg);
06020             ast_mutex_unlock(&netlock);
06021             return 0;
06022          }
06023          if (listen(skinnysock,DEFAULT_SKINNY_BACKLOG)) {
06024                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
06025                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
06026                      strerror(errno));
06027                close(skinnysock);
06028                skinnysock = -1;
06029                ast_config_destroy(cfg);
06030                ast_mutex_unlock(&netlock);
06031                return 0;
06032          }
06033          ast_verb(2, "Skinny listening on %s:%d\n",
06034                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
06035          ast_netsock_set_qos(skinnysock, tos, cos, "Skinny");
06036          ast_pthread_create_background(&accept_t,NULL, accept_thread, NULL);
06037       }
06038    }
06039    ast_mutex_unlock(&netlock);
06040    ast_config_destroy(cfg);
06041    return 1;
06042 }

static struct skinny_req* req_alloc ( size_t  size,
int  response_message 
) [static]

Definition at line 1436 of file chan_skinny.c.

References ast_calloc, skinny_req::e, htolel, and skinny_req::len.

Referenced by handle_button_template_req_message(), handle_keep_alive_message(), handle_line_state_req_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_server_request_message(), handle_skinny_reset(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_time_date_req_message(), handle_version_req_message(), skinny_hold(), skinny_set_rtp_peer(), skinny_unhold(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_connect(), transmit_dialednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

01437 {
01438    struct skinny_req *req;
01439 
01440    if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
01441       return NULL;
01442 
01443    req->len = htolel(size+4);
01444    req->e = htolel(response_message);
01445 
01446    return req;
01447 }

static int restart_monitor ( void   )  [static]

Definition at line 5786 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, monitor_thread, and monlock.

05787 {
05788    /* If we're supposed to be stopped -- stay stopped */
05789    if (monitor_thread == AST_PTHREADT_STOP)
05790       return 0;
05791 
05792    ast_mutex_lock(&monlock);
05793    if (monitor_thread == pthread_self()) {
05794       ast_mutex_unlock(&monlock);
05795       ast_log(LOG_WARNING, "Cannot kill myself\n");
05796       return -1;
05797    }
05798    if (monitor_thread != AST_PTHREADT_NULL) {
05799       /* Wake up the thread */
05800       pthread_kill(monitor_thread, SIGURG);
05801    } else {
05802       /* Start a new monitor */
05803       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
05804          ast_mutex_unlock(&monlock);
05805          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
05806          return -1;
05807       }
05808    }
05809    ast_mutex_unlock(&monlock);
05810    return 0;
05811 }

static int set_callforwards ( struct skinny_line l,
const char *  cfwd,
int  cfwdtype 
) [static]

Definition at line 1647 of file chan_skinny.c.

References ast_copy_string(), ast_strlen_zero(), skinny_line::call_forward_all, skinny_line::call_forward_busy, skinny_line::call_forward_noanswer, skinny_line::cfwdtype, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, and SKINNY_CFWD_NOANSWER.

Referenced by build_device(), handle_callforward_button(), and skinny_ss().

01648 {
01649    if (!l)
01650       return 0;
01651 
01652    if (!ast_strlen_zero(cfwd)) {
01653       if (cfwdtype & SKINNY_CFWD_ALL) {
01654          l->cfwdtype |= SKINNY_CFWD_ALL;
01655          ast_copy_string(l->call_forward_all, cfwd, sizeof(l->call_forward_all));
01656       }
01657       if (cfwdtype & SKINNY_CFWD_BUSY) {
01658          l->cfwdtype |= SKINNY_CFWD_BUSY;
01659          ast_copy_string(l->call_forward_busy, cfwd, sizeof(l->call_forward_busy));
01660       }
01661       if (cfwdtype & SKINNY_CFWD_NOANSWER) {
01662          l->cfwdtype |= SKINNY_CFWD_NOANSWER;
01663          ast_copy_string(l->call_forward_noanswer, cfwd, sizeof(l->call_forward_noanswer));
01664       }
01665    } else {
01666       if (cfwdtype & SKINNY_CFWD_ALL) {
01667          l->cfwdtype &= ~SKINNY_CFWD_ALL;
01668          memset(l->call_forward_all, 0, sizeof(l->call_forward_all));
01669       }
01670       if (cfwdtype & SKINNY_CFWD_BUSY) {
01671          l->cfwdtype &= ~SKINNY_CFWD_BUSY;
01672          memset(l->call_forward_busy, 0, sizeof(l->call_forward_busy));
01673       }
01674       if (cfwdtype & SKINNY_CFWD_NOANSWER) {
01675          l->cfwdtype &= ~SKINNY_CFWD_NOANSWER;
01676          memset(l->call_forward_noanswer, 0, sizeof(l->call_forward_noanswer));
01677       }
01678    }
01679    return l->cfwdtype;
01680 }

static int skinny_answer ( struct ast_channel ast  )  [static]

Definition at line 3456 of file chan_skinny.c.

References ast_channel::_state, ast_copy_string(), ast_debug, AST_MAX_EXTENSION, ast_setstate(), AST_STATE_UP, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, skinny_subchannel::cxmode, ast_channel::exten, exten, skinny_line::instance, KEYDEF_CONNECTED, ast_channel::macroexten, skinny_device::name, skinny_line::name, ast_channel::name, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, s, S_OR, skinny_device::session, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, SKINNY_SILENCE, skinnydebug, start_rtp(), skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_selectsoftkeys(), and transmit_tone().

03457 {
03458    int res = 0;
03459    struct skinny_subchannel *sub = ast->tech_pvt;
03460    struct skinny_line *l = sub->parent;
03461    struct skinny_device *d = l->parent;
03462    struct skinnysession *s = d->session;
03463    char exten[AST_MAX_EXTENSION] = "";
03464 
03465    ast_copy_string(exten, S_OR(ast->macroexten, ast->exten), sizeof(exten));
03466 
03467    sub->cxmode = SKINNY_CX_SENDRECV;
03468    if (!sub->rtp) {
03469       start_rtp(sub);
03470    }
03471    if (skinnydebug)
03472       ast_debug(1, "skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, d->name, sub->callid);
03473    if (ast->_state != AST_STATE_UP) {
03474       ast_setstate(ast, AST_STATE_UP);
03475    }
03476 
03477    transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03478    /* order matters here...
03479       for some reason, transmit_callinfo must be before transmit_callstate,
03480       or you won't get keypad messages in some situations. */
03481    transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, exten, exten, l->instance, sub->callid, 2);
03482    transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
03483    transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
03484    transmit_dialednumber(s, exten, l->instance, sub->callid);
03485    transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
03486    return res;
03487 }

static int skinny_call ( struct ast_channel ast,
char *  dest,
int  timeout 
) [static]

Definition at line 3359 of file chan_skinny.c.

References ast_channel::_state, AST_CONTROL_BUSY, AST_CONTROL_RINGING, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_verb, skinny_subchannel::callid, ast_channel::cid, skinny_line::cid_name, ast_callerid::cid_name, skinny_line::cid_num, ast_callerid::cid_num, skinny_line::dnd, skinny_line::hookstate, skinny_line::instance, KEYDEF_RINGIN, LOG_ERROR, LOG_WARNING, ast_channel::name, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::parent, skinny_device::registered, s, skinny_device::session, SKINNY_ALERT, SKINNY_CALLWAITTONE, SKINNY_LAMP_BLINK, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_INSIDE, SKINNY_RINGIN, skinnydebug, STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), and transmit_selectsoftkeys().

03360 {
03361    int res = 0;
03362    int tone = 0;
03363    struct skinny_subchannel *sub = ast->tech_pvt;
03364    struct skinny_line *l = sub->parent;
03365    struct skinny_device *d = l->parent;
03366    struct skinnysession *s = d->session;
03367 
03368    if (!d->registered) {
03369       ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
03370       return -1;
03371    }
03372 
03373    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03374       ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast->name);
03375       return -1;
03376    }
03377 
03378    if (skinnydebug)
03379       ast_verb(3, "skinny_call(%s)\n", ast->name);
03380 
03381    if (l->dnd) {
03382       ast_queue_control(ast, AST_CONTROL_BUSY);
03383       return -1;
03384    }
03385 
03386    switch (l->hookstate) {
03387    case SKINNY_OFFHOOK:
03388       tone = SKINNY_CALLWAITTONE;
03389       break;
03390    case SKINNY_ONHOOK:
03391       tone = SKINNY_ALERT;
03392       break;
03393    default:
03394       ast_log(LOG_ERROR, "Don't know how to deal with hookstate %d\n", l->hookstate);
03395       break;
03396    }
03397 
03398    transmit_callstate(s, l->instance, SKINNY_RINGIN, sub->callid);
03399    transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGIN);
03400    transmit_displaypromptstatus(s, "Ring-In", 0, l->instance, sub->callid);
03401    transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
03402    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03403    transmit_ringer_mode(s, SKINNY_RING_INSIDE);
03404 
03405    ast_setstate(ast, AST_STATE_RINGING);
03406    ast_queue_control(ast, AST_CONTROL_RINGING);
03407    sub->outgoing = 1;
03408    return res;
03409 }

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 5813 of file chan_skinny.c.

References ast_strdupa, find_line_by_name(), and get_devicestate().

05814 {
05815    struct skinny_line *l;
05816    char *tmp;
05817 
05818    tmp = ast_strdupa(data);
05819 
05820    l = find_line_by_name(tmp);
05821 
05822    return get_devicestate(l);
05823 }

static int skinny_extensionstate_cb ( char *  context,
char *  exten,
int  state,
void *  data 
) [static]

Definition at line 2193 of file chan_skinny.c.

References ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_EXTENSION_BUSY, AST_EXTENSION_DEACTIVATED, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_REMOVED, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_hint(), AST_MAX_EXTENSION, ast_verb, skinny_speeddial::context, skinny_speeddial::exten, skinny_speeddial::instance, skinny_speeddial::laststate, skinny_device::name, skinny_speeddial::parent, s, skinny_device::session, SKINNY_CALLREMOTEMULTILINE, SKINNY_HOLD, SKINNY_LAMP_BLINK, SKINNY_LAMP_FLASH, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_LAMP_WINK, SKINNY_ONHOOK, SKINNY_RINGIN, skinny_speeddial::stateid, STIMULUS_LINE, transmit_callstate(), and transmit_lamp_indication().

02194 {
02195    struct skinny_speeddial *sd = data;
02196    struct skinny_device *d = sd->parent;
02197    struct skinnysession *s = d->session;
02198    char hint[AST_MAX_EXTENSION];
02199    int callstate = SKINNY_CALLREMOTEMULTILINE;
02200    int lamp = SKINNY_LAMP_OFF;
02201 
02202    switch (state) {
02203    case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
02204    case AST_EXTENSION_REMOVED:     /* Extension is gone */
02205       ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
02206       sd->stateid = -1;
02207       callstate = SKINNY_ONHOOK;
02208       lamp = SKINNY_LAMP_OFF;
02209       break;
02210    case AST_EXTENSION_RINGING:
02211    case AST_EXTENSION_UNAVAILABLE:
02212       callstate = SKINNY_RINGIN;
02213       lamp = SKINNY_LAMP_BLINK;
02214       break;
02215    case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
02216    case AST_EXTENSION_INUSE:
02217       callstate = SKINNY_CALLREMOTEMULTILINE;
02218       lamp = SKINNY_LAMP_ON;
02219       break;
02220    case AST_EXTENSION_ONHOLD:
02221       callstate = SKINNY_HOLD;
02222       lamp = SKINNY_LAMP_WINK;
02223       break;
02224    case AST_EXTENSION_NOT_INUSE:
02225    default:
02226       callstate = SKINNY_ONHOOK;
02227       lamp = SKINNY_LAMP_OFF;
02228       break;
02229    }
02230 
02231    if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
02232       /* If they are not registered, we will override notification and show no availability */
02233       if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
02234          callstate = SKINNY_ONHOOK;
02235          lamp = SKINNY_LAMP_FLASH;
02236       }
02237    }
02238 
02239    transmit_lamp_indication(s, STIMULUS_LINE, sd->instance, lamp);
02240    transmit_callstate(s, sd->instance, callstate, 0);
02241    sd->laststate = state;
02242 
02243    return 0;
02244 }

static int skinny_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 3575 of file chan_skinny.c.

References ast_log(), LOG_NOTICE, LOG_WARNING, ast_channel::name, skinny_subchannel::owner, and ast_channel::tech_pvt.

03576 {
03577    struct skinny_subchannel *sub = newchan->tech_pvt;
03578    ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
03579    if (sub->owner != oldchan) {
03580       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
03581       return -1;
03582    }
03583    sub->owner = newchan;
03584    return 0;
03585 }

static enum ast_rtp_get_result skinny_get_rtp_peer ( struct ast_channel c,
struct ast_rtp **  rtp 
) [static]

Definition at line 2324 of file chan_skinny.c.

References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, skinny_line::canreinvite, skinny_subchannel::lock, ast_channel::name, skinny_line::nat, skinny_subchannel::parent, skinny_subchannel::rtp, skinnydebug, skinny_line::sub, and ast_channel::tech_pvt.

02325 {
02326    struct skinny_subchannel *sub = NULL;
02327    struct skinny_line *l;
02328    enum ast_rtp_get_result res = AST_RTP_TRY_NATIVE;
02329 
02330    if (skinnydebug)
02331       ast_debug(1, "skinny_get_rtp_peer() Channel = %s\n", c->name);
02332 
02333 
02334    if (!(sub = c->tech_pvt))
02335       return AST_RTP_GET_FAILED;
02336 
02337    ast_mutex_lock(&sub->lock);
02338 
02339    if (!(sub->rtp)){
02340       ast_mutex_unlock(&sub->lock);
02341       return AST_RTP_GET_FAILED;
02342    }
02343    
02344    *rtp = sub->rtp;
02345 
02346    l = sub->parent;
02347 
02348    if (!l->canreinvite || l->nat){
02349       res = AST_RTP_TRY_PARTIAL;
02350       if (skinnydebug)
02351          ast_debug(1, "skinny_get_rtp_peer() Using AST_RTP_TRY_PARTIAL \n");
02352    }
02353 
02354    ast_mutex_unlock(&sub->lock);
02355 
02356    return res;
02357 
02358 }

static enum ast_rtp_get_result skinny_get_vrtp_peer ( struct ast_channel c,
struct ast_rtp **  rtp 
) [static]

Definition at line 2312 of file chan_skinny.c.

References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, skinny_subchannel::rtp, ast_channel::tech_pvt, and skinny_subchannel::vrtp.

02313 {
02314    struct skinny_subchannel *sub = NULL;
02315 
02316    if (!(sub = c->tech_pvt) || !(sub->vrtp))
02317       return AST_RTP_GET_FAILED;
02318 
02319    *rtp = sub->vrtp;
02320 
02321    return AST_RTP_TRY_NATIVE;
02322 }

static int skinny_hangup ( struct ast_channel ast  )  [static]

Definition at line 3411 of file chan_skinny.c.

References skinny_subchannel::alreadygone, ast_debug, ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), skinny_subchannel::callid, do_housekeeping(), skinny_line::hookstate, skinny_line::instance, skinny_subchannel::lock, skinny_device::name, skinny_line::name, ast_channel::name, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_device::registered, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_LAMP_OFF, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, skinnydebug, STIMULUS_LINE, ast_channel::tech_pvt, transmit_callstate(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), transmit_tone(), skinny_line::type, and TYPE_LINE.

03412 {
03413    struct skinny_subchannel *sub = ast->tech_pvt;
03414    struct skinny_line *l;
03415    struct skinny_device *d;
03416    struct skinnysession *s;
03417 
03418    if (!sub) {
03419       ast_debug(1, "Asked to hangup channel not connected\n");
03420       return 0;
03421    }
03422    l = sub->parent;
03423    d = l->parent;
03424    s = d->session;
03425    if (skinnydebug)
03426       ast_debug(1, "skinny_hangup(%s) on %s@%s\n", ast->name, l->name, d->name);
03427 
03428    if (d->registered) {
03429       if ((l->type = TYPE_LINE) && (l->hookstate == SKINNY_OFFHOOK)) {
03430          l->hookstate = SKINNY_ONHOOK;
03431          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
03432          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
03433          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
03434       } else if ((l->type = TYPE_LINE) && (l->hookstate == SKINNY_ONHOOK)) {
03435          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03436          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
03437          transmit_ringer_mode(s, SKINNY_RING_OFF);
03438          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
03439          do_housekeeping(s);
03440       }
03441    }
03442    ast_mutex_lock(&sub->lock);
03443    sub->owner = NULL;
03444    ast->tech_pvt = NULL;
03445    sub->alreadygone = 0;
03446    sub->outgoing = 0;
03447    if (sub->rtp) {
03448       ast_rtp_destroy(sub->rtp);
03449       sub->rtp = NULL;
03450    }
03451    ast_mutex_unlock(&sub->lock);
03452    ast_free(sub);
03453    return 0;
03454 }

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

Definition at line 3878 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_data::activatecallplane, AST_CONTROL_HOLD, ast_debug, ast_queue_control_data(), ast_strlen_zero(), skinny_subchannel::callid, CLOSE_RECEIVE_CHANNEL_MESSAGE, skinny_data::closereceivechannel, stop_media_transmission_message::conferenceId, close_receive_channel_message::conferenceId, skinny_req::data, htolel, skinny_line::instance, activate_call_plane_message::lineInstance, skinny_line::mohsuggest, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, close_receive_channel_message::partyId, stop_media_transmission_message::passThruPartyId, req_alloc(), s, S_OR, skinny_device::session, SKINNY_LAMP_WINK, skinnydebug, STIMULUS_LINE, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, skinny_line::sub, transmit_lamp_indication(), and transmit_response().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

03879 {
03880    struct skinny_line *l = sub->parent;
03881    struct skinny_device *d = l->parent;
03882    struct skinnysession *s = d->session;
03883    struct skinny_req *req;
03884 
03885    /* Don't try to hold a channel that doesn't exist */
03886    if (!sub || !sub->owner)
03887       return 0;
03888 
03889    /* Channel needs to be put on hold */
03890    if (skinnydebug)
03891       ast_debug(1, "Putting on Hold(%d)\n", l->instance);
03892 
03893    ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
03894       S_OR(l->mohsuggest, NULL),
03895       !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
03896 
03897    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
03898       return 0;
03899 
03900    req->data.activatecallplane.lineInstance = htolel(l->instance);
03901    transmit_response(s, req);
03902 
03903    if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
03904       return 0;
03905 
03906    req->data.closereceivechannel.conferenceId = htolel(sub->callid);
03907    req->data.closereceivechannel.partyId = htolel(sub->callid);
03908    transmit_response(s, req);
03909 
03910    if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
03911       return 0;
03912 
03913    req->data.stopmedia.conferenceId = htolel(sub->callid);
03914    req->data.stopmedia.passThruPartyId = htolel(sub->callid);
03915    transmit_response(s, req);
03916 
03917    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
03918    sub->onhold = 1;
03919    return 1;
03920 }

static int skinny_indicate ( struct ast_channel ast,
int  ind,
const void *  data,
size_t  datalen 
) [static]

Definition at line 3684 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_copy_string(), ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, ast_verb, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, control2str(), skinny_device::earlyrtp, ast_channel::exten, exten, skinny_line::instance, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, skinny_line::mohinterpret, ast_channel::name, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::progress, skinny_subchannel::ringing, skinny_subchannel::rtp, s, S_OR, skinny_device::session, SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CONGESTION, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RINGOUT, SKINNY_SILENCE, skinnydebug, skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_dialednumber(), transmit_displaypromptstatus(), and transmit_tone().

03685 {
03686    struct skinny_subchannel *sub = ast->tech_pvt;
03687    struct skinny_line *l = sub->parent;
03688    struct skinny_device *d = l->parent;
03689    struct skinnysession *s = d->session;
03690    char exten[AST_MAX_EXTENSION] = "";
03691 
03692    if (!s) {
03693       ast_log(LOG_NOTICE, "Asked to indicate '%s' condition on channel %s, but session does not exist.\n", control2str(ind), ast->name);
03694       return -1;
03695    }
03696 
03697    ast_copy_string(exten, S_OR(ast->macroexten, ast->exten), sizeof(exten));
03698 
03699    if (skinnydebug)
03700       ast_verb(3, "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
03701    switch(ind) {
03702    case AST_CONTROL_RINGING:
03703       if (ast->_state != AST_STATE_UP) {
03704          if (!sub->progress) {
03705             if (!d->earlyrtp) {
03706                transmit_tone(s, SKINNY_ALERT, l->instance, sub->callid);
03707             }
03708             transmit_callstate(s, l->instance, SKINNY_RINGOUT, sub->callid);
03709             transmit_dialednumber(s, exten, l->instance, sub->callid);
03710             transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, sub->callid);
03711             transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, exten, exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
03712             sub->ringing = 1;
03713             if (!d->earlyrtp) {
03714                break;
03715             }
03716          }
03717       }
03718       return -1; /* Tell asterisk to provide inband signalling */
03719    case AST_CONTROL_BUSY:
03720       if (ast->_state != AST_STATE_UP) {
03721          if (!d->earlyrtp) {
03722             transmit_tone(s, SKINNY_BUSYTONE, l->instance, sub->callid);
03723          }
03724          transmit_callstate(s, l->instance, SKINNY_BUSY, sub->callid);
03725          sub->alreadygone = 1;
03726          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
03727          if (!d->earlyrtp) {
03728             break;
03729          }
03730       }
03731       return -1; /* Tell asterisk to provide inband signalling */
03732    case AST_CONTROL_CONGESTION:
03733       if (ast->_state != AST_STATE_UP) {
03734          if (!d->earlyrtp) {
03735             transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
03736          }
03737          transmit_callstate(s, l->instance, SKINNY_CONGESTION, sub->callid);
03738          sub->alreadygone = 1;
03739          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
03740          if (!d->earlyrtp) {
03741             break;
03742          }
03743       }
03744       return -1; /* Tell asterisk to provide inband signalling */
03745    case AST_CONTROL_PROGRESS:
03746       if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
03747          if (!d->earlyrtp) {
03748             transmit_tone(s, SKINNY_ALERT, l->instance, sub->callid);
03749          }
03750          transmit_callstate(s, l->instance, SKINNY_PROGRESS, sub->callid);
03751          transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, sub->callid);
03752          transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, exten, exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
03753          sub->progress = 1;
03754          if (!d->earlyrtp) {
03755             break;
03756          }
03757       }
03758       return -1; /* Tell asterisk to provide inband signalling */
03759    case -1:  /* STOP_TONE */
03760       transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03761       break;
03762    case AST_CONTROL_HOLD:
03763       ast_moh_start(ast, data, l->mohinterpret);
03764       break;
03765    case AST_CONTROL_UNHOLD:
03766       ast_moh_stop(ast);
03767       break;
03768    case AST_CONTROL_PROCEEDING:
03769       break;
03770    case AST_CONTROL_SRCUPDATE:
03771       ast_rtp_new_source(sub->rtp);
03772       break;
03773    default:
03774       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
03775       return -1; /* Tell asterisk to provide inband signalling */
03776    }
03777    return 0;
03778 }

static struct ast_channel* skinny_new ( struct skinny_line l,
int  state 
) [static]

Definition at line 3780 of file chan_skinny.c.

References accountcode, skinny_line::accountcode, ast_channel::adsicpe, ast_channel::amaflags, skinny_line::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_debug, AST_DEVICE_NOT_INUSE, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_mutex_init(), ast_pbx_start(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), skinny_line::call_forward_all, skinny_line::callgroup, ast_channel::callgroup, callnums, skinny_line::capability, skinny_line::cfwdtype, skinny_line::chanvars, ast_channel::cid, ast_callerid::cid_ani, skinny_line::cid_name, skinny_line::cid_num, ast_channel::context, skinny_line::context, default_capability, ast_channel::exten, skinny_line::exten, get_devicestate(), global_jbconf, skinny_line::instance, language, skinny_line::language, skinny_device::lastcallreference, skinny_device::lastlineinstance, LOG_WARNING, ast_variable::name, skinny_device::name, skinny_line::name, skinny_line::nat, ast_channel::nativeformats, ast_variable::next, skinny_line::next, skinny_line::parent, pbx_builtin_setvar_helper(), skinny_line::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CX_INACTIVE, skinny_tech, skinnydebug, skinny_line::sub, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, and ast_channel::writeformat.

Referenced by handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_request().

03781 {
03782    struct ast_channel *tmp;
03783    struct skinny_subchannel *sub;
03784    struct skinny_device *d = l->parent;
03785    struct ast_variable *v = NULL;
03786    int fmt;
03787 
03788    tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
03789    if (!tmp) {
03790       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
03791       return NULL;
03792    } else {
03793       sub = ast_calloc(1, sizeof(*sub));
03794       if (!sub) {
03795          ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
03796          return NULL;
03797       } else {
03798          ast_mutex_init(&sub->lock);
03799 
03800          sub->owner = tmp;
03801          sub->callid = callnums++;
03802          d->lastlineinstance = l->instance;
03803          d->lastcallreference = sub->callid;
03804          sub->cxmode = SKINNY_CX_INACTIVE;
03805          sub->nat = l->nat;
03806          sub->parent = l;
03807          sub->onhold = 0;
03808 
03809          sub->next = l->sub;
03810          l->sub = sub;
03811       }
03812       tmp->tech = &skinny_tech;
03813       tmp->tech_pvt = sub;
03814       tmp->nativeformats = l->capability;
03815       if (!tmp->nativeformats)
03816          tmp->nativeformats = default_capability;
03817       fmt = ast_best_codec(tmp->nativeformats);
03818       if (skinnydebug)
03819          ast_debug(1, "skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
03820       if (sub->rtp) {
03821          ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
03822       }
03823       if (state == AST_STATE_RING) {
03824          tmp->rings = 1;
03825       }
03826       tmp->writeformat = fmt;
03827       tmp->rawwriteformat = fmt;
03828       tmp->readformat = fmt;
03829       tmp->rawreadformat = fmt;
03830       if (!ast_strlen_zero(l->language))
03831          ast_string_field_set(tmp, language, l->language);
03832       if (!ast_strlen_zero(l->accountcode))
03833          ast_string_field_set(tmp, accountcode, l->accountcode);
03834       if (l->amaflags)
03835          tmp->amaflags = l->amaflags;
03836 
03837       ast_module_ref(ast_module_info->self);
03838       tmp->callgroup = l->callgroup;
03839       tmp->pickupgroup = l->pickupgroup;
03840 
03841       /* XXX Need to figure out how to handle CFwdNoAnswer */
03842       if (l->cfwdtype & SKINNY_CFWD_ALL) {
03843          ast_string_field_set(tmp, call_forward, l->call_forward_all);
03844       } else if (l->cfwdtype & SKINNY_CFWD_BUSY) {
03845          if (get_devicestate(l) != AST_DEVICE_NOT_INUSE) {
03846             ast_string_field_set(tmp, call_forward, l->call_forward_busy);
03847          }
03848       }
03849 
03850       ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
03851       ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
03852 
03853       /* Don't use ast_set_callerid() here because it will
03854        * generate a needless NewCallerID event */
03855       tmp->cid.cid_ani = ast_strdup(l->cid_num);
03856 
03857       tmp->priority = 1;
03858       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
03859 
03860       if (sub->rtp)
03861          ast_jb_configure(tmp, &global_jbconf);
03862 
03863       /* Set channel variables for this call from configuration */
03864       for (v = l->chanvars ; v ; v = v->next)
03865          pbx_builtin_setvar_helper(tmp, v->name, v->value);
03866 
03867       if (state != AST_STATE_DOWN) {
03868          if (ast_pbx_start(tmp)) {
03869             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
03870             ast_hangup(tmp);
03871             tmp = NULL;
03872          }
03873       }
03874    }
03875    return tmp;
03876 }

static void* skinny_newcall ( void *  data  )  [static]

Definition at line 3232 of file chan_skinny.c.

References ast_copy_string(), ast_log(), ast_pbx_run(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_ani, skinny_line::cid_name, skinny_line::cid_num, ast_channel::exten, skinny_line::hidecallerid, skinny_line::instance, skinny_line::lastnumberdialed, LOG_WARNING, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_REORDER, start_rtp(), skinny_line::sub, ast_channel::tech_pvt, and transmit_tone().

Referenced by handle_enbloc_call_message(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_ss().

03233 {
03234    struct ast_channel *c = data;
03235    struct skinny_subchannel *sub = c->tech_pvt;
03236    struct skinny_line *l = sub->parent;
03237    struct skinny_device *d = l->parent;
03238    struct skinnysession *s = d->session;
03239    int res = 0;
03240 
03241    ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed));
03242    ast_set_callerid(c,
03243       l->hidecallerid ? "" : l->cid_num,
03244       l->hidecallerid ? "" : l->cid_name,
03245       c->cid.cid_ani ? NULL : l->cid_num);
03246    ast_setstate(c, AST_STATE_RING);
03247    if (!sub->rtp) {
03248       start_rtp(sub);
03249    }
03250    res = ast_pbx_run(c);
03251    if (res) {
03252       ast_log(LOG_WARNING, "PBX exited non-zero\n");
03253       transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
03254    }
03255    return NULL;
03256 }

static struct ast_frame * skinny_read ( struct ast_channel ast  )  [static]

Definition at line 3537 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), skinny_subchannel::lock, skinny_rtp_read(), and ast_channel::tech_pvt.

03538 {
03539    struct ast_frame *fr;
03540    struct skinny_subchannel *sub = ast->tech_pvt;
03541    ast_mutex_lock(&sub->lock);
03542    fr = skinny_rtp_read(sub);
03543    ast_mutex_unlock(&sub->lock);
03544    return fr;
03545 }

static int skinny_register ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 1754 of file chan_skinny.c.

References __ourip, ast_apply_ha(), ast_copy_string(), ast_log(), ast_mutex_lock(), ast_strlen_zero(), skinny_req::data, devicelock, devices, skinny_device::ha, skinny_device::id, letohl, LOG_WARNING, register_message::name, skinny_device::next, skinny_data::reg, skinny_device::registered, s, skinny_device::session, register_message::type, skinny_device::type, version_id, and skinny_device::version_id.

Referenced by handle_register_message().

01755 {
01756    struct skinny_device *d;
01757    struct skinny_line *l;
01758    struct skinny_speeddial *sd;
01759    struct sockaddr_in sin;
01760    socklen_t slen;
01761 
01762    ast_mutex_lock(&devicelock);
01763    for (d = devices; d; d = d->next) {
01764       if (!strcasecmp(req->data.reg.name, d->id)
01765             && ast_apply_ha(d->ha, &(s->sin))) {
01766          s->device = d;
01767          d->type = letohl(req->data.reg.type);
01768          if (ast_strlen_zero(d->version_id)) {
01769             ast_copy_string(d->version_id, version_id, sizeof(d->version_id));
01770          }
01771          d->registered = 1;
01772          d->session = s;
01773 
01774          slen = sizeof(sin);
01775          if (getsockname(s->fd, (struct sockaddr *)&sin, &slen)) {
01776             ast_log(LOG_WARNING, "Cannot get socket name\n");
01777             sin.sin_addr = __ourip;
01778          }
01779          d->ourip = sin.sin_addr;
01780 
01781          for (sd = d->speeddials; sd; sd = sd->next) {
01782             sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd);
01783          }
01784          for (l = d->lines; l; l = l->next) {
01785             register_exten(l);
01786             ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
01787          }
01788          break;
01789       }
01790    }
01791    ast_mutex_unlock(&devicelock);
01792    if (!d) {
01793       return 0;
01794    }
01795    return 1;
01796 }

static struct skinny_req* skinny_req_parse ( struct skinnysession s  )  [static]

Definition at line 5658 of file chan_skinny.c.

References ast_calloc, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), skinny_req::data, skinny_req::e, letohl, LOG_ERROR, s, skinny_header_size, and SKINNY_MAX_PACKET.

Referenced by skinny_session().

05659 {
05660    struct skinny_req *req;
05661 
05662    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
05663       return NULL;
05664 
05665    ast_mutex_lock(&s->lock);
05666    memcpy(req, s->inbuf, skinny_header_size);
05667    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*(int*)(s->inbuf))-4);
05668 
05669    ast_mutex_unlock(&s->lock);
05670 
05671    if (letohl(req->e) < 0) {
05672       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
05673       ast_free(req);
05674       return NULL;
05675    }
05676 
05677    return req;
05678 }

static struct ast_channel * skinny_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 5825 of file chan_skinny.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_log(), AST_STATE_DOWN, ast_strlen_zero(), ast_verb, find_line_by_name(), LOG_NOTICE, LOG_WARNING, restart_monitor(), and skinny_new().

05826 {
05827    int oldformat;
05828    
05829    struct skinny_line *l;
05830    struct ast_channel *tmpc = NULL;
05831    char tmp[256];
05832    char *dest = data;
05833 
05834    oldformat = format;
05835    
05836    if (!(format &= AST_FORMAT_AUDIO_MASK)) {
05837       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
05838       return NULL;   
05839    }     
05840 
05841    ast_copy_string(tmp, dest, sizeof(tmp));
05842    if (ast_strlen_zero(tmp)) {
05843       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
05844       return NULL;
05845    }
05846    l = find_line_by_name(tmp);
05847    if (!l) {
05848       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
05849       return NULL;
05850    }
05851    ast_verb(3, "skinny_request(%s)\n", tmp);
05852    tmpc = skinny_new(l, AST_STATE_DOWN);
05853    if (!tmpc) {
05854       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
05855    }
05856    restart_monitor();
05857    return tmpc;
05858 }

static struct ast_frame* skinny_rtp_read ( struct skinny_subchannel sub  )  [static]

Definition at line 3490 of file chan_skinny.c.

References ast_debug, AST_FRAME_VOICE, ast_null_frame, ast_rtcp_read(), ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), ast_udptl_read(), f, ast_channel::fdno, ast_channel::nativeformats, skinny_subchannel::owner, ast_channel::readformat, skinny_subchannel::rtp, skinny_subchannel::vrtp, and ast_channel::writeformat.

Referenced by skinny_read().

03491 {
03492    struct ast_channel *ast = sub->owner;
03493    struct ast_frame *f;
03494 
03495    if (!sub->rtp) {
03496       /* We have no RTP allocated for this channel */
03497       return &ast_null_frame;
03498    }
03499 
03500    switch(ast->fdno) {
03501    case 0:
03502       f = ast_rtp_read(sub->rtp);   /* RTP Audio */
03503       break;
03504    case 1:
03505       f = ast_rtcp_read(sub->rtp);  /* RTCP Control Channel */
03506       break;
03507    case 2:
03508       f = ast_rtp_read(sub->vrtp);  /* RTP Video */
03509       break;
03510    case 3:
03511       f = ast_rtcp_read(sub->vrtp); /* RTCP Control Channel for video */
03512       break;
03513 #if 0
03514    case 5:
03515       /* Not yet supported */
03516       f = ast_udptl_read(sub->udptl);  /* UDPTL for T.38 */
03517       break;
03518 #endif
03519    default:
03520       f = &ast_null_frame;
03521    }
03522 
03523    if (ast) {
03524       /* We already hold the channel lock */
03525       if (f->frametype == AST_FRAME_VOICE) {
03526          if (f->subclass != ast->nativeformats) {
03527             ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
03528             ast->nativeformats = f->subclass;
03529             ast_set_read_format(ast, ast->readformat);
03530             ast_set_write_format(ast, ast->writeformat);
03531          }
03532       }
03533    }
03534    return f;
03535 }

static int skinny_senddigit_begin ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 3587 of file chan_skinny.c.

03588 {
03589    return -1; /* Start inband indications */
03590 }

static int skinny_senddigit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 3592 of file chan_skinny.c.

References skinny_subchannel::callid, skinny_line::instance, skinny_line::parent, skinny_subchannel::parent, skinny_device::session, skinny_line::sub, ast_channel::tech_pvt, and transmit_tone().

03593 {
03594 #if 0
03595    struct skinny_subchannel *sub = ast->tech_pvt;
03596    struct skinny_line *l = sub->parent;
03597    struct skinny_device *d = l->parent;
03598    int tmp;
03599    /* not right */
03600    sprintf(tmp, "%d", digit);
03601    transmit_tone(d->session, digit, l->instance, sub->callid);
03602 #endif
03603    return -1; /* Stop inband indications */
03604 }

static void* skinny_session ( void *  data  )  [static]

Definition at line 5680 of file chan_skinny.c.

References ast_debug, ast_inet_ntoa(), ast_verb, destroy_session(), errno, get_input(), handle_message(), skinny_req::res, s, and skinny_req_parse().

Referenced by accept_thread().

05681 {
05682    int res;
05683    struct skinny_req *req;
05684    struct skinnysession *s = data;
05685 
05686    ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
05687 
05688    for (;;) {
05689       res = get_input(s);
05690       if (res < 0) {
05691          break;
05692       }
05693 
05694       if (res > 0)
05695       {
05696          if (!(req = skinny_req_parse(s))) {
05697             destroy_session(s);
05698             return NULL;
05699          }
05700 
05701          res = handle_message(req, s);
05702          if (res < 0) {
05703             destroy_session(s);
05704             return NULL;
05705          }
05706       }
05707    }
05708    ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));
05709 
05710    if (s) 
05711       destroy_session(s);
05712    
05713    return 0;
05714 }

static int skinny_set_rtp_peer ( struct ast_channel c,
struct ast_rtp rtp,
struct ast_rtp vrtp,
struct ast_rtp trtp,
int  codecs,
int  nat_active 
) [static]

Definition at line 2360 of file chan_skinny.c.

References ast_channel::_state, ast_best_codec(), ast_codec_pref_getsize(), ast_debug, ast_inet_ntoa(), ast_rtp_get_peer(), ast_rtp_get_us(), AST_STATE_UP, media_qualifier::bitRate, ast_format_list::bits, skinny_subchannel::callid, skinny_line::canreinvite, skinny_line::capability, codec_ast2skinny(), start_media_transmission_message::conferenceId, stop_media_transmission_message::conferenceId, ast_format_list::cur_ms, skinny_req::data, htolel, skinny_line::nat, skinny_device::ourip, media_qualifier::packets, start_media_transmission_message::packetSize, skinny_line::parent, skinny_subchannel::parent, start_media_transmission_message::passThruPartyId, stop_media_transmission_message::passThruPartyId, start_media_transmission_message::payloadType, media_qualifier::precedence, skinny_line::prefs, start_media_transmission_message::qualifier, start_media_transmission_message::remoteIp, start_media_transmission_message::remotePort, req_alloc(), s, skinny_device::session, skinnydebug, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, ast_channel::tech_pvt, transmit_response(), and media_qualifier::vad.

02361 {
02362    struct skinny_subchannel *sub;
02363    struct skinny_line *l;
02364    struct skinny_device *d;
02365    struct skinnysession *s;
02366    struct ast_format_list fmt;
02367    struct sockaddr_in us;
02368    struct sockaddr_in them;
02369    struct skinny_req *req;
02370    
02371    sub = c->tech_pvt;
02372 
02373    if (c->_state != AST_STATE_UP)
02374       return 0;
02375 
02376    if (!sub) {
02377       return -1;
02378    }
02379 
02380    l = sub->parent;
02381    d = l->parent;
02382    s = d->session;
02383 
02384    if (rtp){
02385       ast_rtp_get_peer(rtp, &them);
02386 
02387       /* Shutdown any early-media or previous media on re-invite */
02388       if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02389          return -1;
02390 
02391       req->data.stopmedia.conferenceId = htolel(sub->callid);
02392       req->data.stopmedia.passThruPartyId = htolel(sub->callid);
02393       transmit_response(s, req);
02394 
02395       if (skinnydebug)
02396          ast_debug(1, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port));
02397 
02398       if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
02399          return -1;
02400 
02401       fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
02402 
02403       if (skinnydebug)
02404          ast_debug(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
02405 
02406       req->data.startmedia.conferenceId = htolel(sub->callid);
02407       req->data.startmedia.passThruPartyId = htolel(sub->callid);
02408       if (!(l->canreinvite) || (l->nat)){
02409          ast_rtp_get_us(rtp, &us);
02410          req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
02411          req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
02412       } else {
02413          req->data.startmedia.remoteIp = htolel(them.sin_addr.s_addr);
02414          req->data.startmedia.remotePort = htolel(ntohs(them.sin_port));
02415       }
02416       req->data.startmedia.packetSize = htolel(fmt.cur_ms);
02417       req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
02418       req->data.startmedia.qualifier.precedence = htolel(127);
02419       req->data.startmedia.qualifier.vad = htolel(0);
02420       req->data.startmedia.qualifier.packets = htolel(0);
02421       req->data.startmedia.qualifier.bitRate = htolel(0);
02422       transmit_response(s, req);
02423 
02424       return 0;
02425    }
02426    /* Need a return here to break the bridge */
02427    return 0;
02428 }

static void* skinny_ss ( void *  data  )  [static]

Definition at line 3258 of file chan_skinny.c.

References ast_channel::_state, ast_canmatch_extension(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_safe_sleep(), AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::callid, skinny_line::cfwdtype, ast_channel::cid, ast_callerid::cid_num, skinny_line::cid_num, ast_channel::context, ast_channel::exten, skinny_device::exten, firstdigittimeout, gendigittimeout, skinny_line::getforward, skinny_line::instance, skinny_line::lastnumberdialed, len(), LOG_WARNING, matchdigittimeout, ast_channel::name, skinny_device::name, skinny_line::name, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, s, skinny_device::session, set_callforwards(), SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_newcall(), SKINNY_REORDER, SKINNY_SILENCE, STIMULUS_FORWARDALL, skinny_line::sub, ast_channel::tech_pvt, transmit_cfwdstate(), transmit_displaynotify(), transmit_lamp_indication(), and transmit_tone().

Referenced by handle_callforward_button(), handle_offhook_message(), handle_soft_key_event_message(), and handle_stimulus_message().

03259 {
03260    struct ast_channel *c = data;
03261    struct skinny_subchannel *sub = c->tech_pvt;
03262    struct skinny_line *l = sub->parent;
03263    struct skinny_device *d = l->parent;
03264    struct skinnysession *s = d->session;
03265    int len = 0;
03266    int timeout = firstdigittimeout;
03267    int res = 0;
03268    int loop_pause = 100;
03269 
03270    ast_verb(3, "Starting simple switch on '%s@%s'\n", l->name, d->name);
03271 
03272    len = strlen(d->exten);
03273 
03274    while (len < AST_MAX_EXTENSION-1) {
03275       res = 1;  /* Assume that we will get a digit */
03276       while (strlen(d->exten) == len){
03277          ast_safe_sleep(c, loop_pause);
03278          timeout -= loop_pause;
03279          if ( (timeout -= loop_pause) <= 0){
03280              res = 0;
03281              break;
03282          }
03283       res = 1;
03284       }
03285 
03286       timeout = 0;
03287       len = strlen(d->exten);
03288 
03289       if (!ast_ignore_pattern(c->context, d->exten)) {
03290          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03291       }
03292       if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) {
03293          if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) {
03294             if (l->getforward) {
03295                /* Record this as the forwarding extension */
03296                set_callforwards(l, d->exten, l->getforward);
03297                ast_verb(3, "Setting call forward (%d) to '%s' on channel %s\n",
03298                      l->cfwdtype, d->exten, c->name);
03299                transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
03300                transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
03301                transmit_displaynotify(s, "CFwd enabled", 10);
03302                transmit_cfwdstate(s, l);
03303                ast_safe_sleep(c, 500);
03304                ast_indicate(c, -1);
03305                ast_safe_sleep(c, 1000);
03306                memset(d->exten, 0, sizeof(d->exten));
03307                len = 0;
03308                l->getforward = 0;
03309                if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03310                   ast_indicate(c, -1);
03311                   ast_hangup(c);
03312                }
03313                return NULL;
03314             } else {
03315                ast_copy_string(c->exten, d->exten, sizeof(c->exten));
03316                ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed));
03317                memset(d->exten, 0, sizeof(d->exten));
03318                skinny_newcall(c);
03319                return NULL;
03320             }
03321          } else {
03322             /* It's a match, but they just typed a digit, and there is an ambiguous match,
03323                so just set the timeout to matchdigittimeout and wait some more */
03324             timeout = matchdigittimeout;
03325          }
03326       } else if (res == 0) {
03327          ast_debug(1, "Not enough digits (%s) (and no ambiguous match)...\n", d->exten);
03328          memset(d->exten, 0, sizeof(d->exten));
03329          transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
03330          if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03331             ast_indicate(c, -1);
03332             ast_hangup(c);
03333          }
03334          return NULL;
03335       } else if (!ast_canmatch_extension(c, c->context, d->exten, 1, c->cid.cid_num) &&
03336             ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
03337          ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten, c->cid.cid_num ? c->cid.cid_num : "<Unknown Caller>", c->context);
03338          memset(d->exten, 0, sizeof(d->exten));
03339          transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
03340          /* hang out for 3 seconds to let congestion play */
03341          ast_safe_sleep(c, 3000);
03342          break;
03343       }
03344       if (!timeout) {
03345          timeout = gendigittimeout;
03346       }
03347       if (len && !ast_ignore_pattern(c->context, d->exten)) {
03348          ast_indicate(c, -1);
03349       }
03350    }
03351    if (c)
03352       ast_hangup(c);
03353    memset(d->exten, 0, sizeof(d->exten));
03354    return NULL;
03355 }

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

Definition at line 3922 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_data::activatecallplane, AST_CONTROL_UNHOLD, ast_debug, ast_queue_control(), skinny_req::data, htolel, skinny_line::instance, activate_call_plane_message::lineInstance, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, req_alloc(), s, skinny_device::session, SKINNY_LAMP_ON, skinnydebug, STIMULUS_LINE, skinny_line::sub, transmit_connect(), transmit_lamp_indication(), and transmit_response().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

03923 {
03924    struct skinny_line *l = sub->parent;
03925    struct skinny_device *d = l->parent;
03926    struct skinnysession *s = d->session;
03927    struct skinny_req *req;
03928 
03929    /* Don't try to unhold a channel that doesn't exist */
03930    if (!sub || !sub->owner)
03931       return 0;
03932 
03933    /* Channel is on hold, so we will unhold */
03934    if (skinnydebug)
03935       ast_debug(1, "Taking off Hold(%d)\n", l->instance);
03936 
03937    ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03938 
03939    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
03940       return 0;
03941 
03942    req->data.activatecallplane.lineInstance = htolel(l->instance);
03943    transmit_response(s, req);
03944 
03945    transmit_connect(s, sub);
03946    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
03947    sub->onhold = 0;
03948    return 1;
03949 }

static int skinny_unregister ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 1798 of file chan_skinny.c.

References ast_device_state_changed(), ast_extension_state_del(), skinny_device::lines, skinny_device::name, skinny_line::name, skinny_line::next, skinny_speeddial::next, skinny_device::registered, s, skinny_device::session, skinny_device::speeddials, skinny_speeddial::stateid, and unregister_exten().

Referenced by get_input(), handle_unregister_message(), and transmit_response().

01799 {
01800    struct skinny_device *d;
01801    struct skinny_line *l;
01802    struct skinny_speeddial *sd;
01803 
01804    d = s->device;
01805 
01806    if (d) {
01807       d->session = NULL;
01808       d->registered = 0;
01809 
01810       for (sd = d->speeddials; sd; sd = sd->next) {
01811          if (sd->stateid > -1)
01812             ast_extension_state_del(sd->stateid, NULL);
01813       }
01814       for (l = d->lines; l; l = l->next) {
01815          unregister_exten(l);
01816          ast_device_state_changed("Skinny/%s@%s", l->name, d->name);
01817       }
01818    }
01819 
01820    return -1; /* main loop will destroy the session */
01821 }

static int skinny_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 3547 of file chan_skinny.c.

References AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, skinny_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, skinny_subchannel::rtp, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.

03548 {
03549    struct skinny_subchannel *sub = ast->tech_pvt;
03550    int res = 0;
03551    if (frame->frametype != AST_FRAME_VOICE) {
03552       if (frame->frametype == AST_FRAME_IMAGE) {
03553          return 0;
03554       } else {
03555          ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
03556          return 0;
03557       }
03558    } else {
03559       if (!(frame->subclass & ast->nativeformats)) {
03560          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
03561             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
03562          return -1;
03563       }
03564    }
03565    if (sub) {
03566       ast_mutex_lock(&sub->lock);
03567       if (sub->rtp) {
03568          res = ast_rtp_write(sub->rtp, frame);
03569       }
03570       ast_mutex_unlock(&sub->lock);
03571    }
03572    return res;
03573 }

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 3195 of file chan_skinny.c.

References ast_channel_set_fd(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_setnat(), ast_rtp_setqos(), bindaddr, cos_audio, cos_video, io, skinny_subchannel::lock, skinny_line::nat, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_line::prefs, skinny_subchannel::rtp, skinny_device::session, skinny_line::sub, tos_audio, tos_video, transmit_connect(), and skinny_subchannel::vrtp.

03196 {
03197    struct skinny_line *l = sub->parent;
03198    struct skinny_device *d = l->parent;
03199    int hasvideo = 0;
03200 
03201    ast_mutex_lock(&sub->lock);
03202    /* Allocate the RTP */
03203    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
03204    if (hasvideo)
03205       sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
03206    
03207    if (sub->rtp && sub->owner) {
03208       ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
03209       ast_channel_set_fd(sub->owner, 1, ast_rtcp_fd(sub->rtp));
03210    }
03211    if (hasvideo && sub->vrtp && sub->owner) {
03212       ast_channel_set_fd(sub->owner, 2, ast_rtp_fd(sub->vrtp));
03213       ast_channel_set_fd(sub->owner, 3, ast_rtcp_fd(sub->vrtp));
03214    }
03215    if (sub->rtp) {
03216       ast_rtp_setqos(sub->rtp, tos_audio, cos_audio, "Skinny RTP");
03217       ast_rtp_setnat(sub->rtp, l->nat);
03218    }
03219    if (sub->vrtp) {
03220       ast_rtp_setqos(sub->vrtp, tos_video, cos_video, "Skinny VRTP");
03221       ast_rtp_setnat(sub->vrtp, l->nat);
03222    }
03223    /* Set Frame packetization */
03224    if (sub->rtp)
03225       ast_rtp_codec_setpref(sub->rtp, &l->prefs);
03226 
03227    /* Create the RTP connection */
03228    transmit_connect(d->session, sub);
03229    ast_mutex_unlock(&sub->lock);
03230 }

static void transmit_callinfo ( struct skinnysession s,
const char *  fromname,
const char *  fromnum,
const char *  toname,
const char *  tonum,
int  instance,
int  callid,
int  calltype 
) [static]

Definition at line 1887 of file chan_skinny.c.

References ast_copy_string(), ast_debug, CALL_INFO_MESSAGE, call_info_message::calledParty, call_info_message::calledPartyName, skinny_data::callinfo, call_info_message::callingParty, call_info_message::callingPartyName, skinny_req::data, htolel, call_info_message::instance, call_info_message::reference, req_alloc(), s, skinnydebug, transmit_response(), and call_info_message::type.

Referenced by skinny_answer(), skinny_call(), and skinny_indicate().

01888 {
01889    struct skinny_req *req;
01890 
01891    if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
01892       return;
01893 
01894    if (skinnydebug)
01895          ast_debug(1, "Setting Callinfo to %s(%s) from %s(%s) on %s(%d)\n", fromname, fromnum, toname, tonum, s->device->name, instance);
01896 
01897    if (fromname) {
01898       ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
01899    }
01900    if (fromnum) {
01901       ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
01902    }
01903    if (toname) {
01904       ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
01905    }
01906    if (tonum) {
01907       ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
01908    }
01909    req->data.callinfo.instance = htolel(instance);
01910    req->data.callinfo.reference = htolel(callid);
01911    req->data.callinfo.type = htolel(calltype);
01912    transmit_response(s, req);
01913 }

static void transmit_callstate ( struct skinnysession s,
int  instance,
int  state,
unsigned  callid 
) [static]

Definition at line 2103 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_data::activatecallplane, CALL_STATE_MESSAGE, call_state_message::callReference, call_state_message::callState, skinny_data::callstate, CLOSE_RECEIVE_CHANNEL_MESSAGE, skinny_data::closereceivechannel, stop_media_transmission_message::conferenceId, close_receive_channel_message::conferenceId, skinny_req::data, htolel, KEYDEF_ONHOOK, activate_call_plane_message::lineInstance, call_state_message::lineInstance, close_receive_channel_message::partyId, stop_media_transmission_message::passThruPartyId, req_alloc(), s, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, transmit_displaypromptstatus(), transmit_response(), transmit_selectsoftkeys(), and transmit_speaker_mode().

Referenced by handle_callforward_button(), handle_enbloc_call_message(), handle_offhook_message(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_answer(), skinny_call(), skinny_extensionstate_cb(), skinny_hangup(), and skinny_indicate().

02104 {
02105    struct skinny_req *req;
02106 
02107    if (state == SKINNY_ONHOOK) {
02108       if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
02109          return;
02110 
02111       req->data.closereceivechannel.conferenceId = htolel(callid);
02112       req->data.closereceivechannel.partyId = htolel(callid);
02113       transmit_response(s, req);
02114 
02115       if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02116          return;
02117 
02118       req->data.stopmedia.conferenceId = htolel(callid);
02119       req->data.stopmedia.passThruPartyId = htolel(callid);
02120       transmit_response(s, req);
02121 
02122       transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
02123 
02124       transmit_displaypromptstatus(s, NULL, 0, instance, callid);
02125    }
02126 
02127    if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
02128       return;
02129 
02130    req->data.callstate.callState = htolel(state);
02131    req->data.callstate.lineInstance = htolel(instance);
02132    req->data.callstate.callReference = htolel(callid);
02133    transmit_response(s, req);
02134 
02135    if (state == SKINNY_ONHOOK) {
02136       transmit_selectsoftkeys(s, 0, 0, KEYDEF_ONHOOK);
02137    }
02138 
02139    if (state == SKINNY_OFFHOOK || state == SKINNY_ONHOOK) {
02140       if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02141          return;
02142 
02143       req->data.activatecallplane.lineInstance = htolel(instance);
02144       transmit_response(s, req);
02145    }
02146 }

static void transmit_cfwdstate ( struct skinnysession s,
struct skinny_line l 
) [static]

Definition at line 2149 of file chan_skinny.c.

References forward_stat_message::activeforward, ast_copy_string(), ast_strlen_zero(), skinny_line::call_forward_all, skinny_line::call_forward_busy, skinny_line::call_forward_noanswer, skinny_line::cfwdtype, skinny_req::data, FORWARD_STAT_MESSAGE, skinny_data::forwardstat, forward_stat_message::fwdall, forward_stat_message::fwdallnum, forward_stat_message::fwdbusy, forward_stat_message::fwdbusynum, forward_stat_message::fwdnoanswer, forward_stat_message::fwdnoanswernum, htolel, skinny_line::instance, forward_stat_message::lineNumber, req_alloc(), s, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, and transmit_response().

Referenced by handle_callforward_button(), and skinny_ss().

02150 {
02151    struct skinny_req *req;
02152    int anyon = 0;
02153 
02154    if (!(req = req_alloc(sizeof(struct forward_stat_message), FORWARD_STAT_MESSAGE)))
02155       return;
02156 
02157    if (l->cfwdtype & SKINNY_CFWD_ALL) {
02158       if (!ast_strlen_zero(l->call_forward_all)) {
02159          ast_copy_string(req->data.forwardstat.fwdallnum, l->call_forward_all, sizeof(req->data.forwardstat.fwdallnum));
02160          req->data.forwardstat.fwdall = htolel(1);
02161          anyon++;
02162       } else {
02163          req->data.forwardstat.fwdall = htolel(0);
02164       }
02165    }
02166    if (l->cfwdtype & SKINNY_CFWD_BUSY) {
02167       if (!ast_strlen_zero(l->call_forward_busy)) {
02168          ast_copy_string(req->data.forwardstat.fwdbusynum, l->call_forward_busy, sizeof(req->data.forwardstat.fwdbusynum));
02169          req->data.forwardstat.fwdbusy = htolel(1);
02170          anyon++;
02171       } else {
02172          req->data.forwardstat.fwdbusy = htolel(0);
02173       }
02174    }
02175    if (l->cfwdtype & SKINNY_CFWD_NOANSWER) {
02176       if (!ast_strlen_zero(l->call_forward_noanswer)) {
02177          ast_copy_string(req->data.forwardstat.fwdnoanswernum, l->call_forward_noanswer, sizeof(req->data.forwardstat.fwdnoanswernum));
02178          req->data.forwardstat.fwdnoanswer = htolel(1);
02179          anyon++;
02180       } else {
02181          req->data.forwardstat.fwdnoanswer = htolel(0);
02182       }
02183    }
02184    req->data.forwardstat.lineNumber = htolel(l->instance);
02185    if (anyon)
02186       req->data.forwardstat.activeforward = htolel(7);
02187    else
02188       req->data.forwardstat.activeforward = htolel(0);
02189 
02190    transmit_response(s, req);
02191 }

static void transmit_connect ( struct skinnysession s,
struct skinny_subchannel sub 
) [static]

Definition at line 1915 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), open_receive_channel_message::bitrate, ast_format_list::bits, skinny_subchannel::callid, open_receive_channel_message::capability, skinny_line::capability, codec_ast2skinny(), open_receive_channel_message::conferenceId, ast_format_list::cur_ms, skinny_req::data, open_receive_channel_message::echo, htolel, OPEN_RECEIVE_CHANNEL_MESSAGE, skinny_data::openreceivechannel, open_receive_channel_message::packets, skinny_subchannel::parent, open_receive_channel_message::partyId, skinny_line::prefs, req_alloc(), s, skinny_line::sub, and transmit_response().

Referenced by skinny_unhold(), and start_rtp().

01916 {
01917    struct skinny_req *req;
01918    struct skinny_line *l = sub->parent;
01919    struct ast_format_list fmt;
01920 
01921    if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
01922       return;
01923 
01924    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
01925 
01926    req->data.openreceivechannel.conferenceId = htolel(sub->callid);
01927    req->data.openreceivechannel.partyId = htolel(sub->callid);
01928    req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
01929    req->data.openreceivechannel.capability = htolel(codec_ast2skinny(fmt.bits));
01930    req->data.openreceivechannel.echo = htolel(0);
01931    req->data.openreceivechannel.bitrate = htolel(0);
01932    transmit_response(s, req);
01933 }

static void transmit_dialednumber ( struct skinnysession s,
const char *  text,
int  instance,
int  callid 
) [static]

Definition at line 2089 of file chan_skinny.c.

References ast_copy_string(), dialed_number_message::callReference, skinny_req::data, DIALED_NUMBER_MESSAGE, dialed_number_message::dialedNumber, skinny_data::dialednumber, htolel, dialed_number_message::lineInstance, req_alloc(), s, and transmit_response().

Referenced by skinny_answer(), and skinny_indicate().

02090 {
02091    struct skinny_req *req;
02092 
02093    if (!(req = req_alloc(sizeof(struct dialed_number_message), DIALED_NUMBER_MESSAGE)))
02094       return;
02095 
02096    ast_copy_string(req->data.dialednumber.dialedNumber, text, sizeof(req->data.dialednumber.dialedNumber));
02097    req->data.dialednumber.lineInstance = htolel(instance);
02098    req->data.dialednumber.callReference = htolel(callid);
02099 
02100    transmit_response(s, req);
02101 }

static void transmit_displaymessage ( struct skinnysession s,
const char *  text,
int  instance,
int  reference 
) [static]

Definition at line 2017 of file chan_skinny.c.

References ast_copy_string(), ast_debug, CLEAR_DISPLAY_MESSAGE, skinny_req::data, skinny_data::displaytext, DISPLAYTEXT_MESSAGE, req_alloc(), s, skinnydebug, displaytext_message::text, and transmit_response().

Referenced by handle_callforward_button(), handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), and handle_stimulus_message().

02018 {
02019    struct skinny_req *req;
02020 
02021    if (text == 0) {
02022       if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
02023          return;
02024 
02025       //what do we want hear CLEAR_DISPLAY_MESSAGE or CLEAR_PROMPT_STATUS???
02026       //if we are clearing the display, it appears there is no instance and refernece info (size 0)
02027       //req->data.clearpromptstatus.lineInstance = instance;
02028       //req->data.clearpromptstatus.callReference = reference;
02029 
02030       if (skinnydebug)
02031          ast_debug(1, "Clearing Display\n");
02032    } else {
02033       if (!(req = req_alloc(sizeof(struct displaytext_message), DISPLAYTEXT_MESSAGE)))
02034          return;
02035 
02036       ast_copy_string(req->data.displaytext.text, text, sizeof(req->data.displaytext.text));
02037       if (skinnydebug)
02038          ast_debug(1, "Displaying message '%s'\n", req->data.displaytext.text);
02039    }
02040 
02041    transmit_response(s, req);
02042 }

static void transmit_displaynotify ( struct skinnysession s,
const char *  text,
int  t 
) [static]

Definition at line 2044 of file chan_skinny.c.

References ast_copy_string(), ast_debug, skinny_req::data, DISPLAY_NOTIFY_MESSAGE, display_notify_message::displayMessage, skinny_data::displaynotify, display_notify_message::displayTimeout, htolel, req_alloc(), s, skinnydebug, and transmit_response().

Referenced by handle_callforward_button(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_ss().

02045 {
02046    struct skinny_req *req;
02047 
02048    if (!(req = req_alloc(sizeof(struct display_notify_message), DISPLAY_NOTIFY_MESSAGE)))
02049       return;
02050 
02051    ast_copy_string(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage));
02052    req->data.displaynotify.displayTimeout = htolel(t);
02053 
02054    if (skinnydebug)
02055       ast_debug(1, "Displaying notify '%s'\n", text);
02056 
02057    transmit_response(s, req);
02058 }

static void transmit_displaypromptstatus ( struct skinnysession s,
const char *  text,
int  t,
int  instance,
int  callid 
) [static]

Definition at line 2060 of file chan_skinny.c.

References ast_copy_string(), ast_debug, display_prompt_status_message::callReference, clear_prompt_message::callReference, CLEAR_PROMPT_MESSAGE, skinny_data::clearpromptstatus, skinny_req::data, DISPLAY_PROMPT_STATUS_MESSAGE, skinny_data::displaypromptstatus, htolel, display_prompt_status_message::lineInstance, clear_prompt_message::lineInstance, display_prompt_status_message::messageTimeout, display_prompt_status_message::promptMessage, req_alloc(), s, skinnydebug, and transmit_response().

Referenced by handle_stimulus_message(), skinny_answer(), skinny_call(), skinny_indicate(), and transmit_callstate().

02061 {
02062    struct skinny_req *req;
02063 
02064    if (text == 0) {
02065       if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
02066          return;
02067 
02068       req->data.clearpromptstatus.lineInstance = htolel(instance);
02069       req->data.clearpromptstatus.callReference = htolel(callid);
02070 
02071       if (skinnydebug)
02072          ast_debug(1, "Clearing Prompt\n");
02073    } else {
02074       if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
02075          return;
02076 
02077       ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
02078       req->data.displaypromptstatus.messageTimeout = htolel(t);
02079       req->data.displaypromptstatus.lineInstance = htolel(instance);
02080       req->data.displaypromptstatus.callReference = htolel(callid);
02081 
02082       if (skinnydebug)
02083          ast_debug(1, "Displaying Prompt Status '%s'\n", text);
02084    }
02085 
02086    transmit_response(s, req);
02087 }

static void transmit_lamp_indication ( struct skinnysession s,
int  stimulus,
int  instance,
int  indication 
) [static]

Definition at line 1979 of file chan_skinny.c.

References skinny_req::data, set_lamp_message::deviceStimulus, htolel, req_alloc(), s, SET_LAMP_MESSAGE, skinny_data::setlamp, set_lamp_message::stimulus, set_lamp_message::stimulusInstance, and transmit_response().

Referenced by do_housekeeping(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_call(), skinny_extensionstate_cb(), skinny_hangup(), skinny_hold(), skinny_ss(), and skinny_unhold().

01980 {
01981    struct skinny_req *req;
01982 
01983    if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
01984       return;
01985 
01986    req->data.setlamp.stimulus = htolel(stimulus);
01987    req->data.setlamp.stimulusInstance = htolel(instance);
01988    req->data.setlamp.deviceStimulus = htolel(indication);
01989    transmit_response(s, req);
01990 }

static int transmit_response ( struct skinnysession s,
struct skinny_req req 
) [static]

Definition at line 1823 of file chan_skinny.c.

References ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), skinny_req::data, skinny_req::e, errno, skinny_req::len, letohl, LOG_VERBOSE, LOG_WARNING, s, skinny_header_size, SKINNY_MAX_PACKET, skinny_unregister(), and skinnydebug.

01824 {
01825    int res = 0;
01826 
01827    if (!s) {
01828       ast_log(LOG_WARNING, "Asked to transmit to a non-existent session!\n");
01829       return -1;
01830    }
01831 
01832    ast_mutex_lock(&s->lock);
01833 
01834    if (skinnydebug)
01835       ast_log(LOG_VERBOSE, "writing packet type %04X (%d bytes) to socket %d\n", letohl(req->e), letohl(req->len)+8, s->fd);
01836 
01837    if (letohl(req->len > SKINNY_MAX_PACKET) || letohl(req->len < 0)) {
01838       ast_log(LOG_WARNING, "transmit_response: the length of the request is out of bounds\n");
01839       ast_mutex_unlock(&s->lock);
01840       return -1;
01841    }
01842 
01843    memset(s->outbuf,0,sizeof(s->outbuf));
01844    memcpy(s->outbuf, req, skinny_header_size);
01845    memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
01846 
01847    res = write(s->fd, s->outbuf, letohl(req->len)+8);
01848    
01849    if (res != letohl(req->len)+8) {
01850       ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
01851       if (res == -1) {
01852          if (skinnydebug)
01853             ast_log(LOG_WARNING, "Transmit: Skinny Client was lost, unregistering\n");
01854          skinny_unregister(NULL, s);
01855       }
01856       
01857    }
01858    
01859    ast_free(req);
01860    ast_mutex_unlock(&s->lock);
01861    return 1;
01862 }

static void transmit_ringer_mode ( struct skinnysession s,
int  mode 
) [static]

Definition at line 1992 of file chan_skinny.c.

References ast_debug, skinny_req::data, htolel, req_alloc(), set_ringer_message::ringerMode, s, SET_RINGER_MESSAGE, skinny_data::setringer, skinnydebug, transmit_response(), set_ringer_message::unknown1, and set_ringer_message::unknown2.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_call(), and skinny_hangup().

01993 {
01994    struct skinny_req *req;
01995 
01996    if (skinnydebug)
01997       ast_debug(1, "Setting ringer mode to '%d'.\n", mode);
01998 
01999    if (!(req = req_alloc(sizeof(struct set_ringer_message), SET_RINGER_MESSAGE)))
02000       return;
02001 
02002    req->data.setringer.ringerMode = htolel(mode);
02003    /* XXX okay, I don't quite know what this is, but here's what happens (on a 7960).
02004       Note: The phone will always show as ringing on the display.
02005 
02006       1: phone will audibly ring over and over
02007       2: phone will audibly ring only once
02008       any other value, will NOT cause the phone to audibly ring
02009    */
02010    req->data.setringer.unknown1 = htolel(1);
02011    /* XXX the value here doesn't seem to change anything.  Must be higher than 0.
02012       Perhaps a packet capture can shed some light on this. */
02013    req->data.setringer.unknown2 = htolel(1);
02014    transmit_response(s, req);
02015 }

static void transmit_selectsoftkeys ( struct skinnysession s,
int  instance,
int  callid,
int  softkey 
) [static]

Definition at line 1965 of file chan_skinny.c.

References skinny_req::data, htolel, select_soft_keys_message::instance, select_soft_keys_message::reference, req_alloc(), s, SELECT_SOFT_KEYS_MESSAGE, skinny_data::selectsoftkey, select_soft_keys_message::softKeySetIndex, transmit_response(), and select_soft_keys_message::validKeyMask.

Referenced by handle_callforward_button(), handle_offhook_message(), handle_soft_key_event_message(), handle_soft_key_set_req_message(), handle_stimulus_message(), skinny_answer(), skinny_call(), and transmit_callstate().

01966 {
01967    struct skinny_req *req;
01968 
01969    if (!(req = req_alloc(sizeof(struct select_soft_keys_message), SELECT_SOFT_KEYS_MESSAGE)))
01970       return;
01971 
01972    req->data.selectsoftkey.instance = htolel(instance);
01973    req->data.selectsoftkey.reference = htolel(callid);
01974    req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
01975    req->data.selectsoftkey.validKeyMask = htolel(0xFFFFFFFF);
01976    transmit_response(s, req);
01977 }

static void transmit_speaker_mode ( struct skinnysession s,
int  mode 
) [static]

Definition at line 1864 of file chan_skinny.c.

References skinny_req::data, htolel, set_speaker_message::mode, req_alloc(), s, SET_SPEAKER_MESSAGE, skinny_data::setspeaker, and transmit_response().

Referenced by handle_callforward_button(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_hangup(), and transmit_callstate().

01865 {
01866    struct skinny_req *req;
01867 
01868    if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
01869       return;
01870 
01871    req->data.setspeaker.mode = htolel(mode);
01872    transmit_response(s, req);
01873 }

static void transmit_tone ( struct skinnysession s,
int  tone,
int  instance,
int  reference 
) [static]

Definition at line 1935 of file chan_skinny.c.

References skinny_req::data, htolel, stop_tone_message::instance, start_tone_message::instance, stop_tone_message::reference, start_tone_message::reference, req_alloc(), s, SKINNY_NOTONE, START_TONE_MESSAGE, skinny_data::starttone, STOP_TONE_MESSAGE, skinny_data::stoptone, start_tone_message::tone, and transmit_response().

Referenced by handle_callforward_button(), handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_answer(), skinny_hangup(), skinny_indicate(), skinny_newcall(), skinny_senddigit_end(), and skinny_ss().

01936 {
01937    struct skinny_req *req;
01938 
01939    if (tone == SKINNY_NOTONE) {
01940       /* This is bad, mmm'kay? */
01941       return;
01942    }
01943 
01944    if (tone > 0) {
01945       if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
01946          return;
01947       req->data.starttone.tone = htolel(tone);
01948       req->data.starttone.instance = htolel(instance);
01949       req->data.starttone.reference = htolel(reference);
01950    } else {
01951       if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
01952          return;
01953       req->data.stoptone.instance = htolel(instance);
01954       req->data.stoptone.reference = htolel(reference);
01955    }
01956 
01957    //Bad, tone is already set so this is redundant and a change to the if above
01958    //may lead to issues where we try to set a tone to a stop_tone_message
01959    //if (tone > 0) {
01960    // req->data.starttone.tone = htolel(tone);
01961    //}
01962    transmit_response(s, req);
01963 }

static int unload_module ( void   )  [static]

Definition at line 6133 of file chan_skinny.c.

References accept_t, skinny_subchannel::alreadygone, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_context_destroy(), ast_context_find(), ast_event_unsubscribe(), ast_free, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_skinny, delete_devices(), skinnysession::device, skinnysession::fd, skinny_device::lines, skinnysession::lock, skinny_subchannel::lock, skinny_line::lock, monitor_thread, monlock, skinny_line::mwi_event_sub, netlock, skinny_subchannel::next, skinny_line::next, skinny_device::next, skinny_subchannel::owner, s, sched_context_destroy(), sessionlock, skinny_rtp, skinny_tech, skinnysock, skinny_line::sub, and used_context.

06134 {
06135    struct skinnysession *s, *slast;
06136    struct skinny_device *d;
06137    struct skinny_line *l;
06138    struct skinny_subchannel *sub;
06139    struct ast_context *con;
06140 
06141    ast_mutex_lock(&sessionlock);
06142    /* Destroy all the interfaces and free their memory */
06143    s = sessions;
06144    while(s) {
06145       slast = s;
06146       s = s->next;
06147       for (d = slast->device; d; d = d->next) {
06148          for (l = d->lines; l; l = l->next) {
06149             ast_mutex_lock(&l->lock);
06150             for (sub = l->sub; sub; sub = sub->next) {
06151                ast_mutex_lock(&sub->lock);
06152                if (sub->owner) {
06153                   sub->alreadygone = 1;
06154                   ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
06155                }
06156                ast_mutex_unlock(&sub->lock);
06157             }
06158             if (l->mwi_event_sub)
06159                ast_event_unsubscribe(l->mwi_event_sub);
06160             ast_mutex_unlock(&l->lock);
06161          }
06162       }
06163       if (slast->fd > -1)
06164          close(slast->fd);
06165       ast_mutex_destroy(&slast->lock);
06166       ast_free(slast);
06167    }
06168    sessions = NULL;
06169    ast_mutex_unlock(&sessionlock);
06170 
06171    delete_devices();
06172 
06173    ast_mutex_lock(&monlock);
06174    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
06175       pthread_cancel(monitor_thread);
06176       pthread_kill(monitor_thread, SIGURG);
06177       pthread_join(monitor_thread, NULL);
06178    }
06179    monitor_thread = AST_PTHREADT_STOP;
06180    ast_mutex_unlock(&monlock);
06181 
06182    ast_mutex_lock(&netlock);
06183    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
06184       pthread_cancel(accept_t);
06185       pthread_kill(accept_t, SIGURG);
06186       pthread_join(accept_t, NULL);
06187    }
06188    accept_t = AST_PTHREADT_STOP;
06189    ast_mutex_unlock(&netlock);
06190 
06191    ast_rtp_proto_unregister(&skinny_rtp);
06192    ast_channel_unregister(&skinny_tech);
06193    ast_cli_unregister_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
06194 
06195    close(skinnysock);
06196    if (sched)
06197       sched_context_destroy(sched);
06198 
06199    con = ast_context_find(used_context);
06200    if (con)
06201       ast_context_destroy(con, "Skinny");
06202    
06203    return 0;
06204 }

static void unregister_exten ( struct skinny_line l  )  [static]

Definition at line 1730 of file chan_skinny.c.

References ast_context_find(), ast_context_remove_extension(), ast_copy_string(), ast_log(), ast_strlen_zero(), context, ext, LOG_WARNING, skinny_line::name, regcontext, skinny_line::regexten, S_OR, and strsep().

Referenced by skinny_unregister().

01731 {
01732    char multi[256];
01733    char *stringp, *ext, *context;
01734 
01735    if (ast_strlen_zero(regcontext))
01736       return;
01737 
01738    ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
01739    stringp = multi;
01740    while ((ext = strsep(&stringp, "&"))) {
01741       if ((context = strchr(ext, '@'))) {
01742          *context++ = '\0';   /* split ext@context */
01743          if (!ast_context_find(context)) {
01744             ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
01745             continue;
01746          }
01747       } else {
01748          context = regcontext;
01749       }
01750       ast_context_remove_extension(context, ext, 1, NULL);
01751    }
01752 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Skinny Client Control Protocol (Skinny)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static]

Definition at line 6209 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 959 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 963 of file chan_skinny.c.

Referenced by reload_config(), and unload_module().

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 983 of file chan_skinny.c.

struct ast_hostent ahp

Definition at line 960 of file chan_skinny.c.

Referenced by __ast_http_load(), __init_manager(), __set_address_from_contact(), ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_parse_arg(), check_via(), create_addr(), dnsmgr_refresh(), festival_exec(), gtalk_load_config(), gtalk_update_stun(), handle_cli_udptl_debug_deprecated(), handle_cli_udptl_set_debug(), jingle_load_config(), jingle_update_stun(), launch_netscript(), parse_register_contact(), process_sdp(), realtime_peer(), realtime_user(), reload_config(), rtcp_do_debug_ip(), rtp_do_debug_ip(), set_destination(), and sip_do_debug_ip().

int amaflags = 0 [static]

Definition at line 986 of file chan_skinny.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 6209 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 956 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 987 of file chan_skinny.c.

Referenced by skinny_new().

int callreturn = 0 [static]

Definition at line 976 of file chan_skinny.c.

int callwaiting = 0 [static]

Definition at line 975 of file chan_skinny.c.

int cancallforward = 0 [static]

Definition at line 981 of file chan_skinny.c.

int canreinvite = 0 [static]

Definition at line 988 of file chan_skinny.c.

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 969 of file chan_skinny.c.

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 968 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 2942 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_skinny_set_debug_deprecated = { .handler = handle_skinny_set_debug_deprecated , .summary = "Enable/Disable Skinny debugging" ,__VA_ARGS__ } [static]

Definition at line 2941 of file chan_skinny.c.

const char config[] = "skinny.conf" [static]

Definition at line 75 of file chan_skinny.c.

char context[AST_MAX_CONTEXT] = "default" [static]

Definition at line 964 of file chan_skinny.c.

struct ast_threadstorage control2str_threadbuf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_control2str_threadbuf , .custom_init = NULL , } [static]

Definition at line 161 of file chan_skinny.c.

Referenced by control2str().

unsigned int cos = 0 [static]

Definition at line 97 of file chan_skinny.c.

unsigned int cos_audio = 0 [static]

Definition at line 98 of file chan_skinny.c.

unsigned int cos_video = 0 [static]

Definition at line 99 of file chan_skinny.c.

Referenced by reload_config(), and start_rtp().

ast_group_t cur_callergroup = 0 [static]

Definition at line 972 of file chan_skinny.c.

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 973 of file chan_skinny.c.

char date_format[6] = "D-M-Y" [static]

Definition at line 105 of file chan_skinny.c.

Referenced by handle_register_message(), handle_skinny_show_settings(), and reload_config().

int default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW [static]

Definition at line 77 of file chan_skinny.c.

Referenced by build_device(), reload_config(), and skinny_new().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 149 of file chan_skinny.c.

struct ast_codec_pref default_prefs [static]

Definition at line 78 of file chan_skinny.c.

struct ast_threadstorage device2str_threadbuf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_device2str_threadbuf , .custom_init = NULL , } [static]

Definition at line 158 of file chan_skinny.c.

Referenced by device2str().

ast_mutex_t devicelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 1107 of file chan_skinny.c.

Referenced by build_device(), delete_devices(), find_line_by_name(), find_subchannel_by_name(), handle_line_state_req_message(), handle_skinny_reset(), handle_skinny_show_device(), handle_skinny_show_devices(), handle_skinny_show_line(), handle_skinny_show_lines(), key_main_page(), key_select_extension(), rcv_mac_addr(), reload_config(), skinny_register(), and unistim_register().

struct skinny_device * devices [static]

Referenced by build_device(), change_favorite_icon(), complete_skinny_devices(), complete_skinny_show_line(), delete_devices(), find_line_by_name(), find_subchannel_by_name(), finish_bookmark(), handle_skinny_reset(), handle_skinny_show_device(), handle_skinny_show_devices(), handle_skinny_show_line(), handle_skinny_show_lines(), key_select_extension(), rcv_mac_addr(), reload_config(), skinny_register(), unistim_info(), and unistim_register().

int firstdigittimeout = 16000 [static]

Definition at line 1118 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1121 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 156 of file chan_skinny.c.

struct hostent* hp

Definition at line 961 of file chan_skinny.c.

Referenced by __ast_http_load(), __init_manager(), __set_address_from_contact(), ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_gethostbyname(), ast_parse_arg(), build_peer(), check_via(), connect_sphinx(), create_addr(), dnsmgr_refresh(), get_ip_and_port_from_sdp(), gtalk_load_config(), gtalk_update_stun(), handle_cli_udptl_debug_deprecated(), handle_cli_udptl_set_debug(), iax_template_parse(), jingle_load_config(), jingle_update_stun(), launch_netscript(), parse_register_contact(), process_sdp(), realtime_peer(), realtime_user(), reload_config(), rtcp_do_debug_ip(), rtp_do_debug_ip(), set_config(), set_destination(), and sip_do_debug_ip().

int immediate = 0 [static]

Definition at line 974 of file chan_skinny.c.

struct io_context* io [static]

Definition at line 1097 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 101 of file chan_skinny.c.

Referenced by get_input(), handle_register_message(), handle_skinny_show_settings(), and reload_config().

char language[MAX_LANGUAGE] = "" [static]

Definition at line 965 of file chan_skinny.c.

char linelabel[AST_MAX_EXTENSION] = "" [static]

Definition at line 970 of file chan_skinny.c.

Referenced by build_device().

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 984 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 1124 of file chan_skinny.c.

char mohinterpret[MAX_MUSICCLASS] = "default" [static]

Definition at line 966 of file chan_skinny.c.

char mohsuggest[MAX_MUSICCLASS] = "" [static]

Definition at line 967 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 1115 of file chan_skinny.c.

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 1101 of file chan_skinny.c.

int mwiblink = 0 [static]

Definition at line 978 of file chan_skinny.c.

Referenced by build_device().

int nat = 0 [static]

Definition at line 971 of file chan_skinny.c.

ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 1103 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 957 of file chan_skinny.c.

int ourport [static]

Definition at line 958 of file chan_skinny.c.

char regcontext[AST_MAX_CONTEXT] [static]

Definition at line 104 of file chan_skinny.c.

char regexten[AST_MAX_EXTENSION] [static]

Definition at line 985 of file chan_skinny.c.

Referenced by build_device(), and build_peer().

struct sched_context* sched = NULL [static]

Definition at line 1096 of file chan_skinny.c.

ast_mutex_t sessionlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 1105 of file chan_skinny.c.

Referenced by accept_thread(), close_client(), create_client(), destroy_session(), do_monitor(), unistim_info(), unistimsock_read(), and unload_module().

struct skinnysession * sessions [static]

int skinny_header_size = 12

Definition at line 947 of file chan_skinny.c.

Referenced by skinny_req_parse(), and transmit_response().

struct ast_rtp_protocol skinny_rtp [static]

Definition at line 2430 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1279 of file chan_skinny.c.

Referenced by load_module(), skinny_new(), and unload_module().

int skinnydebug = 0 [static]

Definition at line 953 of file chan_skinny.c.

Referenced by accept_thread(), do_housekeeping(), get_input(), handle_alarm_message(), handle_callforward_button(), handle_capabilities_res_message(), handle_enbloc_call_message(), handle_keypad_button_message(), handle_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_skinny_set_debug(), handle_skinny_set_debug_deprecated(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_answer(), skinny_call(), skinny_get_rtp_peer(), skinny_hangup(), skinny_hold(), skinny_indicate(), skinny_new(), skinny_set_rtp_peer(), skinny_unhold(), transmit_callinfo(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_response(), and transmit_ringer_mode().

int skinnysock = -1 [static]

Definition at line 962 of file chan_skinny.c.

Referenced by accept_thread(), reload_config(), and unload_module().

const uint8_t soft_key_default_connected[] [static]

Definition at line 744 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 788 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 774 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 783 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 806 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 766 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 797 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 753 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 734 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 760 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 792 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 802 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[]

Definition at line 571 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), and load_module().

const char tdesc[] = "Skinny Client Control Protocol (Skinny)" [static]

Definition at line 74 of file chan_skinny.c.

int threewaycalling = 0 [static]

Definition at line 977 of file chan_skinny.c.

unsigned int tos = 0 [static]

Definition at line 94 of file chan_skinny.c.

unsigned int tos_audio = 0 [static]

Definition at line 95 of file chan_skinny.c.

unsigned int tos_video = 0 [static]

Definition at line 96 of file chan_skinny.c.

Referenced by reload_config(), and start_rtp().

int transfer = 0 [static]

Definition at line 980 of file chan_skinny.c.

char used_context[AST_MAX_EXTENSION] [static]

Definition at line 103 of file chan_skinny.c.

char version_id[16] = "P002F202" [static]

Definition at line 106 of file chan_skinny.c.

Referenced by skinny_register().

char vmexten[AST_MAX_EXTENSION] [static]

Definition at line 102 of file chan_skinny.c.

Referenced by build_device(), handle_skinny_show_settings(), handle_stimulus_message(), and reload_config().


Generated on Thu Jul 9 13:41:11 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7