Wed Aug 18 22:34:17 2010

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 "asterisk/indications.h"
#include "asterisk/linkedlists.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  devices
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  sessions
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_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_hold_button (struct skinny_subchannel *sub)
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_transfer_button (struct skinny_subchannel *sub)
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_transfer (struct skinny_subchannel *sub)
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_activatecallplane (struct skinny_device *d, struct skinny_line *l)
static void transmit_callinfo (struct skinny_device *d, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
static void transmit_callstate (struct skinny_device *d, int instance, int state, unsigned callid)
static void transmit_callstateonly (struct skinny_device *d, struct skinny_subchannel *sub, int state)
static void transmit_cfwdstate (struct skinny_device *d, struct skinny_line *l)
static void transmit_closereceivechannel (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_connect (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_dialednumber (struct skinny_device *d, const char *text, int instance, int callid)
static void transmit_displaymessage (struct skinny_device *d, const char *text, int instance, int reference)
static void transmit_displaynotify (struct skinny_device *d, const char *text, int t)
static void transmit_displaypromptstatus (struct skinny_device *d, const char *text, int t, int instance, int callid)
static void transmit_lamp_indication (struct skinny_device *d, int stimulus, int instance, int indication)
static int transmit_response (struct skinny_device *d, struct skinny_req *req)
static void transmit_ringer_mode (struct skinny_device *d, int mode)
static void transmit_selectsoftkeys (struct skinny_device *d, int instance, int callid, int softkey)
static void transmit_speaker_mode (struct skinny_device *d, int mode)
static void transmit_stopmediatransmission (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_tone (struct skinny_device *d, 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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 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 struct ast_threadstorage control2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_control2str_threadbuf , .custom_init = NULL , }
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 int firstdigittimeout = 16000
static int gendigittimeout = 8000
static char global_context [AST_MAX_CONTEXT] = "default"
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 parkinglot [AST_MAX_CONTEXT] = ""
struct {
   unsigned int   cos
   unsigned int   cos_audio
   unsigned int   cos_video
   unsigned int   tos
   unsigned int   tos_audio
   unsigned int   tos_video
qos
static char regcontext [AST_MAX_CONTEXT]
static char regexten [AST_MAX_EXTENSION]
static struct sched_contextsched = NULL
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 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 885 of file chan_skinny.c.

Referenced by transmit_activatecallplane(), and transmit_callstate().

#define ALARM_MESSAGE   0x0020

Definition at line 252 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 459 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 462 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 463 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 461 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 470 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 469 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 456 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 460 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 453 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 454 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 455 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 451 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 457 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 464 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 449 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 450 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 452 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 458 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 248 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 419 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 357 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 856 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_callstateonly().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 492 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 220 of file chan_skinny.c.

Referenced by handle_message().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 490 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 489 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 873 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 528 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 167 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 93 of file chan_skinny.c.

Referenced by reload_config().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 92 of file chan_skinny.c.

Referenced by build_device(), and reload_config().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 406 of file chan_skinny.c.

Referenced by handle_time_date_req_message().

#define DEVICE2STR_BUFSIZE   15

Definition at line 164 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 890 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 879 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 864 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 484 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 196 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 379 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 279 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     bswap_32(x)

Definition at line 122 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_set_rtp_peer(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_callstateonly(), transmit_cfwdstate(), transmit_closereceivechannel(), transmit_connect(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stopmediatransmission(), and transmit_tone().

#define htoles (  )     bswap_16(x)

Definition at line 123 of file chan_skinny.c.

#define IP_PORT_MESSAGE   0x0002

Definition at line 186 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 515 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 173 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

Definition at line 543 of file chan_skinny.c.

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

#define KEYDEF_CONNWITHCONF   7

Definition at line 549 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 547 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 548 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

Definition at line 546 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 551 of file chan_skinny.c.

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 544 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0

Definition at line 542 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), and transmit_callstate().

#define KEYDEF_RINGIN   3

Definition at line 545 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

Definition at line 550 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 552 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 188 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     bswap_32(x)

Definition at line 120 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_register_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 121 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 398 of file chan_skinny.c.

Referenced by handle_line_state_req_message().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 242 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 208 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 214 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 260 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 517 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 282 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 280 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 176 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 494 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 510 of file chan_skinny.c.

Referenced by handle_skinny_reset().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 848 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 250 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 499 of file chan_skinny.c.

Referenced by handle_server_request_message().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 313 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 326 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 305 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 320 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1061 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1048 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1060 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1055 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1051 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1063 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CFWD_ALL   (1 << 0)

Definition at line 1077 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 1078 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 1079 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 1049 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

Definition at line 1047 of file chan_skinny.c.

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

#define SKINNY_CX_CONF   3

Definition at line 1088 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 1089 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1091 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1090 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1086 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1085 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1087 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 1003 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1002 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1001 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 1000 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1004 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1030 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1026 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1019 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1005 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1014 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1029 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1012 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1027 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1018 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1017 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1008 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1033 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1021 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1007 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1010 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1016 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1022 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1023 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1006 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1032 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1015 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1020 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1024 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1028 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1011 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1025 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1013 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1009 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1031 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 999 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1034 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1035 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 998 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DIALTONE   0x21

Definition at line 1059 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(), handle_transfer_button(), and skinny_ss().

#define SKINNY_HOLD   8

Definition at line 1050 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1056 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 1070 of file chan_skinny.c.

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

#define SKINNY_LAMP_FLASH   4

Definition at line 1069 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1

Definition at line 1066 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 1067 of file chan_skinny.c.

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

#define SKINNY_LAMP_WINK   3

Definition at line 1068 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 230 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 94 of file chan_skinny.c.

Referenced by handle_register_message(), skinny_req_parse(), and transmit_response().

#define SKINNY_MICOFF   2

Definition at line 1041 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 1040 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1064 of file chan_skinny.c.

Referenced by transmit_tone().

#define SKINNY_OFFHOOK   1

Definition at line 1043 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(), handle_transfer_button(), skinny_call(), skinny_ss(), skinny_unhold(), and transmit_callstate().

#define SKINNY_ONHOOK   2

Definition at line 1044 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 1053 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1054 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER   0x25

Definition at line 1062 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1075 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1073 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

Definition at line 1072 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 1074 of file chan_skinny.c.

#define SKINNY_RINGIN   4

Definition at line 1046 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_extensionstate_cb().

#define SKINNY_RINGOUT   3

Definition at line 1045 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE   0x00

Definition at line 1058 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 1038 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 1037 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 1052 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 270 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 268 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 833 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 278 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 535 of file chan_skinny.c.

Referenced by handle_soft_key_template_req_message().

#define SOFTKEY_ANSWER   0x0B

Definition at line 565 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 562 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 559 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 560 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 561 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 567 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 573 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 563 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 572 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 557 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 574 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 566 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 569 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 570 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 556 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 554 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 568 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 571 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 555 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 564 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 558 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 237 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 391 of file chan_skinny.c.

Referenced by handle_speed_dial_stat_req_message().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 331 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 291 of file chan_skinny.c.

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 441 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 444 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 445 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 443 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 438 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 442 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 435 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 436 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 437 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 433 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

Definition at line 439 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 201 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 446 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 431 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 432 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 434 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 440 of file chan_skinny.c.

Referenced by do_housekeeping(), and handle_stimulus_message().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 350 of file chan_skinny.c.

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

#define STOP_TONE_MESSAGE   0x0083

Definition at line 299 of file chan_skinny.c.

Referenced by transmit_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 247 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_LINE   2

Definition at line 1082 of file chan_skinny.c.

#define TYPE_TRUNK   1

Definition at line 1081 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 277 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 249 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

Definition at line 479 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 82 of file chan_skinny.c.

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


Function Documentation

static void __init_control2str_threadbuf ( void   )  [static]

Definition at line 166 of file chan_skinny.c.

00177 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 163 of file chan_skinny.c.

00177 {

static void __reg_module ( void   )  [static]

Definition at line 6497 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

Definition at line 6497 of file chan_skinny.c.

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

Definition at line 6030 of file chan_skinny.c.

References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init(), ast_pthread_create_detached, ast_verb, destroy_session(), errno, LOG_NOTICE, LOG_WARNING, s, and skinny_session().

Referenced by reload_config().

06031 {
06032    int as;
06033    struct sockaddr_in sin;
06034    socklen_t sinlen;
06035    struct skinnysession *s;
06036    struct protoent *p;
06037    int arg = 1;
06038    pthread_t tcp_thread;
06039 
06040    for (;;) {
06041       sinlen = sizeof(sin);
06042       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
06043       if (as < 0) {
06044          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
06045          continue;
06046       }
06047       p = getprotobyname("tcp");
06048       if(p) {
06049          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
06050             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
06051          }
06052       }
06053       if (!(s = ast_calloc(1, sizeof(struct skinnysession))))
06054          continue;
06055 
06056       memcpy(&s->sin, &sin, sizeof(sin));
06057       ast_mutex_init(&s->lock);
06058       s->fd = as;
06059       AST_LIST_LOCK(&sessions);
06060       AST_LIST_INSERT_HEAD(&sessions, s, list);
06061       AST_LIST_UNLOCK(&sessions);
06062 
06063       if (ast_pthread_create_detached(&tcp_thread, NULL, skinny_session, s)) {
06064          destroy_session(s);
06065       }
06066    }
06067    if (skinnydebug)
06068       ast_verb(1, "killing accept thread\n");
06069    close(as);
06070    return 0;
06071 }

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

implement the setvar config line

Definition at line 1527 of file chan_skinny.c.

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

01528 {
01529    struct ast_variable *tmpvar = NULL;
01530    char *varname = ast_strdupa(buf), *varval = NULL;
01531 
01532    if ((varval = strchr(varname,'='))) {
01533       *varval++ = '\0';
01534       if ((tmpvar = ast_variable_new(varname, varval, ""))) {
01535          tmpvar->next = list;
01536          list = tmpvar;
01537       }
01538    }
01539    return list;
01540 }

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

Definition at line 3011 of file chan_skinny.c.

References add_var(), 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_LIST_FIRST, AST_LIST_INSERT_HEAD, ast_log(), AST_MAX_EXTENSION, ast_mutex_init(), ast_parse_allow_disallow(), ast_strdupa, ast_strlen_zero(), ast_true(), ast_verb, buf, default_prefs, DEFAULT_SKINNY_PORT, ast_variable::lineno, LOG_ERROR, LOG_WARNING, mwi_event_cb(), ast_variable::name, ast_variable::next, S_OR, set_callforwards(), SKINNY_ONHOOK, strsep(), TYPE_LINE, TYPE_TRUNK, and ast_variable::value.

03012 {
03013    struct skinny_device *d;
03014    struct skinny_line *l;
03015    struct skinny_speeddial *sd;
03016    struct skinny_addon *a;
03017    char device_vmexten[AST_MAX_EXTENSION];
03018    struct ast_variable *chanvars = NULL;
03019    int lineInstance = 1;
03020    int speeddialInstance = 1;
03021    int y = 0;
03022 
03023    if (!(d = ast_calloc(1, sizeof(*d)))) {
03024       return NULL;
03025    } else {
03026       ast_copy_string(d->name, cat, sizeof(d->name));
03027       d->lastlineinstance = 1;
03028       d->capability = default_capability;
03029       d->prefs = default_prefs;
03030       if (!ast_strlen_zero(vmexten))
03031          ast_copy_string(device_vmexten, vmexten, sizeof(device_vmexten));
03032       else
03033          memset(device_vmexten, 0, sizeof(device_vmexten));
03034 
03035       d->earlyrtp = 1;
03036       while(v) {
03037          if (!strcasecmp(v->name, "host")) {
03038             if (ast_get_ip(&d->addr, v->value)) {
03039                ast_free(d);
03040                return NULL;
03041             }
03042          } else if (!strcasecmp(v->name, "port")) {
03043             d->addr.sin_port = htons(atoi(v->value));
03044          } else if (!strcasecmp(v->name, "device")) {
03045             ast_copy_string(d->id, v->value, sizeof(d->id));
03046          } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
03047             d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
03048          } else if (!strcasecmp(v->name, "vmexten")) {
03049             ast_copy_string(device_vmexten, v->value, sizeof(device_vmexten));
03050          } else if (!strcasecmp(v->name, "context")) {
03051             ast_copy_string(global_context, v->value, sizeof(global_context));
03052          } else if (!strcasecmp(v->name, "regexten")) {
03053             ast_copy_string(regexten, v->value, sizeof(regexten));
03054          } else if (!strcasecmp(v->name, "allow")) {
03055             ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 1);
03056          } else if (!strcasecmp(v->name, "disallow")) {
03057             ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 0);
03058          } else if (!strcasecmp(v->name, "version")) {
03059             ast_copy_string(d->version_id, v->value, sizeof(d->version_id));
03060          } else if (!strcasecmp(v->name, "canreinvite")) {
03061             canreinvite = ast_true(v->value);
03062          } else if (!strcasecmp(v->name, "earlyrtp")) {
03063             d->earlyrtp = ast_true(v->value);
03064          } else if (!strcasecmp(v->name, "nat")) {
03065             nat = ast_true(v->value);
03066          } else if (!strcasecmp(v->name, "callerid")) {
03067             if (!strcasecmp(v->value, "asreceived")) {
03068                cid_num[0] = '\0';
03069                cid_name[0] = '\0';
03070             } else {
03071                ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
03072             }
03073          } else if (!strcasecmp(v->name, "language")) {
03074             ast_copy_string(language, v->value, sizeof(language));
03075          } else if (!strcasecmp(v->name, "accountcode")) {
03076             ast_copy_string(accountcode, v->value, sizeof(accountcode));
03077          } else if (!strcasecmp(v->name, "amaflags")) {
03078             y = ast_cdr_amaflags2int(v->value);
03079             if (y < 0) {
03080                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
03081             } else {
03082                amaflags = y;
03083             }
03084          } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) {
03085             ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
03086          } else if (!strcasecmp(v->name, "mohsuggest")) {
03087             ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest));
03088          } else if (!strcasecmp(v->name, "callgroup")) {
03089             cur_callergroup = ast_get_group(v->value);
03090          } else if (!strcasecmp(v->name, "pickupgroup")) {
03091             cur_pickupgroup = ast_get_group(v->value);
03092          } else if (!strcasecmp(v->name, "immediate")) {
03093             immediate = ast_true(v->value);
03094          } else if (!strcasecmp(v->name, "cancallforward")) {
03095             cancallforward = ast_true(v->value);
03096          } else if (!strcasecmp(v->name, "mailbox")) {
03097             ast_copy_string(mailbox, v->value, sizeof(mailbox));
03098          } else if (!strcasecmp(v->name, "hasvoicemail")) {
03099             if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
03100                ast_copy_string(mailbox, cat, sizeof(mailbox));
03101             }
03102          } else if (!strcasecmp(v->name, "callreturn")) {
03103             callreturn = ast_true(v->value);
03104          } else if (!strcasecmp(v->name, "callwaiting")) {
03105             callwaiting = ast_true(v->value);
03106          } else if (!strcasecmp(v->name, "transfer")) {
03107             transfer = ast_true(v->value);
03108          } else if (!strcasecmp(v->name, "threewaycalling")) {
03109             threewaycalling = ast_true(v->value);
03110          } else if (!strcasecmp(v->name, "mwiblink")) {
03111             mwiblink = ast_true(v->value);
03112          } else if (!strcasecmp(v->name, "linelabel")) {
03113             ast_copy_string(linelabel, v->value, sizeof(linelabel));
03114          } else if (!strcasecmp(v->name, "setvar")) {
03115             chanvars = add_var(v->value, chanvars);
03116          } else if ( !strcasecmp(v->name, "parkinglot")) {
03117             ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
03118          } else if (!strcasecmp(v->name, "speeddial")) {
03119             if (!(sd = ast_calloc(1, sizeof(*sd)))) {
03120                return NULL;
03121             } else {
03122                char buf[256];
03123                char *stringp = buf, *exten, *context, *label;
03124 
03125                ast_copy_string(buf, v->value, sizeof(buf));
03126                exten = strsep(&stringp, ",");
03127                if ((context = strchr(exten, '@'))) {
03128                   *context++ = '\0';
03129                }
03130                label = stringp;
03131                ast_mutex_init(&sd->lock);
03132                ast_copy_string(sd->exten, exten, sizeof(sd->exten));
03133                if (!ast_strlen_zero(context)) {
03134                   sd->isHint = 1;
03135                   sd->instance = lineInstance++;
03136                   ast_copy_string(sd->context, context, sizeof(sd->context));
03137                } else {
03138                   sd->isHint = 0;
03139                   sd->instance = speeddialInstance++;
03140                   sd->context[0] = '\0';
03141                }
03142                ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
03143 
03144                sd->parent = d;
03145 
03146                AST_LIST_INSERT_HEAD(&d->speeddials, sd, list);
03147             }
03148          } else if (!strcasecmp(v->name, "addon")) {
03149             if (!(a = ast_calloc(1, sizeof(*a)))) {
03150                return NULL;
03151             } else {
03152                ast_mutex_init(&a->lock);
03153                ast_copy_string(a->type, v->value, sizeof(a->type));
03154 
03155                AST_LIST_INSERT_HEAD(&d->addons, a, list);
03156             }
03157          } else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) {
03158             if (!(l = ast_calloc(1, sizeof(*l)))) {
03159                return NULL;
03160             } else {
03161                ast_mutex_init(&l->lock);
03162                ast_copy_string(l->name, v->value, sizeof(l->name));
03163 
03164                /* XXX Should we check for uniqueness?? XXX */
03165                ast_copy_string(l->context, global_context, sizeof(l->context));
03166                ast_copy_string(l->cid_num, cid_num, sizeof(l->cid_num));
03167                ast_copy_string(l->cid_name, cid_name, sizeof(l->cid_name));
03168                ast_copy_string(l->label, linelabel, sizeof(l->label));
03169                ast_copy_string(l->parkinglot, parkinglot, sizeof(l->parkinglot));
03170                ast_copy_string(l->language, language, sizeof(l->language));
03171                ast_copy_string(l->mohinterpret, mohinterpret, sizeof(l->mohinterpret));
03172                ast_copy_string(l->mohsuggest, mohsuggest, sizeof(l->mohsuggest));
03173                ast_copy_string(l->regexten, regexten, sizeof(l->regexten));
03174                ast_copy_string(l->mailbox, mailbox, sizeof(l->mailbox));
03175                if (!ast_strlen_zero(mailbox)) {
03176                   char *cfg_mailbox, *cfg_context;
03177                   cfg_context = cfg_mailbox = ast_strdupa(l->mailbox);
03178                   ast_verb(3, "Setting mailbox '%s' on %s@%s\n", cfg_mailbox, d->name, l->name);
03179                   strsep(&cfg_context, "@");
03180                   if (ast_strlen_zero(cfg_context))
03181                       cfg_context = "default";
03182                   l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
03183                      AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
03184                      AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
03185                      AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
03186                      AST_EVENT_IE_END);
03187                }
03188                ast_copy_string(l->vmexten, device_vmexten, sizeof(vmexten));
03189                l->chanvars = chanvars;
03190                l->msgstate = -1;
03191                l->capability = d->capability;
03192                l->prefs = d->prefs;
03193                l->parent = d;
03194                if (!strcasecmp(v->name, "trunk")) {
03195                   l->type = TYPE_TRUNK;
03196                } else {
03197                   l->type = TYPE_LINE;
03198                }
03199                l->immediate = immediate;
03200                l->callgroup = cur_callergroup;
03201                l->pickupgroup = cur_pickupgroup;
03202                l->callreturn = callreturn;
03203                l->cancallforward = cancallforward;
03204                l->getforward = 0;
03205                set_callforwards(l, NULL, 0);
03206                l->callwaiting = callwaiting;
03207                l->transfer = transfer;
03208                l->threewaycalling = threewaycalling;
03209                l->mwiblink = mwiblink;
03210                l->onhooktime = time(NULL);
03211                l->instance = lineInstance++;
03212                /* ASSUME we're onhook at this point */
03213                l->hookstate = SKINNY_ONHOOK;
03214                l->nat = nat;
03215                l->canreinvite = canreinvite;
03216 
03217                if (!AST_LIST_FIRST(&d->lines)) {
03218                   d->activeline = l;
03219                }
03220                AST_LIST_INSERT_HEAD(&d->lines, l, list);
03221             }
03222          } else {
03223             ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
03224          }
03225          v = v->next;
03226       }
03227 
03228       if (!AST_LIST_FIRST(&d->lines)) {
03229          ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
03230          return NULL;
03231       }
03232       if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
03233          d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
03234       }
03235    }
03236    return d;
03237 }

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

Definition at line 1688 of file chan_skinny.c.

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

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

static int codec_ast2skinny ( int  astcodec  )  [static]

Definition at line 1631 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().

01632 {
01633    switch (astcodec) {
01634    case AST_FORMAT_ALAW:
01635       return SKINNY_CODEC_ALAW;
01636    case AST_FORMAT_ULAW:
01637       return SKINNY_CODEC_ULAW;
01638    case AST_FORMAT_G723_1:
01639       return SKINNY_CODEC_G723_1;
01640    case AST_FORMAT_G729A:
01641       return SKINNY_CODEC_G729A;
01642    case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
01643       return SKINNY_CODEC_G726_32;
01644    case AST_FORMAT_H261:
01645       return SKINNY_CODEC_H261;
01646    case AST_FORMAT_H263:
01647       return SKINNY_CODEC_H263;
01648    default:
01649       return 0;
01650    }
01651 }

static int codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

Definition at line 1609 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().

01610 {
01611    switch (skinnycodec) {
01612    case SKINNY_CODEC_ALAW:
01613       return AST_FORMAT_ALAW;
01614    case SKINNY_CODEC_ULAW:
01615       return AST_FORMAT_ULAW;
01616    case SKINNY_CODEC_G723_1:
01617       return AST_FORMAT_G723_1;
01618    case SKINNY_CODEC_G729A:
01619       return AST_FORMAT_G729A;
01620    case SKINNY_CODEC_G726_32:
01621       return AST_FORMAT_G726_AAL2; /* XXX Is this right? */
01622    case SKINNY_CODEC_H261:
01623       return AST_FORMAT_H261;
01624    case SKINNY_CODEC_H263:
01625       return AST_FORMAT_H263;
01626    default:
01627       return 0;
01628    }
01629 }

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

Definition at line 2552 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, and skinny_device::id.

Referenced by complete_skinny_reset(), and complete_skinny_show_device().

02553 {
02554    struct skinny_device *d;
02555    char *result = NULL;
02556    int wordlen = strlen(word), which = 0;
02557 
02558    AST_LIST_TRAVERSE(&devices, d, list) {
02559       if (!strncasecmp(word, d->id, wordlen) && ++which > state)
02560          result = ast_strdup(d->id);
02561    }
02562 
02563    return result;
02564 }

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

Definition at line 2571 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

02572 {
02573    return (pos == 2 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02574 }

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

Definition at line 2566 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

02567 {
02568    return (pos == 3 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02569 }

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

Definition at line 2576 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, skinny_device::lines, and skinny_line::name.

Referenced by handle_skinny_show_line().

02577 {
02578    struct skinny_device *d;
02579    struct skinny_line *l;
02580    char *result = NULL;
02581    int wordlen = strlen(word), which = 0;
02582 
02583    if (pos != 3)
02584       return NULL;
02585    
02586    AST_LIST_TRAVERSE(&devices, d, list) {
02587       AST_LIST_TRAVERSE(&d->lines, l, list) {
02588          if (!strncasecmp(word, l->name, wordlen) && ++which > state)
02589             result = ast_strdup(l->name);
02590       }
02591    }
02592 
02593    return result;
02594 }

static char* control2str ( int  ind  )  [static]

Definition at line 3720 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.

03720                                   {
03721    char *tmp;
03722 
03723    switch (ind) {
03724    case AST_CONTROL_HANGUP:
03725       return "Other end has hungup";
03726    case AST_CONTROL_RING:
03727       return "Local ring";
03728    case AST_CONTROL_RINGING:
03729       return "Remote end is ringing";
03730    case AST_CONTROL_ANSWER:
03731       return "Remote end has answered";
03732    case AST_CONTROL_BUSY:
03733       return "Remote end is busy";
03734    case AST_CONTROL_TAKEOFFHOOK:
03735       return "Make it go off hook";
03736    case AST_CONTROL_OFFHOOK:
03737       return "Line is off hook";
03738    case AST_CONTROL_CONGESTION:
03739       return "Congestion (circuits busy)";
03740    case AST_CONTROL_FLASH:
03741       return "Flash hook";
03742    case AST_CONTROL_WINK:
03743       return "Wink";
03744    case AST_CONTROL_OPTION:
03745       return "Set a low-level option";
03746    case AST_CONTROL_RADIO_KEY:
03747       return "Key Radio";
03748    case AST_CONTROL_RADIO_UNKEY:
03749       return "Un-Key Radio";
03750    case AST_CONTROL_PROGRESS:
03751       return "Remote end is making Progress";
03752    case AST_CONTROL_PROCEEDING:
03753       return "Remote end is proceeding";
03754    case AST_CONTROL_HOLD:
03755       return "Hold";
03756    case AST_CONTROL_UNHOLD:
03757       return "Unhold";
03758    case -1:
03759       return "Stop tone";
03760    default:
03761       if (!(tmp = ast_threadstorage_get(&control2str_threadbuf, CONTROL2STR_BUFSIZE)))
03762                         return "Unknown";
03763       snprintf(tmp, CONTROL2STR_BUFSIZE, "UNKNOWN-%d", ind);
03764       return tmp;
03765    }
03766 }

static void delete_devices ( void   )  [static]

Definition at line 6350 of file chan_skinny.c.

References skinny_device::addons, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, free, skinny_device::lines, and skinny_device::speeddials.

Referenced by unload_module().

06351 {
06352    struct skinny_device *d;
06353    struct skinny_line *l;
06354    struct skinny_speeddial *sd;
06355    struct skinny_addon *a;
06356 
06357    AST_LIST_LOCK(&devices);
06358 
06359    /* Delete all devices */
06360    while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
06361       /* Delete all lines for this device */
06362       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
06363          free(l);
06364       }
06365       /* Delete all speeddials for this device */
06366       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
06367          free(sd);
06368       }
06369       /* Delete all addons for this device */
06370       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
06371          free(a);
06372       } 
06373       free(d);
06374    }
06375    AST_LIST_UNLOCK(&devices);
06376 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 5872 of file chan_skinny.c.

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), LOG_WARNING, and s.

05873 {
05874    struct skinnysession *cur;
05875    AST_LIST_LOCK(&sessions);
05876    AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, cur, list) {
05877       if (cur == s) {
05878          AST_LIST_REMOVE_CURRENT(list);
05879          if (s->fd > -1) 
05880             close(s->fd);
05881          
05882          ast_mutex_destroy(&s->lock);
05883          
05884          ast_free(s);
05885       } else {
05886          ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
05887       }
05888    }
05889    AST_LIST_TRAVERSE_SAFE_END
05890    AST_LIST_UNLOCK(&sessions);
05891 }

static char* device2str ( int  type  )  [static]

Definition at line 2641 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().

02642 {
02643    char *tmp;
02644 
02645    switch (type) {
02646    case SKINNY_DEVICE_NONE:
02647       return "No Device";
02648    case SKINNY_DEVICE_30SPPLUS:
02649       return "30SP Plus";
02650    case SKINNY_DEVICE_12SPPLUS:
02651       return "12SP Plus";
02652    case SKINNY_DEVICE_12SP:
02653       return "12SP";
02654    case SKINNY_DEVICE_12:
02655       return "12";
02656    case SKINNY_DEVICE_30VIP:
02657       return "30VIP";
02658    case SKINNY_DEVICE_7910:
02659       return "7910";
02660    case SKINNY_DEVICE_7960:
02661       return "7960";
02662    case SKINNY_DEVICE_7940:
02663       return "7940";
02664    case SKINNY_DEVICE_7935:
02665       return "7935";
02666    case SKINNY_DEVICE_ATA186:
02667       return "ATA186";
02668    case SKINNY_DEVICE_7941:
02669       return "7941";
02670    case SKINNY_DEVICE_7971:
02671       return "7971";
02672    case SKINNY_DEVICE_7914:
02673       return "7914";
02674    case SKINNY_DEVICE_7985:
02675       return "7985";
02676    case SKINNY_DEVICE_7911:
02677       return "7911";
02678    case SKINNY_DEVICE_7961GE:
02679       return "7961GE";
02680    case SKINNY_DEVICE_7941GE:
02681       return "7941GE";
02682    case SKINNY_DEVICE_7931:
02683       return "7931";
02684    case SKINNY_DEVICE_7921:
02685       return "7921";
02686    case SKINNY_DEVICE_7906:
02687       return "7906";
02688    case SKINNY_DEVICE_7962:
02689       return "7962";
02690    case SKINNY_DEVICE_7937:
02691       return "7937";
02692    case SKINNY_DEVICE_7942:
02693       return "7942";
02694    case SKINNY_DEVICE_7945:
02695       return "7945";
02696    case SKINNY_DEVICE_7965:
02697       return "7965";
02698    case SKINNY_DEVICE_7975:
02699       return "7975";
02700    case SKINNY_DEVICE_7905:
02701       return "7905";
02702    case SKINNY_DEVICE_7920:
02703       return "7920";
02704    case SKINNY_DEVICE_7970:
02705       return "7970";
02706    case SKINNY_DEVICE_7912:
02707       return "7912";
02708    case SKINNY_DEVICE_7902:
02709       return "7902";
02710    case SKINNY_DEVICE_CIPC:
02711       return "IP Communicator";
02712    case SKINNY_DEVICE_7961:
02713       return "7961";
02714    case SKINNY_DEVICE_7936:
02715       return "7936";
02716    case SKINNY_DEVICE_SCCPGATEWAY_AN:
02717       return "SCCPGATEWAY_AN";
02718    case SKINNY_DEVICE_SCCPGATEWAY_BRI:
02719       return "SCCPGATEWAY_BRI";
02720    case SKINNY_DEVICE_UNKNOWN:
02721       return "Unknown";
02722    default:
02723       if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE)))
02724          return "Unknown";
02725       snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type);
02726       return tmp;
02727    }
02728 }

static void do_housekeeping ( struct skinnysession s  )  [static]

Definition at line 2337 of file chan_skinny.c.

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

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

02338 {
02339    int device_lamp = 0;
02340    struct skinny_device *d = s->device;
02341    struct skinny_line *l;
02342 
02343    /* Update time on device */
02344    handle_time_date_req_message(NULL, s);
02345 
02346    /* Set MWI on individual lines */
02347    AST_LIST_TRAVERSE(&d->lines, l, list) {
02348       if (has_voicemail(l)) {
02349          if (skinnydebug)
02350             ast_verb(1, "Checking for voicemail Skinny %s@%s\n", l->name, d->name);
02351          if (skinnydebug)
02352             ast_verb(1, "Skinny %s@%s has voicemail!\n", l->name, d->name);
02353          transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
02354          device_lamp++;
02355       } else {
02356          transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
02357       }
02358    }
02359    /* If at least one line has VM, turn the device level lamp on */
02360    if (device_lamp)
02361       transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, SKINNY_LAMP_ON);
02362    else
02363       transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, SKINNY_LAMP_OFF);
02364 }

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

Definition at line 6073 of file chan_skinny.c.

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

06074 {
06075    int res;
06076 
06077    /* This thread monitors all the interfaces which are not yet in use
06078       (and thus do not have a separate thread) indefinitely */
06079    /* From here on out, we die whenever asked */
06080    for(;;) {
06081       pthread_testcancel();
06082       /* Wait for sched or io */
06083       res = ast_sched_wait(sched);
06084       if ((res < 0) || (res > 1000)) {
06085          res = 1000;
06086       }
06087       res = ast_io_wait(io, res);
06088       ast_mutex_lock(&monlock);
06089       if (res >= 0) {
06090          ast_sched_runq(sched);
06091       }
06092       ast_mutex_unlock(&monlock);
06093    }
06094    /* Never reached */
06095    return NULL;
06096 
06097 }

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

Definition at line 1455 of file chan_skinny.c.

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

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().

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

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

Definition at line 1476 of file chan_skinny.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_verb, skinny_device::lines, skinny_line::name, and skinny_device::name.

Referenced by skinny_devicestate(), and skinny_request().

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

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

Definition at line 1594 of file chan_skinny.c.

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

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

01595 {
01596    struct skinny_speeddial *sd;
01597 
01598    AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01599       if (sd->isHint == isHint && sd->instance == instance)
01600          break;
01601    }
01602 
01603    if (!sd) {
01604       ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
01605    }
01606    return sd;
01607 }

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

Definition at line 1543 of file chan_skinny.c.

References AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_log(), skinny_subchannel::callid, find_line_by_instance(), LOG_WARNING, skinny_device::name, 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().

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

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

Definition at line 1570 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message().

01571 {
01572    struct skinny_line *l;
01573    struct skinny_subchannel *sub = NULL;
01574 
01575    AST_LIST_TRAVERSE(&d->lines, l, list){
01576       AST_LIST_TRAVERSE(&l->sub, sub, list){
01577          if (sub->callid == reference)
01578             break;
01579       }
01580       if (sub)
01581          break;
01582    }
01583 
01584    if (!l) {
01585       ast_log(LOG_WARNING, "Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
01586    } else {
01587       if (!sub) {
01588          ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
01589       }
01590    }
01591    return sub;
01592 }

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

Definition at line 1304 of file chan_skinny.c.

References skinny_device::addons, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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, 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().

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

static int get_devicestate ( struct skinny_line l  )  [static]

Definition at line 3691 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, AST_LIST_TRAVERSE, skinny_line::dnd, skinny_line::hookstate, skinny_subchannel::onhold, skinny_line::parent, SKINNY_ONHOOK, and skinny_line::sub.

Referenced by skinny_devicestate(), and skinny_new().

03692 {
03693    struct skinny_subchannel *sub;
03694    int res = AST_DEVICE_UNKNOWN;
03695 
03696    if (!l)
03697       res = AST_DEVICE_INVALID;
03698    else if (!l->parent)
03699       res = AST_DEVICE_UNAVAILABLE;
03700    else if (l->dnd)
03701       res = AST_DEVICE_BUSY;
03702    else {
03703       if (l->hookstate == SKINNY_ONHOOK) {
03704          res = AST_DEVICE_NOT_INUSE;
03705       } else {
03706          res = AST_DEVICE_INUSE;
03707       }
03708 
03709       AST_LIST_TRAVERSE(&l->sub, sub, list) {
03710          if (sub->onhold) {
03711             res = AST_DEVICE_ONHOLD;
03712             break;
03713          }
03714       }
03715    }
03716 
03717    return res;
03718 }

static int get_input ( struct skinnysession s  )  [static]

Definition at line 5893 of file chan_skinny.c.

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

05894 {
05895    int res;
05896    int dlen = 0;
05897    int *bufaddr;
05898    struct pollfd fds[1];
05899 
05900    fds[0].fd = s->fd;
05901    fds[0].events = POLLIN;
05902    fds[0].revents = 0;
05903    res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
05904                    /* we add 10% to the keep_alive to deal */
05905                    /* with network delays, etc */
05906    if (res < 0) {
05907       if (errno != EINTR) {
05908          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
05909          return res;
05910       }
05911    } else if (res == 0) {
05912       if (skinnydebug)
05913          ast_verb(1, "Skinny Client was lost, unregistering\n");
05914       skinny_unregister(NULL, s);
05915       return -1;
05916    }
05917            
05918    if (fds[0].revents) {
05919       ast_mutex_lock(&s->lock);
05920       memset(s->inbuf, 0, sizeof(s->inbuf));
05921       res = read(s->fd, s->inbuf, 4);
05922       if (res < 0) {
05923          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
05924 
05925          if (skinnydebug)
05926             ast_verb(1, "Skinny Client was lost, unregistering\n");
05927 
05928          skinny_unregister(NULL, s);
05929          ast_mutex_unlock(&s->lock);
05930          return res;
05931       } else if (res != 4) {
05932          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
05933          ast_mutex_unlock(&s->lock);
05934          
05935          if (res == 0) {
05936             if (skinnydebug)
05937                ast_verb(1, "Skinny Client was lost, unregistering\n");
05938             skinny_unregister(NULL, s);
05939          }
05940 
05941          return -1;
05942       }
05943 
05944       bufaddr = (int *)s->inbuf;
05945       dlen = letohl(*bufaddr);
05946       if (dlen < 4) {
05947          ast_debug(1, "Skinny Client sent invalid data.\n");
05948          ast_mutex_unlock(&s->lock);
05949          return -1;
05950       }
05951       if (dlen+8 > sizeof(s->inbuf)) {
05952          dlen = sizeof(s->inbuf) - 8;
05953       }
05954       *bufaddr = htolel(dlen);
05955 
05956       res = read(s->fd, s->inbuf+4, dlen+4);
05957       ast_mutex_unlock(&s->lock);
05958       if (res < 0) {
05959          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
05960          return res;
05961       } else if (res != (dlen+4)) {
05962          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
05963          return -1;
05964       }
05965       return res;
05966    }
05967    return 0;
05968 }

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

Definition at line 5157 of file chan_skinny.c.

References skinny_data::alarm, ast_verb, skinny_req::data, and alarm_message::displayMessage.

Referenced by handle_message().

05158 {
05159    /* no response necessary */
05160    if (skinnydebug)
05161       ast_verb(1, "Received Alarm Message: %s\n", req->data.alarm.displayMessage);
05162 
05163    return 1;
05164 }

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

Definition at line 4984 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_verb, BT_CUST_LINE, BT_CUST_LINESPEEDDIAL, BT_LINE, BT_NONE, BT_SPEEDDIAL, BUTTON_TEMPLATE_RES_MESSAGE, button_template_res_message::buttonCount, button_definition::buttonDefinition, button_definition_template::buttonDefinition, button_template_res_message::buttonOffset, 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_device::name, req_alloc(), s, skinny_device::speeddials, button_template_res_message::totalButtonCount, transmit_response(), and skinny_device::type.

Referenced by handle_message().

04985 {
04986    struct skinny_device *d = s->device;
04987    struct skinny_line *l;
04988    int i;
04989 
04990    struct skinny_speeddial *sd;
04991    struct button_definition_template btn[42];
04992    int lineInstance = 1;
04993    int speeddialInstance = 1;
04994    int buttonCount = 0;
04995 
04996    if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
04997       return -1;
04998 
04999    memset(&btn, 0, sizeof(btn));
05000 
05001    get_button_template(s, btn);
05002 
05003    for (i=0; i<42; i++) {
05004       int btnSet = 0;
05005       switch (btn[i].buttonDefinition) {
05006          case BT_CUST_LINE:
05007             /* assume failure */
05008             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05009             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05010 
05011             AST_LIST_TRAVERSE(&d->lines, l, list) {
05012                if (l->instance == lineInstance) {
05013                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05014                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05015                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05016                   lineInstance++;
05017                   buttonCount++;
05018                   btnSet = 1;
05019                   break;
05020                }
05021             }
05022 
05023             if (!btnSet) {
05024                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05025                   if (sd->isHint && sd->instance == lineInstance) {
05026                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05027                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05028                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05029                      lineInstance++;
05030                      buttonCount++;
05031                      btnSet = 1;
05032                      break;
05033                   }
05034                }
05035             }
05036             break;
05037          case BT_CUST_LINESPEEDDIAL:
05038             /* assume failure */
05039             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05040             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05041 
05042             AST_LIST_TRAVERSE(&d->lines, l, list) {
05043                if (l->instance == lineInstance) {
05044                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05045                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05046                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05047                   lineInstance++;
05048                   buttonCount++;
05049                   btnSet = 1;
05050                   break;
05051                }
05052             }
05053 
05054             if (!btnSet) {
05055                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05056                   if (sd->isHint && sd->instance == lineInstance) {
05057                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05058                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05059                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05060                      lineInstance++;
05061                      buttonCount++;
05062                      btnSet = 1;
05063                      break;
05064                   } else if (!sd->isHint && sd->instance == speeddialInstance) {
05065                      ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05066                      req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05067                      req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance);
05068                      speeddialInstance++;
05069                      buttonCount++;
05070                      btnSet = 1;
05071                      break;
05072                   }
05073                }
05074             }
05075             break;
05076          case BT_LINE:
05077             req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
05078             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05079 
05080             AST_LIST_TRAVERSE(&d->lines, l, list) {
05081                if (l->instance == lineInstance) {
05082                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05083                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05084                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05085                   lineInstance++;
05086                   buttonCount++;
05087                   btnSet = 1;
05088                   break;
05089                }
05090             }
05091             break;
05092          case BT_SPEEDDIAL:
05093             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05094             req->data.buttontemplate.definition[i].instanceNumber = 0;
05095 
05096             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05097                if (!sd->isHint && sd->instance == speeddialInstance) {
05098                   ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05099                   req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05100                   req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance - 1);
05101                   speeddialInstance++;
05102                   buttonCount++;
05103                   btnSet = 1;
05104                   break;
05105                }
05106             }
05107             break;
05108          case BT_NONE:
05109             break;
05110          default:
05111             ast_verb(0, "Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
05112             req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
05113             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05114             buttonCount++;
05115             btnSet = 1;
05116             break;
05117       }
05118    }
05119 
05120    req->data.buttontemplate.buttonOffset = htolel(0);
05121    req->data.buttontemplate.buttonCount = htolel(buttonCount);
05122    req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
05123 
05124    if (skinnydebug)
05125       ast_verb(1, "Sending %d template to %s\n",
05126                d->type,
05127                d->name);
05128    transmit_response(d, req);
05129    return 1;
05130 }

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

Definition at line 4244 of file chan_skinny.c.

References ast_channel::_state, ast_hangup(), ast_indicate(), ast_log(), ast_pthread_create, ast_safe_sleep(), AST_STATE_UP, ast_verb, 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, set_callforwards(), SKINNY_DIALTONE, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), 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().

04245 {
04246    struct skinny_line *l = sub->parent;
04247    struct skinny_device *d = l->parent;
04248    struct ast_channel *c = sub->owner;
04249    pthread_t t;
04250 
04251    if (l->hookstate == SKINNY_ONHOOK) {
04252       l->hookstate = SKINNY_OFFHOOK;
04253       transmit_speaker_mode(d, SKINNY_SPEAKERON);
04254       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04255    }
04256    if (skinnydebug)
04257       ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04258    transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04259 
04260    if (l->cfwdtype & cfwdtype) {
04261       set_callforwards(l, NULL, cfwdtype);
04262       ast_safe_sleep(c, 500);
04263       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04264       transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
04265       transmit_displaynotify(d, "CFwd disabled", 10);
04266       if (sub->owner && sub->owner->_state != AST_STATE_UP) {
04267          ast_indicate(c, -1);
04268          ast_hangup(c);
04269       }
04270       transmit_cfwdstate(d, l);
04271    } else {
04272       l->getforward = cfwdtype;
04273       transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04274       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04275       if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04276          ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04277          ast_hangup(c);
04278       }
04279    }
04280    return 0;
04281 }

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

Definition at line 4864 of file chan_skinny.c.

References AST_LIST_TRAVERSE, 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, s, and SKINNY_MAX_CAPABILITIES.

Referenced by handle_message().

04865 {
04866    struct skinny_device *d = s->device;
04867    struct skinny_line *l;
04868    uint32_t count = 0;
04869    int codecs = 0;
04870    int i;
04871 
04872    count = letohl(req->data.caps.count);
04873    if (count > SKINNY_MAX_CAPABILITIES) {
04874       count = SKINNY_MAX_CAPABILITIES;
04875       ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
04876    }
04877 
04878    for (i = 0; i < count; i++) {
04879       int acodec = 0;
04880       int scodec = 0;
04881       scodec = letohl(req->data.caps.caps[i].codec);
04882       acodec = codec_skinny2ast(scodec);
04883       if (skinnydebug)
04884          ast_verb(1, "Adding codec capability '%d (%d)'\n", acodec, scodec);
04885       codecs |= acodec;
04886    }
04887 
04888    d->capability &= codecs;
04889    ast_verb(0, "Device capability set to '%d'\n", d->capability);
04890    AST_LIST_TRAVERSE(&d->lines, l, list) {
04891       ast_mutex_lock(&l->lock);
04892       l->capability = d->capability;
04893       ast_mutex_unlock(&l->lock);
04894    }
04895 
04896    return 1;
04897 }

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

Definition at line 5233 of file chan_skinny.c.

References ast_copy_string(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_pthread_create, AST_STATE_DOWN, ast_verb, 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, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), and transmit_tone().

Referenced by handle_message().

05234 {
05235    struct skinny_device *d = s->device;
05236    struct skinny_line *l;
05237    struct skinny_subchannel *sub = NULL;
05238    struct ast_channel *c;
05239    pthread_t t;
05240 
05241    if (skinnydebug)
05242       ast_verb(1, "Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
05243 
05244    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05245 
05246    if (!sub) {
05247       l = find_line_by_instance(d, d->lastlineinstance);
05248       if (!l) {
05249          return 0;
05250       }
05251    } else {
05252       l = sub->parent;
05253    }
05254 
05255    c = skinny_new(l, AST_STATE_DOWN);
05256 
05257    if(!c) {
05258       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05259    } else {
05260       l->hookstate = SKINNY_OFFHOOK;
05261 
05262       sub = c->tech_pvt;
05263       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05264       if (skinnydebug)
05265          ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05266       transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05267       transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05268 
05269       if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
05270          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05271       }
05272       ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
05273       if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05274          ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05275          ast_hangup(c);
05276       }
05277    }
05278    
05279    return 1;
05280 }

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

Definition at line 5691 of file chan_skinny.c.

Referenced by handle_message().

05692 {
05693    /* XXX umm...okay?  Why do I care? */
05694    return 1;
05695 }

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4088 of file chan_skinny.c.

References skinny_line::activesub, skinny_subchannel::callid, skinny_line::instance, KEYDEF_CONNECTED, KEYDEF_ONHOLD, skinny_subchannel::onhold, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::related, skinny_hold(), skinny_unhold(), and transmit_selectsoftkeys().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

04089 {
04090    if (!sub)
04091       return -1;
04092    if (sub->related) {
04093       skinny_hold(sub);
04094       skinny_unhold(sub->related);
04095       sub->parent->activesub = sub->related;
04096    } else {
04097       if (sub->onhold) {
04098          skinny_unhold(sub);
04099          transmit_selectsoftkeys(sub->parent->parent, sub->parent->instance, sub->callid, KEYDEF_CONNECTED);
04100       } else {
04101          skinny_hold(sub);
04102          transmit_selectsoftkeys(sub->parent->parent, sub->parent->instance, sub->callid, KEYDEF_ONHOLD);
04103       }
04104    }
04105    return 1;
04106 }

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

Definition at line 4282 of file chan_skinny.c.

Referenced by handle_message().

04283 {
04284    /* no response necessary */
04285    return 1;
04286 }

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

Definition at line 4169 of file chan_skinny.c.

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

Referenced by handle_message().

04170 {
04171    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
04172       return -1;
04173 
04174    transmit_response(s->device, req);
04175    do_housekeeping(s);
04176    return 1;
04177 }

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

Definition at line 4288 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_LIST_NEXT, ast_log(), ast_queue_frame(), ast_verb, keypad_button_message::button, keypad_button_message::callReference, skinny_req::data, f, find_subchannel_by_instance_reference(), skinny_data::keypad, letohl, keypad_button_message::lineInstance, LOG_WARNING, skinny_line::name, skinny_subchannel::owner, skinny_subchannel::parent, and s.

Referenced by handle_message().

04289 {
04290    struct skinny_subchannel *sub = NULL;
04291    struct skinny_line *l;
04292    struct skinny_device *d = s->device;
04293    struct ast_frame f = { 0, };
04294    char dgt;
04295    int digit;
04296    int lineInstance;
04297    int callReference;
04298 
04299    digit = letohl(req->data.keypad.button);
04300    lineInstance = letohl(req->data.keypad.lineInstance);
04301    callReference = letohl(req->data.keypad.callReference);
04302 
04303    if (digit == 14) {
04304       dgt = '*';
04305    } else if (digit == 15) {
04306       dgt = '#';
04307    } else if (digit >= 0 && digit <= 9) {
04308       dgt = '0' + digit;
04309    } else {
04310       /* digit=10-13 (A,B,C,D ?), or
04311        * digit is bad value
04312        *
04313        * probably should not end up here, but set
04314        * value for backward compatibility, and log
04315        * a warning.
04316        */
04317       dgt = '0' + digit;
04318       ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
04319    }
04320 
04321    f.subclass = dgt;
04322 
04323    f.src = "skinny";
04324 
04325    if (lineInstance && callReference)
04326       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
04327    else
04328       sub = d->activeline->activesub;
04329       //sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04330 
04331    if (!sub)
04332       return 0;
04333 
04334    l = sub->parent;
04335    if (sub->owner) {
04336       if (sub->owner->_state == 0) {
04337          f.frametype = AST_FRAME_DTMF_BEGIN;
04338          ast_queue_frame(sub->owner, &f);
04339       }
04340       /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
04341       f.frametype = AST_FRAME_DTMF_END;
04342       ast_queue_frame(sub->owner, &f);
04343       /* XXX This seriously needs to be fixed */
04344       if (AST_LIST_NEXT(sub, list) && AST_LIST_NEXT(sub, list)->owner) {
04345          if (sub->owner->_state == 0) {
04346             f.frametype = AST_FRAME_DTMF_BEGIN;
04347             ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04348          }
04349          f.frametype = AST_FRAME_DTMF_END;
04350          ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04351       }
04352    } else {
04353       if (skinnydebug)
04354          ast_verb(1, "No owner: %s\n", l->name);
04355    }
04356    return 1;
04357 }

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

Definition at line 4924 of file chan_skinny.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, skinny_req::data, find_line_by_instance(), find_speeddial_by_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().

04925 {
04926    struct skinny_device *d = s->device;
04927    struct skinny_line *l;
04928    struct skinny_speeddial *sd = NULL;
04929    int instance;
04930 
04931    instance = letohl(req->data.line.lineNumber);
04932 
04933    AST_LIST_LOCK(&devices);
04934 
04935    l = find_line_by_instance(d, instance);
04936 
04937    if (!l) {
04938       sd = find_speeddial_by_instance(d, instance, 1);
04939    }
04940 
04941    if (!l && !sd) {
04942       return 0;
04943    }
04944 
04945    AST_LIST_UNLOCK(&devices);
04946 
04947    if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
04948       return -1;
04949 
04950    req->data.linestat.lineNumber = letohl(instance);
04951    if (!l) {
04952       memcpy(req->data.linestat.lineDirNumber, sd->label, sizeof(req->data.linestat.lineDirNumber));
04953       memcpy(req->data.linestat.lineDisplayName, sd->label, sizeof(req->data.linestat.lineDisplayName));
04954    } else {
04955       memcpy(req->data.linestat.lineDirNumber, l->name, sizeof(req->data.linestat.lineDirNumber));
04956       memcpy(req->data.linestat.lineDisplayName, l->label, sizeof(req->data.linestat.lineDisplayName));
04957    }
04958    transmit_response(d, req);
04959    return 1;
04960 }

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

Definition at line 5703 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, ALARM_MESSAGE, ast_free, ast_log(), AST_STATE_UP, ast_verb, 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, skinny_subchannel::onhold, ONHOOK_MESSAGE, OPEN_RECEIVE_CHANNEL_ACK_MESSAGE, skinny_subchannel::owner, skinny_data::reg, REGISTER_AVAILABLE_LINES_MESSAGE, REGISTER_MESSAGE, s, SERVER_REQUEST_MESSAGE, 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().

05704 {
05705    int res = 0;
05706 
05707    if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
05708       ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
05709       ast_free(req);
05710       return 0;
05711    }
05712 
05713    switch(letohl(req->e)) {
05714    case KEEP_ALIVE_MESSAGE:
05715       res = handle_keep_alive_message(req, s);
05716       break;
05717    case REGISTER_MESSAGE:
05718       if (skinnydebug)
05719          ast_verb(1, "Device %s is attempting to register\n", req->data.reg.name);
05720 
05721       res = handle_register_message(req, s);
05722       break;
05723    case IP_PORT_MESSAGE:
05724       res = handle_ip_port_message(req, s);
05725       break;
05726    case KEYPAD_BUTTON_MESSAGE:
05727        {
05728       struct skinny_device *d = s->device;
05729       struct skinny_subchannel *sub;
05730       int lineInstance;
05731       int callReference;
05732 
05733       if (skinnydebug)
05734          ast_verb(1, "Collected digit: [%d]\n", letohl(req->data.keypad.button));
05735 
05736       lineInstance = letohl(req->data.keypad.lineInstance);
05737       callReference = letohl(req->data.keypad.callReference);
05738 
05739       if (lineInstance) {
05740          sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
05741       } else {
05742          sub = d->activeline->activesub;
05743       }
05744 
05745       if (sub && ((sub->owner && sub->owner->_state <  AST_STATE_UP) || sub->onhold)) {
05746          char dgt;
05747          int digit = letohl(req->data.keypad.button);
05748 
05749          if (digit == 14) {
05750             dgt = '*';
05751          } else if (digit == 15) {
05752             dgt = '#';
05753          } else if (digit >= 0 && digit <= 9) {
05754             dgt = '0' + digit;
05755          } else {
05756             /* digit=10-13 (A,B,C,D ?), or
05757             * digit is bad value
05758             *
05759             * probably should not end up here, but set
05760             * value for backward compatibility, and log
05761             * a warning.
05762             */
05763             dgt = '0' + digit;
05764             ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
05765          }
05766 
05767          d->exten[strlen(d->exten)] = dgt;
05768          d->exten[strlen(d->exten)+1] = '\0';
05769       } else
05770          res = handle_keypad_button_message(req, s);
05771       }
05772       break;
05773    case ENBLOC_CALL_MESSAGE:
05774       res = handle_enbloc_call_message(req, s);
05775       break;
05776    case STIMULUS_MESSAGE:
05777       res = handle_stimulus_message(req, s);
05778       break;
05779    case OFFHOOK_MESSAGE:
05780       res = handle_offhook_message(req, s);
05781       break;
05782    case ONHOOK_MESSAGE:
05783       res = handle_onhook_message(req, s);
05784       break;
05785    case CAPABILITIES_RES_MESSAGE:
05786       if (skinnydebug)
05787          ast_verb(1, "Received CapabilitiesRes\n");
05788 
05789       res = handle_capabilities_res_message(req, s);
05790       break;
05791    case SPEED_DIAL_STAT_REQ_MESSAGE:
05792       if (skinnydebug)
05793          ast_verb(1, "Received SpeedDialStatRequest\n");
05794 
05795       res = handle_speed_dial_stat_req_message(req, s);
05796       break;
05797    case LINE_STATE_REQ_MESSAGE:
05798       if (skinnydebug)
05799          ast_verb(1, "Received LineStatRequest\n");
05800       res = handle_line_state_req_message(req, s);
05801       break;
05802    case TIME_DATE_REQ_MESSAGE:
05803       if (skinnydebug)
05804          ast_verb(1, "Received Time/Date Request\n");
05805 
05806       res = handle_time_date_req_message(req, s);
05807       break;
05808    case BUTTON_TEMPLATE_REQ_MESSAGE:
05809       if (skinnydebug)
05810          ast_verb(1, "Buttontemplate requested\n");
05811 
05812       res = handle_button_template_req_message(req, s);
05813       break;
05814    case VERSION_REQ_MESSAGE:
05815       if (skinnydebug)
05816          ast_verb(1, "Version Request\n");
05817 
05818       res = handle_version_req_message(req, s);
05819       break;
05820    case SERVER_REQUEST_MESSAGE:
05821       if (skinnydebug)
05822          ast_verb(1, "Received Server Request\n");
05823 
05824       res = handle_server_request_message(req, s);
05825       break;
05826    case ALARM_MESSAGE:
05827       res = handle_alarm_message(req, s);
05828       break;
05829    case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
05830       if (skinnydebug)
05831          ast_verb(1, "Received Open Receive Channel Ack\n");
05832 
05833       res = handle_open_receive_channel_ack_message(req, s);
05834       break;
05835    case SOFT_KEY_SET_REQ_MESSAGE:
05836       if (skinnydebug)
05837          ast_verb(1, "Received SoftKeySetReq\n");
05838 
05839       res = handle_soft_key_set_req_message(req, s);
05840       break;
05841    case SOFT_KEY_EVENT_MESSAGE:
05842       res = handle_soft_key_event_message(req, s);
05843       break;
05844    case UNREGISTER_MESSAGE:
05845       if (skinnydebug)
05846          ast_verb(1, "Received Unregister Request\n");
05847 
05848       res = handle_unregister_message(req, s);
05849       break;
05850    case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
05851       if (skinnydebug)
05852          ast_verb(1, "Received SoftKey Template Request\n");
05853 
05854       res = handle_soft_key_template_req_message(req, s);
05855       break;
05856    case HEADSET_STATUS_MESSAGE:
05857       res = handle_headset_status_message(req, s);
05858       break;
05859    case REGISTER_AVAILABLE_LINES_MESSAGE:
05860       res = handle_register_available_lines_message(req, s);
05861       break;
05862    default:
05863       if (skinnydebug)
05864          ast_verb(1, "RECEIVED UNKNOWN MESSAGE TYPE:  %x\n", letohl(req->e));
05865       break;
05866    }
05867    if (res >= 0 && req)
05868       ast_free(req);
05869    return res;
05870 }

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

Definition at line 4700 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, AST_CONTROL_ANSWER, ast_debug, AST_DEVICE_INUSE, ast_devstate_changed(), ast_hangup(), AST_LIST_TRAVERSE, ast_log(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_verb, ast_verbose, skinny_req::data, errno, find_line_by_instance(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, offhook_message::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, skinny_device::lastcallreference, skinny_device::lastlineinstance, letohl, skinny_device::lines, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_data::offhook, offhook_message::reference, s, SKINNY_CONNECTED, SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, skinny_ss(), start_rtp(), STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_callstate(), transmit_callstateonly(), transmit_displaymessage(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_tone(), and VERBOSE_PREFIX_3.

Referenced by handle_message().

04701 {
04702    struct skinny_device *d = s->device;
04703    struct skinny_line *l;
04704    struct skinny_subchannel *sub;
04705    struct ast_channel *c;
04706    struct skinny_line *tmp;
04707    pthread_t t;
04708    int instance;
04709    int reference;
04710 
04711    /* if any line on a device is offhook, than the device must be offhook, 
04712       unless we have shared lines CCM seems that it would never get here, 
04713       but asterisk does, so we may need to do more work.  Ugly, we should 
04714       probably move hookstate from line to device, afterall, it's actually
04715        a device that changes hookstates */
04716 
04717    AST_LIST_TRAVERSE(&d->lines, tmp, list) {
04718       if (tmp->hookstate == SKINNY_OFFHOOK) {
04719          ast_verbose(VERBOSE_PREFIX_3 "Got offhook message when device (%s@%s) already offhook\n", tmp->name, d->name);
04720          return 0;
04721       }
04722    }
04723 
04724    instance = letohl(req->data.offhook.instance);
04725    reference = letohl(req->data.offhook.reference);
04726 
04727    if (instance) {
04728       sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04729       if (!sub) {
04730          l = find_line_by_instance(d, d->lastlineinstance);
04731          if (!l) {
04732             return 0;
04733          }
04734       } else {
04735          l = sub->parent;
04736       }
04737    } else {
04738       l = d->activeline;
04739       sub = l->activesub;
04740    }
04741 
04742    transmit_ringer_mode(d, SKINNY_RING_OFF);
04743    l->hookstate = SKINNY_OFFHOOK;
04744 
04745    ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name);
04746 
04747    if (sub && sub->onhold) {
04748       return 1;
04749    }
04750 
04751    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04752 
04753    if (sub && sub->outgoing) {
04754       /* We're answering a ringing call */
04755       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
04756       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04757       transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04758       transmit_callstateonly(d, sub, SKINNY_CONNECTED);
04759       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
04760       start_rtp(sub);
04761       ast_setstate(sub->owner, AST_STATE_UP);
04762    } else {
04763       if (sub && sub->owner) {
04764          ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
04765       } else {
04766          c = skinny_new(l, AST_STATE_DOWN);
04767          if (c) {
04768             sub = c->tech_pvt;
04769             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04770             if (skinnydebug)
04771                ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04772             transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04773             transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04774             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
04775 
04776             /* start the switch thread */
04777             if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04778                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04779                ast_hangup(c);
04780             }
04781          } else {
04782             ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04783          }
04784       }
04785    }
04786    return 1;
04787 }

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

Definition at line 4789 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, skinny_subchannel::alreadygone, ast_debug, AST_DEVICE_NOT_INUSE, ast_devstate_changed(), AST_LIST_NEXT, AST_LIST_REMOVE, ast_log(), ast_queue_hangup(), AST_STATE_RING, skinny_subchannel::blindxfer, skinny_subchannel::callid, skinny_subchannel::cxmode, skinny_req::data, do_housekeeping(), find_subchannel_by_instance_reference(), handle_transfer_button(), skinny_line::hookstate, skinny_line::instance, onhook_message::instance, letohl, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::onhold, skinny_data::onhook, skinny_subchannel::owner, skinny_subchannel::parent, onhook_message::reference, skinny_subchannel::related, s, SKINNY_CX_RECVONLY, SKINNY_ONHOOK, skinny_line::sub, skinny_line::transfer, transmit_callstate(), and skinny_subchannel::xferor.

Referenced by handle_message().

04790 {
04791    struct skinny_device *d = s->device;
04792    struct skinny_line *l;
04793    struct skinny_subchannel *sub;
04794    int instance;
04795    int reference;
04796    int onlysub = 0;
04797 
04798    instance = letohl(req->data.onhook.instance);
04799    reference = letohl(req->data.onhook.reference);
04800 
04801    if (instance && reference) {
04802       sub = find_subchannel_by_instance_reference(d, instance, reference);
04803       if (!sub) {
04804          return 0;
04805       }
04806       l = sub->parent;
04807    } else {
04808       l = d->activeline;
04809       sub = l->activesub;
04810    }
04811 
04812    if (l->hookstate == SKINNY_ONHOOK) {
04813       /* Something else already put us back on hook */
04814       return 0;
04815    }
04816 
04817    ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
04818 
04819    if (sub->onhold) {
04820       return 0;
04821    }
04822 
04823    if (!AST_LIST_NEXT(sub, list)) {
04824       onlysub = 1;
04825    } else {
04826       AST_LIST_REMOVE(&l->sub, sub, list);
04827    }
04828 
04829    sub->cxmode = SKINNY_CX_RECVONLY;
04830    if (onlysub || sub->xferor){  /* is this the only call to this device? */
04831       l->hookstate = SKINNY_ONHOOK;
04832       if (skinnydebug)
04833          ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, reference);
04834    }
04835 
04836    transmit_callstate(d, l->instance, l->hookstate, sub->callid);
04837    if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
04838       /* We're allowed to transfer, we have two active calls and
04839          we made at least one of the calls.  Let's try and transfer */
04840       handle_transfer_button(sub);
04841    } else {
04842       /* Hangup the current call */
04843       /* If there is another active call, skinny_hangup will ring the phone with the other call */
04844       if (sub->xferor && sub->related){
04845          sub->related->related = NULL;
04846          sub->related->blindxfer = 0;
04847       }
04848 
04849       if (sub->owner) {
04850          sub->alreadygone = 1;
04851          ast_queue_hangup(sub->owner);
04852       } else {
04853          ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
04854             l->name, d->name, sub->callid);
04855       }
04856    }
04857    /* The bit commented below gives a very occasional core dump. */
04858    if ((l->hookstate == SKINNY_ONHOOK) && (AST_LIST_NEXT(sub, list) /*&& !AST_LIST_NEXT(sub, list)->rtp*/)) {
04859       do_housekeeping(s);
04860    }
04861    return 1;
04862 }

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

Definition at line 5166 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), ast_inet_ntoa(), ast_log(), ast_rtp_get_us(), ast_rtp_set_peer(), ast_verb, 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, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, open_receive_channel_ack_message::status, status, transmit_response(), and media_qualifier::vad.

Referenced by handle_message().

05167 {
05168    struct skinny_device *d = s->device;
05169    struct skinny_line *l;
05170    struct skinny_subchannel *sub;
05171    struct ast_format_list fmt;
05172    struct sockaddr_in sin;
05173    struct sockaddr_in us;
05174    uint32_t addr;
05175    int port;
05176    int status;
05177    int passthruid;
05178 
05179    status = letohl(req->data.openreceivechannelack.status);
05180    if (status) {
05181       ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
05182       return 0;
05183    }
05184    addr = letohl(req->data.openreceivechannelack.ipAddr);
05185    port = letohl(req->data.openreceivechannelack.port);
05186    passthruid = letohl(req->data.openreceivechannelack.passThruId);
05187 
05188    sin.sin_family = AF_INET;
05189    sin.sin_addr.s_addr = addr;
05190    sin.sin_port = htons(port);
05191 
05192    sub = find_subchannel_by_reference(d, passthruid);
05193 
05194    if (!sub)
05195       return 0;
05196 
05197    l = sub->parent;
05198 
05199    if (sub->rtp) {
05200       ast_rtp_set_peer(sub->rtp, &sin);
05201       ast_rtp_get_us(sub->rtp, &us);
05202    } else {
05203       ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
05204       return 0;
05205    }
05206 
05207    if (skinnydebug)
05208       ast_verb(1, "ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
05209 
05210    if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
05211       return -1;
05212 
05213    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
05214 
05215    if (skinnydebug)
05216       ast_verb(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
05217 
05218    req->data.startmedia.conferenceId = htolel(sub->callid);
05219    req->data.startmedia.passThruPartyId = htolel(sub->callid);
05220    req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
05221    req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
05222    req->data.startmedia.packetSize = htolel(fmt.cur_ms);
05223    req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
05224    req->data.startmedia.qualifier.precedence = htolel(127);
05225    req->data.startmedia.qualifier.vad = htolel(0);
05226    req->data.startmedia.qualifier.packets = htolel(0);
05227    req->data.startmedia.qualifier.bitRate = htolel(0);
05228    transmit_response(d, req);
05229 
05230    return 1;
05231 }

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

Definition at line 5697 of file chan_skinny.c.

Referenced by handle_message().

05698 {
05699    /* XXX I have no clue what this is for, but my phone was sending it, so... */
05700    return 1;
05701 }

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

Definition at line 4179 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, CAPABILITIES_REQ_MESSAGE, skinny_req::data, register_ack_message::dateTemplate, register_rej_message::errMsg, errno, htolel, register_ack_message::keepAlive, skinny_req::len, letohl, LOG_ERROR, LOG_WARNING, register_message::name, skinny_data::reg, skinny_data::regack, REGISTER_ACK_MESSAGE, REGISTER_REJ_MESSAGE, skinny_data::regrej, req_alloc(), register_ack_message::res, register_ack_message::res2, s, register_ack_message::secondaryKeepAlive, SKINNY_MAX_PACKET, skinny_register(), and transmit_response().

Referenced by handle_message().

04180 {
04181    struct skinny_device *d = NULL;
04182    char name[16];
04183    int res;
04184 
04185    memcpy(&name, req->data.reg.name, sizeof(name));
04186 
04187    res = skinny_register(req, s);
04188    if (!res) {
04189       ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
04190       if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
04191          return -1;
04192 
04193       snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
04194 
04195       /* transmit_respons in line as we don't have a valid d */
04196       ast_mutex_lock(&s->lock);
04197 
04198       if (letohl(req->len > SKINNY_MAX_PACKET) || letohl(req->len < 0)) {
04199          ast_log(LOG_WARNING, "transmit_response: the length of the request is out of bounds\n");
04200          ast_mutex_unlock(&s->lock);
04201          return -1;
04202       }
04203 
04204       memset(s->outbuf, 0, sizeof(s->outbuf));
04205       memcpy(s->outbuf, req, skinny_header_size);
04206       memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
04207 
04208       res = write(s->fd, s->outbuf, letohl(req->len)+8);
04209 
04210       if (res != letohl(req->len)+8) {
04211          ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
04212       }
04213    
04214       ast_mutex_unlock(&s->lock);
04215 
04216       return 0;
04217    }
04218    ast_verb(3, "Device '%s' successfully registered\n", name);
04219 
04220    d = s->device;
04221    
04222    if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
04223       return -1;
04224 
04225    req->data.regack.res[0] = '0';
04226    req->data.regack.res[1] = '\0';
04227    req->data.regack.keepAlive = htolel(keep_alive);
04228    memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
04229    req->data.regack.res2[0] = '0';
04230    req->data.regack.res2[1] = '\0';
04231    req->data.regack.secondaryKeepAlive = htolel(keep_alive);
04232    transmit_response(d, req);
04233    if (skinnydebug)
04234       ast_verb(1, "Requesting capabilities\n");
04235 
04236    if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
04237       return -1;
04238 
04239    transmit_response(d, req);
04240 
04241    return res;
04242 }

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

Definition at line 5143 of file chan_skinny.c.

References skinny_req::data, htolel, skinny_device::ourip, 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().

05144 {
05145    struct skinny_device *d = s->device;
05146    if (!(req = req_alloc(sizeof(struct server_res_message), SERVER_RES_MESSAGE)))
05147       return -1;
05148 
05149    memcpy(req->data.serverres.server[0].serverName, ourhost,
05150          sizeof(req->data.serverres.server[0].serverName));
05151    req->data.serverres.serverListenPort[0] = htolel(ourport);
05152    req->data.serverres.serverIpAddr[0] = htolel(d->ourip.s_addr);
05153    transmit_response(d, req);
05154    return 1;
05155 }

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

Definition at line 2596 of file chan_skinny.c.

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

02597 {
02598    struct skinny_device *d;
02599    struct skinny_req *req;
02600 
02601    switch (cmd) {
02602    case CLI_INIT:
02603       e->command = "skinny reset";
02604       e->usage =
02605          "Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
02606          "       Causes a Skinny device to reset itself, optionally with a full restart\n";
02607       return NULL;
02608    case CLI_GENERATE:
02609       return complete_skinny_reset(a->line, a->word, a->pos, a->n);
02610    }
02611 
02612    if (a->argc < 3 || a->argc > 4)
02613       return CLI_SHOWUSAGE;
02614 
02615    AST_LIST_LOCK(&devices);
02616    AST_LIST_TRAVERSE(&devices, d, list) {
02617       int fullrestart = 0;
02618       if (!strcasecmp(a->argv[2], d->id) || !strcasecmp(a->argv[2], d->name) || !strcasecmp(a->argv[2], "all")) {
02619          if (!(d->session))
02620             continue;
02621 
02622          if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
02623             continue;
02624 
02625          if (a->argc == 4 && !strcasecmp(a->argv[3], "restart"))
02626             fullrestart = 1;
02627 
02628          if (fullrestart)
02629             req->data.reset.resetType = 2;
02630          else
02631             req->data.reset.resetType = 1;
02632 
02633          ast_verb(3, "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id);
02634          transmit_response(d, req);
02635       }
02636    }
02637    AST_LIST_UNLOCK(&devices);
02638    return CLI_SUCCESS;
02639 }

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

Definition at line 2523 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, and ast_cli_entry::usage.

02524 {
02525    switch (cmd) {
02526    case CLI_INIT:
02527       e->command = "skinny set debug {on|off}";
02528       e->usage =
02529          "Usage: skinny set debug {on|off}\n"
02530          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02531       return NULL;
02532    case CLI_GENERATE:
02533       return NULL;
02534    }
02535    
02536    if (a->argc != e->args)
02537       return CLI_SHOWUSAGE;
02538 
02539    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
02540       skinnydebug = 1;
02541       ast_cli(a->fd, "Skinny Debugging Enabled\n");
02542       return CLI_SUCCESS;
02543    } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
02544       skinnydebug = 0;
02545       ast_cli(a->fd, "Skinny Debugging Disabled\n");
02546       return CLI_SUCCESS;
02547    } else {
02548       return CLI_SHOWUSAGE;
02549    }
02550 }

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

Definition at line 2494 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, and ast_cli_entry::usage.

02495 {
02496    switch (cmd) {
02497    case CLI_INIT:
02498       e->command = "skinny set debug [off]";
02499       e->usage =
02500          "Usage: skinny set debug [off]\n"
02501          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02502       return NULL;
02503    case CLI_GENERATE:
02504       return NULL;
02505    }
02506    
02507    if (a->argc < 3 || a->argc > 4)
02508       return CLI_SHOWUSAGE;
02509 
02510    if (a->argc == 3) {
02511       skinnydebug = 1;
02512       ast_cli(a->fd, "Skinny Debugging Enabled\n");
02513       return CLI_SUCCESS;
02514    } else if (!strncasecmp(a->argv[3], "off", 3)) {
02515       skinnydebug = 0;
02516       ast_cli(a->fd, "Skinny Debugging Disabled\n");
02517       return CLI_SUCCESS;
02518    } else {
02519       return CLI_SHOWUSAGE;
02520    }
02521 }

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 2790 of file chan_skinny.c.

References skinny_device::addons, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_skinny_show_device(), device2str(), 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, 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.

02791 {
02792    struct skinny_device *d;
02793    struct skinny_line *l;
02794    struct skinny_speeddial *sd;
02795    struct skinny_addon *sa;
02796 
02797    switch (cmd) {
02798    case CLI_INIT:
02799       e->command = "skinny show device";
02800       e->usage =
02801          "Usage: skinny show device <DeviceId|DeviceName>\n"
02802          "       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
02803       return NULL;
02804    case CLI_GENERATE:
02805       return complete_skinny_show_device(a->line, a->word, a->pos, a->n);
02806    }
02807 
02808    if (a->argc < 4)
02809       return CLI_SHOWUSAGE;
02810 
02811    AST_LIST_LOCK(&devices);
02812    AST_LIST_TRAVERSE(&devices, d, list) {
02813       if (!strcasecmp(a->argv[3], d->id) || !strcasecmp(a->argv[3], d->name)) {
02814          int numlines = 0, numaddons = 0, numspeeddials = 0;
02815 
02816          AST_LIST_TRAVERSE(&d->lines, l, list){
02817             numlines++;
02818          }
02819 
02820          ast_cli(a->fd, "Name:        %s\n", d->name);
02821          ast_cli(a->fd, "Id:          %s\n", d->id);
02822          ast_cli(a->fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
02823          ast_cli(a->fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
02824          ast_cli(a->fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
02825          ast_cli(a->fd, "Device Type: %s\n", device2str(d->type));
02826          ast_cli(a->fd, "Registered:  %s\n", (d->registered ? "Yes" : "No"));
02827          ast_cli(a->fd, "Lines:       %d\n", numlines);
02828          AST_LIST_TRAVERSE(&d->lines, l, list) {
02829             ast_cli(a->fd, "  %s (%s)\n", l->name, l->label);
02830          }
02831          AST_LIST_TRAVERSE(&d->addons, sa, list) {
02832             numaddons++;
02833          }  
02834          ast_cli(a->fd, "Addons:      %d\n", numaddons);
02835          AST_LIST_TRAVERSE(&d->addons, sa, list) {
02836             ast_cli(a->fd, "  %s\n", sa->type);
02837          }
02838          AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
02839             numspeeddials++;
02840          }
02841          ast_cli(a->fd, "Speeddials:  %d\n", numspeeddials);
02842          AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
02843             ast_cli(a->fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
02844          }
02845       }
02846    }
02847    AST_LIST_UNLOCK(&devices);
02848    return CLI_SUCCESS;
02849 }

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

Definition at line 2748 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, device2str(), ast_cli_args::fd, skinny_device::id, skinny_device::lines, skinny_device::name, skinny_device::registered, skinny_device::session, skinnysession::sin, skinny_device::type, and ast_cli_entry::usage.

02749 {
02750    struct skinny_device *d;
02751    struct skinny_line *l;
02752 
02753    switch (cmd) {
02754    case CLI_INIT:
02755       e->command = "skinny show devices";
02756       e->usage =
02757          "Usage: skinny show devices\n"
02758          "       Lists all devices known to the Skinny subsystem.\n";
02759       return NULL;
02760    case CLI_GENERATE:
02761       return NULL;
02762    }
02763 
02764    if (a->argc != 3)
02765       return CLI_SHOWUSAGE;
02766 
02767    ast_cli(a->fd, "Name                 DeviceId         IP              Type            R NL\n");
02768    ast_cli(a->fd, "-------------------- ---------------- --------------- --------------- - --\n");
02769 
02770    AST_LIST_LOCK(&devices); 
02771    AST_LIST_TRAVERSE(&devices, d, list) {
02772       int numlines = 0;
02773       AST_LIST_TRAVERSE(&d->lines, l, list) {
02774          numlines++;
02775       }
02776       
02777       ast_cli(a->fd, "%-20s %-16s %-15s %-15s %c %2d\n",
02778          d->name,
02779          d->id,
02780          d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
02781          device2str(d->type),
02782          d->registered?'Y':'N',
02783          numlines);
02784    }
02785    AST_LIST_UNLOCK(&devices);
02786    return CLI_SUCCESS;
02787 }

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 2888 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_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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, CLI_SUCCESS, ast_cli_entry::command, complete_skinny_show_line(), skinny_line::context, 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::parkinglot, 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.

02889 {
02890    struct skinny_device *d;
02891    struct skinny_line *l;
02892    char codec_buf[512];
02893    char group_buf[256];
02894 
02895    switch (cmd) {
02896    case CLI_INIT:
02897       e->command = "skinny show line";
02898       e->usage =
02899          "Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
02900          "       List all lineinformation of a specific line known to the Skinny subsystem.\n";
02901       return NULL;
02902    case CLI_GENERATE:
02903       return complete_skinny_show_line(a->line, a->word, a->pos, a->n);
02904    }
02905 
02906    if (a->argc < 4)
02907       return CLI_SHOWUSAGE;
02908    
02909    AST_LIST_LOCK(&devices);
02910 
02911    /* Show all lines matching the one supplied */
02912    AST_LIST_TRAVERSE(&devices, d, list) {
02913       if (a->argc == 6 && (strcasecmp(a->argv[5], d->id) && strcasecmp(a->argv[5], d->name)))
02914          continue;
02915       AST_LIST_TRAVERSE(&d->lines, l, list) {
02916          if (strcasecmp(a->argv[3], l->name))
02917             continue;
02918          ast_cli(a->fd, "Line:             %s\n", l->name);
02919          ast_cli(a->fd, "On Device:        %s\n", d->name);
02920          ast_cli(a->fd, "Line Label:       %s\n", l->label);
02921          ast_cli(a->fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
02922          ast_cli(a->fd, "Context:          %s\n", l->context);
02923          ast_cli(a->fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
02924          ast_cli(a->fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
02925          ast_cli(a->fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
02926          ast_cli(a->fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
02927          ast_cli(a->fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
02928          ast_cli(a->fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
02929          ast_cli(a->fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
02930          ast_cli(a->fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
02931          ast_cli(a->fd, "CFwdAll:          %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
02932          ast_cli(a->fd, "CFwdBusy:         %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
02933          ast_cli(a->fd, "CFwdNoAnswer:     %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
02934          ast_cli(a->fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
02935          ast_cli(a->fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
02936          ast_cli(a->fd, "MWIblink:         %d\n", l->mwiblink);
02937          ast_cli(a->fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
02938          ast_cli(a->fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
02939          ast_cli(a->fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
02940          ast_cli(a->fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
02941          ast_cli(a->fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
02942          ast_cli(a->fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
02943          ast_cli(a->fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
02944          ast_cli(a->fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
02945          ast_cli(a->fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
02946          ast_cli(a->fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
02947          ast_cli(a->fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
02948          ast_cli(a->fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
02949          ast_cli(a->fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
02950          ast_cli(a->fd, "Group:            %d\n", l->group);
02951          ast_cli(a->fd, "Parkinglot:       %s\n", S_OR(l->parkinglot, "<not set>"));
02952          ast_cli(a->fd, "Codecs:           ");
02953          ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->capability);
02954          ast_cli(a->fd, "%s\n", codec_buf);
02955          ast_cli(a->fd, "Codec Order:      (");
02956          print_codec_to_cli(a->fd, &l->prefs);
02957          ast_cli(a->fd, ")\n");
02958          ast_cli(a->fd, "\n");
02959       }
02960    }
02961    
02962    AST_LIST_UNLOCK(&devices);
02963    return CLI_SUCCESS;
02964 }

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

Definition at line 2851 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, skinny_line::instance, skinny_line::label, skinny_device::lines, skinny_line::name, skinny_device::name, and ast_cli_entry::usage.

02852 {
02853    struct skinny_device *d;
02854    struct skinny_line *l;
02855 
02856    switch (cmd) {
02857    case CLI_INIT:
02858       e->command = "skinny show lines";
02859       e->usage =
02860          "Usage: skinny show lines\n"
02861          "       Lists all lines known to the Skinny subsystem.\n";
02862       return NULL;
02863    case CLI_GENERATE:
02864       return NULL;
02865    }
02866 
02867    if (a->argc != 3)
02868       return CLI_SHOWUSAGE;
02869    
02870    
02871    ast_cli(a->fd, "Device Name          Instance Name                 Label               \n");
02872    ast_cli(a->fd, "-------------------- -------- -------------------- --------------------\n");
02873    AST_LIST_LOCK(&devices);
02874    AST_LIST_TRAVERSE(&devices, d, list) {
02875       AST_LIST_TRAVERSE(&d->lines, l, list) {
02876          ast_cli(a->fd, "%-20s %8d %-20s %-20s\n",
02877             d->name,
02878             l->instance,
02879             l->name,
02880             l->label);
02881       }
02882    }
02883    AST_LIST_UNLOCK(&devices);
02884    return CLI_SUCCESS;
02885 }

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 2967 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, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, global_jbconf, ast_jb_conf::impl, ast_jb_conf::max_size, ast_jb_conf::resync_threshold, S_OR, and ast_cli_entry::usage.

02968 {
02969    switch (cmd) {
02970    case CLI_INIT:
02971       e->command = "skinny show settings";
02972       e->usage =
02973          "Usage: skinny show settings\n"
02974          "       Lists all global configuration settings of the Skinny subsystem.\n";
02975       return NULL;
02976    case CLI_GENERATE:
02977       return NULL;
02978    }  
02979 
02980    if (a->argc != 3)
02981       return CLI_SHOWUSAGE;
02982 
02983    ast_cli(a->fd, "\nGlobal Settings:\n");
02984    ast_cli(a->fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
02985    ast_cli(a->fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
02986    ast_cli(a->fd, "  KeepAlive:              %d\n", keep_alive);
02987    ast_cli(a->fd, "  Date Format:            %s\n", date_format);
02988    ast_cli(a->fd, "  Voice Mail Extension:   %s\n", S_OR(vmexten, "(not set)"));
02989    ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
02990    ast_cli(a->fd, "  Jitterbuffer enabled:   %s\n", (ast_test_flag(&global_jbconf, AST_JB_ENABLED) ? "Yes" : "No"));
02991    ast_cli(a->fd, "  Jitterbuffer forced:    %s\n", (ast_test_flag(&global_jbconf, AST_JB_FORCED) ? "Yes" : "No"));
02992    ast_cli(a->fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
02993    ast_cli(a->fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
02994    ast_cli(a->fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
02995    ast_cli(a->fd, "  Jitterbuffer log:       %s\n", (ast_test_flag(&global_jbconf, AST_JB_LOG) ? "Yes" : "No"));
02996 
02997    return CLI_SUCCESS;
02998 }

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

Definition at line 5316 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_ANSWER, ast_copy_string(), ast_debug, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_devstate_changed(), ast_hangup(), ast_ignore_pattern(), AST_LIST_NEXT, AST_LIST_REMOVE, ast_log(), ast_masq_park_call(), ast_pthread_create, ast_queue_control(), ast_queue_hangup(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::blindxfer, 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(), handle_hold_button(), handle_transfer_button(), skinny_line::hookstate, skinny_line::instance, soft_key_event_message::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_ONHOLD, KEYDEF_RINGOUT, skinny_device::lastcallreference, skinny_device::lastlineinstance, skinny_line::lastnumberdialed, letohl, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::related, 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(), 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, skinny_line::sub, ast_channel::tech_pvt, skinny_line::transfer, transmit_callstate(), transmit_callstateonly(), transmit_displaymessage(), transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_tone(), and skinny_subchannel::xferor.

Referenced by handle_message().

05317 {
05318    struct skinny_device *d = s->device;
05319    struct skinny_line *l;
05320    struct skinny_subchannel *sub = NULL;
05321    struct ast_channel *c;
05322    pthread_t t;
05323    int event;
05324    int instance;
05325    int callreference;
05326 
05327    event = letohl(req->data.softkeyeventmessage.softKeyEvent);
05328    instance = letohl(req->data.softkeyeventmessage.instance);
05329    callreference = letohl(req->data.softkeyeventmessage.callreference);
05330 
05331    if (instance) {
05332       l = find_line_by_instance(d, instance);
05333       if (callreference) {
05334          sub = find_subchannel_by_instance_reference(d, instance, callreference);
05335       } else {
05336          sub = find_subchannel_by_instance_reference(d, instance, d->lastcallreference);
05337       }
05338    } else {
05339       l = find_line_by_instance(d, d->lastlineinstance);
05340    }
05341 
05342    if (!l) {
05343       if (skinnydebug)
05344          ast_verb(1, "Received Softkey Event: %d(%d/%d)\n", event, instance, callreference);
05345       return 0;
05346    }
05347 
05348    ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name);
05349 
05350    switch(event) {
05351    case SOFTKEY_NONE:
05352       if (skinnydebug)
05353          ast_verb(1, "Received Softkey Event: None(%d/%d)\n", instance, callreference);
05354       break;
05355    case SOFTKEY_REDIAL:
05356       if (skinnydebug)
05357          ast_verb(1, "Received Softkey Event: Redial(%d/%d)\n", instance, callreference);
05358 
05359       if (ast_strlen_zero(l->lastnumberdialed)) {
05360          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
05361          l->hookstate = SKINNY_ONHOOK;
05362          transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
05363          transmit_callstate(d, l->instance, SKINNY_ONHOOK, instance);
05364          break;
05365       }
05366 
05367       if (!sub || !sub->owner) {
05368          c = skinny_new(l, AST_STATE_DOWN);
05369       } else {
05370          c = sub->owner;
05371       }
05372 
05373       if (!c) {
05374          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05375       } else {
05376          sub = c->tech_pvt;
05377          if (l->hookstate == SKINNY_ONHOOK) {
05378             l->hookstate = SKINNY_OFFHOOK;
05379             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05380             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05381          }
05382          if (skinnydebug)
05383             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05384          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05385          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05386          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
05387 
05388          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
05389             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05390          }
05391          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
05392          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05393             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05394             ast_hangup(c);
05395          }
05396       }
05397       break;
05398    case SOFTKEY_NEWCALL:  /* Actually the DIAL softkey */
05399       if (skinnydebug)
05400          ast_verb(1, "Received Softkey Event: New Call(%d/%d)\n", instance, callreference);
05401 
05402       /* New Call ALWAYS gets a new sub-channel */
05403       c = skinny_new(l, AST_STATE_DOWN);
05404       sub = c->tech_pvt;
05405    
05406       /* transmit_ringer_mode(d, SKINNY_RING_OFF);
05407       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON); */
05408 
05409       /* l->hookstate = SKINNY_OFFHOOK; */
05410 
05411       if (!c) {
05412          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05413       } else {
05414          sub = c->tech_pvt;
05415          if (l->hookstate == SKINNY_ONHOOK) {
05416             l->hookstate = SKINNY_OFFHOOK;
05417             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05418          }
05419          ast_verb(1, "Call-id: %d\n", sub->callid);
05420 
05421          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05422 
05423          if (skinnydebug)
05424             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05425          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05426          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05427          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05428 
05429          /* start the switch thread */
05430          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05431             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05432             ast_hangup(c);
05433          }
05434       }
05435       break;
05436    case SOFTKEY_HOLD:
05437       if (skinnydebug)
05438          ast_verb(1, "Received Softkey Event: Hold(%d/%d)\n", instance, callreference);
05439       handle_hold_button(sub);   
05440       break;
05441    case SOFTKEY_TRNSFER:
05442       if (skinnydebug)
05443          ast_verb(1, "Received Softkey Event: Transfer(%d/%d)\n", instance, callreference);
05444       if (l->transfer)
05445          handle_transfer_button(sub);
05446       else
05447          transmit_displaynotify(d, "Transfer disabled", 10);
05448 
05449       break;
05450    case SOFTKEY_DND:
05451       if (skinnydebug)
05452          ast_verb(1, "Received Softkey Event: DND(%d/%d)\n", instance, callreference);
05453 
05454       /* Do not disturb */
05455       if (l->dnd != 0){
05456          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
05457          l->dnd = 0;
05458          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
05459          transmit_displaynotify(d, "DnD disabled", 10);
05460       } else {
05461          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
05462          l->dnd = 1;
05463          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
05464          transmit_displaynotify(d, "DnD enabled", 10);
05465       }
05466       break;
05467    case SOFTKEY_CFWDALL:
05468       if (skinnydebug)
05469          ast_verb(1, "Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
05470 
05471       if (!sub || !sub->owner) {
05472          c = skinny_new(l, AST_STATE_DOWN);
05473       } else {
05474          c = sub->owner;
05475       }
05476 
05477       if (!c) {
05478          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05479       } else {
05480          sub = c->tech_pvt;
05481          handle_callforward_button(sub, SKINNY_CFWD_ALL);
05482       }
05483       break;
05484    case SOFTKEY_CFWDBUSY:
05485       if (skinnydebug)
05486          ast_verb(1, "Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
05487 
05488       if (!sub || !sub->owner) {
05489          c = skinny_new(l, AST_STATE_DOWN);
05490       } else {
05491          c = sub->owner;
05492       }
05493 
05494       if (!c) {
05495          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05496       } else {
05497          sub = c->tech_pvt;
05498          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
05499       }
05500       break;
05501    case SOFTKEY_CFWDNOANSWER:
05502       if (skinnydebug)
05503          ast_verb(1, "Received Softkey Event: Forward No Answer (%d/%d)\n", instance, callreference);
05504 
05505 #if 0 /* Not sure how to handle this yet */
05506       if (!sub || !sub->owner) {
05507          c = skinny_new(l, AST_STATE_DOWN);
05508       } else {
05509          c = sub->owner;
05510       }
05511 
05512       if (!c) {
05513          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05514       } else {
05515          sub = c->tech_pvt;
05516          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
05517       }
05518 #endif
05519       break;
05520    case SOFTKEY_BKSPC:
05521       if (skinnydebug)
05522          ast_verb(1, "Received Softkey Event: Backspace(%d/%d)\n", instance, callreference);
05523       break;
05524    case SOFTKEY_ENDCALL:
05525       if (skinnydebug)
05526          ast_verb(1, "Received Softkey Event: End Call(%d/%d)\n", instance, callreference);
05527 
05528       if (l->hookstate == SKINNY_ONHOOK) {
05529          /* Something else already put us back on hook */
05530          break;
05531       }
05532       if (sub) {
05533          int onlysub = 0;
05534 
05535          if (!AST_LIST_NEXT(sub, list)) {
05536             onlysub = 1;
05537          } else {
05538             AST_LIST_REMOVE(&l->sub, sub, list);
05539          }
05540 
05541          sub->cxmode = SKINNY_CX_RECVONLY;
05542          if (onlysub || sub->xferor){    /*Are there other calls to this device */
05543             l->hookstate = SKINNY_ONHOOK;
05544             if (skinnydebug)
05545                ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, callreference);
05546          }
05547 
05548          transmit_callstate(d, l->instance, l->hookstate, sub->callid);
05549          ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
05550          if (skinnydebug)
05551             ast_verb(1, "Skinny %s@%s went on hook\n", l->name, d->name);
05552          if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
05553             /* We're allowed to transfer, we have two active calls and
05554                we made at least one of the calls.  Let's try and transfer */
05555             handle_transfer_button(sub);
05556          } else {
05557             /* Hangup the current call */
05558             /* If there is another active call, skinny_hangup will ring the phone with the other call */
05559             if (sub->xferor && sub->related){
05560                sub->related->related = NULL;
05561                sub->related->blindxfer = 0;
05562             }
05563 
05564             if (sub->owner) {
05565                sub->alreadygone = 1;
05566                ast_queue_hangup(sub->owner);
05567             } else {
05568                ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
05569                   l->name, d->name, sub->callid);
05570             }
05571          }
05572          if ((l->hookstate == SKINNY_ONHOOK) && (AST_LIST_NEXT(sub, list) && !AST_LIST_NEXT(sub, list)->rtp)) {
05573             do_housekeeping(s);
05574             ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
05575          }
05576       }
05577       break;
05578    case SOFTKEY_RESUME:
05579       if (skinnydebug)
05580          ast_verb(1, "Received Softkey Event: Resume(%d/%d)\n", instance, callreference);
05581 
05582       if (sub) {
05583          if (sub->onhold) {
05584             skinny_unhold(sub);
05585             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05586          } else {
05587             skinny_hold(sub);
05588             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD);
05589          }
05590       }
05591 
05592       break;
05593    case SOFTKEY_ANSWER:
05594       if (skinnydebug)
05595          ast_verb(1, "Received Softkey Event: Answer(%d/%d)\n", instance, callreference);
05596 
05597       transmit_ringer_mode(d, SKINNY_RING_OFF);
05598       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05599       if (l->hookstate == SKINNY_ONHOOK) {
05600          transmit_speaker_mode(d, SKINNY_SPEAKERON);
05601          l->hookstate = SKINNY_OFFHOOK;
05602       }
05603 
05604       if (sub && sub->outgoing) {
05605          /* We're answering a ringing call */
05606          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05607          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05608          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05609          transmit_callstateonly(d, sub, SKINNY_CONNECTED);
05610          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05611          start_rtp(sub);
05612          ast_setstate(sub->owner, AST_STATE_UP);
05613       }
05614       break;
05615    case SOFTKEY_INFO:
05616       if (skinnydebug)
05617          ast_verb(1, "Received Softkey Event: Info(%d/%d)\n", instance, callreference);
05618       break;
05619    case SOFTKEY_CONFRN:
05620       if (skinnydebug)
05621          ast_verb(1, "Received Softkey Event: Conference(%d/%d)\n", instance, callreference);
05622       /* XXX determine the best way to pull off a conference.  Meetme? */
05623       break;
05624    case SOFTKEY_PARK:
05625       {
05626       int extout;
05627       char message[32];
05628 
05629       if (skinnydebug)
05630          ast_verb(1, "Received Softkey Event: Park Call(%d/%d)\n", instance, callreference);
05631 
05632       if ((sub && sub->owner) && (sub->owner->_state ==  AST_STATE_UP)){
05633          c = sub->owner;
05634          if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
05635             snprintf(message, sizeof(message), "Call Parked at: %d", extout);
05636             transmit_displaynotify(d, message, 10);
05637          } else {
05638             transmit_displaynotify(d, "Call Park failed", 10);
05639          }
05640       } else {
05641          transmit_displaynotify(d, "Call Park not available", 10);
05642       }
05643       }
05644       break;
05645    case SOFTKEY_JOIN:
05646       if (skinnydebug)
05647          ast_verb(1, "Received Softkey Event: Join(%d/%d)\n", instance, callreference);
05648       break;
05649    case SOFTKEY_MEETME:
05650       /* XXX How is this different from CONFRN? */
05651       if (skinnydebug)
05652          ast_verb(1, "Received Softkey Event: Meetme(%d/%d)\n", instance, callreference);
05653       break;
05654    case SOFTKEY_PICKUP:
05655       if (skinnydebug)
05656          ast_verb(1, "Received Softkey Event: Pickup(%d/%d)\n", instance, callreference);
05657       break;
05658    case SOFTKEY_GPICKUP:
05659       if (skinnydebug)
05660          ast_verb(1, "Received Softkey Event: Group Pickup(%d/%d)\n", instance, callreference);
05661       break;
05662    default:
05663       if (skinnydebug)
05664          ast_verb(1, "Received unknown Softkey Event: %d(%d/%d)\n", event, instance, callreference);
05665       break;
05666    }
05667 
05668    return 1;
05669 }

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

Definition at line 5283 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().

05284 {
05285    int i;
05286    int x;
05287    int y;
05288    const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
05289    struct skinny_device *d = s->device;
05290 
05291    if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
05292       return -1;
05293 
05294    req->data.softkeysets.softKeySetOffset = htolel(0);
05295    req->data.softkeysets.softKeySetCount = htolel(11);
05296    req->data.softkeysets.totalSoftKeySetCount = htolel(11);
05297    for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
05298       const uint8_t *defaults = softkeymode->defaults;
05299       /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
05300          This will have to do for now. */
05301       for (y = 0; y < softkeymode->count; y++) {
05302          for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
05303             if (defaults[y] == i+1) {
05304                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = htolel(i+1);
05305                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htolel(i+301);
05306             }
05307          }
05308       }
05309       softkeymode++;
05310    }
05311    transmit_response(d, req);
05312    transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
05313    return 1;
05314 }

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

Definition at line 5676 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().

05677 {
05678    if (!(req = req_alloc(sizeof(struct soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
05679       return -1;
05680 
05681    req->data.softkeytemplate.softKeyOffset = htolel(0);
05682    req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
05683    req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
05684    memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
05685       soft_key_template_default,
05686       sizeof(soft_key_template_default));
05687    transmit_response(s->device, req);
05688    return 1;
05689 }

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

Definition at line 4899 of file chan_skinny.c.

References ast_copy_string(), skinny_req::data, skinny_speeddial::exten, find_speeddial_by_instance(), htolel, 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().

04900 {
04901    struct skinny_device *d = s->device;
04902    struct skinny_speeddial *sd;
04903    int instance;
04904 
04905    instance = letohl(req->data.speeddialreq.speedDialNumber);
04906 
04907    sd = find_speeddial_by_instance(d, instance, 0);
04908 
04909    if (!sd) {
04910       return 0;
04911    }
04912 
04913    if (!(req = req_alloc(sizeof(struct speed_dial_stat_res_message), SPEED_DIAL_STAT_RES_MESSAGE)))
04914       return -1;
04915 
04916    req->data.speeddialreq.speedDialNumber = htolel(instance);
04917    ast_copy_string(req->data.speeddial.speedDialDirNumber, sd->exten, sizeof(req->data.speeddial.speedDialDirNumber));
04918    ast_copy_string(req->data.speeddial.speedDialDisplayName, sd->label, sizeof(req->data.speeddial.speedDialDisplayName));
04919 
04920    transmit_response(d, req);
04921    return 1;
04922 }

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

Definition at line 4359 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, ast_bridged_channel(), AST_CONTROL_ANSWER, ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_masq_park_call(), 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(), handle_hold_button(), handle_transfer_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::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, s, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_CONNECTED, SKINNY_DIALTONE, 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(), 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, skinny_line::transfer, transmit_callstate(), transmit_callstateonly(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_tone(), and skinny_line::vmexten.

Referenced by handle_message().

04360 {
04361    struct skinny_device *d = s->device;
04362    struct skinny_line *l;
04363    struct skinny_subchannel *sub;
04364    /*struct skinny_speeddial *sd;*/
04365    struct ast_channel *c;
04366    pthread_t t;
04367    int event;
04368    int instance;
04369    int callreference;
04370    /*int res = 0;*/
04371 
04372    event = letohl(req->data.stimulus.stimulus);
04373    instance = letohl(req->data.stimulus.stimulusInstance);
04374    callreference = letohl(req->data.stimulus.callreference); 
04375    if (skinnydebug)
04376       ast_verb(1, "callreference in handle_stimulus_message is '%d'\n", callreference);
04377 
04378    /*  Note that this call should be using the passed in instance and callreference */
04379    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04380 
04381    if (!sub) {
04382       l = find_line_by_instance(d, d->lastlineinstance);
04383       if (!l) {
04384          return 0;
04385       }
04386    } else {
04387       l = sub->parent;
04388    }
04389 
04390    switch(event) {
04391    case STIMULUS_REDIAL:
04392       if (skinnydebug)
04393          ast_verb(1, "Received Stimulus: Redial(%d/%d)\n", instance, callreference);
04394 
04395       if (ast_strlen_zero(l->lastnumberdialed)) {
04396          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
04397          l->hookstate = SKINNY_ONHOOK;
04398          transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04399          transmit_callstate(d, l->instance, SKINNY_ONHOOK, instance);
04400          break;
04401       }
04402 
04403       c = skinny_new(l, AST_STATE_DOWN);
04404       if (!c) {
04405          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04406       } else {
04407          sub = c->tech_pvt;
04408          l = sub->parent;
04409          if (l->hookstate == SKINNY_ONHOOK) {
04410             l->hookstate = SKINNY_OFFHOOK;
04411             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04412          }
04413          if (skinnydebug)
04414             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04415          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04416          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04417          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04418 
04419          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
04420             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04421          }
04422          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
04423          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04424             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04425             ast_hangup(c);
04426          }
04427       }
04428       break;
04429    case STIMULUS_SPEEDDIAL:
04430        {
04431       struct skinny_speeddial *sd;
04432 
04433       if (skinnydebug)
04434          ast_verb(1, "Received Stimulus: SpeedDial(%d/%d)\n", instance, callreference);
04435       if (!(sd = find_speeddial_by_instance(d, instance, 0))) {
04436          return 0;
04437       }
04438 
04439       if (!sub || !sub->owner)
04440          c = skinny_new(l, AST_STATE_DOWN);
04441       else
04442          c = sub->owner;
04443 
04444       if (!c) {
04445          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04446       } else {
04447          sub = c->tech_pvt;
04448          l = sub->parent;
04449          if (l->hookstate == SKINNY_ONHOOK) {
04450             l->hookstate = SKINNY_OFFHOOK;
04451             transmit_speaker_mode(d, SKINNY_SPEAKERON);
04452             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04453          }
04454          if (skinnydebug)
04455             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04456          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04457          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04458          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04459 
04460          if (!ast_ignore_pattern(c->context, sd->exten)) {
04461             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04462          }
04463          if (ast_exists_extension(c, c->context, sd->exten, 1, l->cid_num)) {
04464             ast_copy_string(c->exten, sd->exten, sizeof(c->exten));
04465             ast_copy_string(l->lastnumberdialed, sd->exten, sizeof(l->lastnumberdialed));
04466 
04467             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04468                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04469                ast_hangup(c);
04470             }
04471             break;
04472          }
04473       }
04474        }
04475       break;
04476    case STIMULUS_HOLD:
04477       if (skinnydebug)
04478          ast_verb(1, "Received Stimulus: Hold(%d/%d)\n", instance, callreference);
04479       handle_hold_button(sub);
04480       break;
04481    case STIMULUS_TRANSFER:
04482       if (skinnydebug)
04483          ast_verb(1, "Received Stimulus: Transfer(%d/%d)\n", instance, callreference);
04484       if (l->transfer)
04485          handle_transfer_button(sub);
04486       else
04487          transmit_displaynotify(d, "Transfer disabled", 10);
04488       break;
04489    case STIMULUS_CONFERENCE:
04490       if (skinnydebug)
04491          ast_verb(1, "Received Stimulus: Conference(%d/%d)\n", instance, callreference);
04492       /* XXX determine the best way to pull off a conference.  Meetme? */
04493       break;
04494    case STIMULUS_VOICEMAIL:
04495       if (skinnydebug)
04496          ast_verb(1, "Received Stimulus: Voicemail(%d/%d)\n", instance, callreference);
04497 
04498       if (!sub || !sub->owner) {
04499          c = skinny_new(l, AST_STATE_DOWN);
04500       } else {
04501          c = sub->owner;
04502       }
04503       if (!c) {
04504          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04505       } else {
04506          sub = c->tech_pvt;
04507          l = sub->parent;
04508 
04509          if (ast_strlen_zero(l->vmexten))  /* Exit the call if no VM pilot */
04510             break;
04511 
04512          if (l->hookstate == SKINNY_ONHOOK){
04513             l->hookstate = SKINNY_OFFHOOK;
04514             transmit_speaker_mode(d, SKINNY_SPEAKERON);
04515             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04516          }
04517 
04518          if (skinnydebug)
04519             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04520 
04521          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04522          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04523          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04524 
04525          if (!ast_ignore_pattern(c->context, vmexten)) {
04526             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04527          }
04528 
04529          if (ast_exists_extension(c, c->context, l->vmexten, 1, l->cid_num)) {
04530             ast_copy_string(c->exten, l->vmexten, sizeof(c->exten));
04531             ast_copy_string(l->lastnumberdialed, l->vmexten, sizeof(l->lastnumberdialed));
04532             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04533                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04534                ast_hangup(c);
04535             }
04536             break;
04537          }
04538       }
04539       break;
04540    case STIMULUS_CALLPARK:
04541       {
04542       int extout;
04543       char message[32];
04544 
04545       if (skinnydebug)
04546          ast_verb(1, "Received Stimulus: Park Call(%d/%d)\n", instance, callreference);
04547 
04548       if ((sub && sub->owner) && (sub->owner->_state ==  AST_STATE_UP)){
04549          c = sub->owner;
04550          if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
04551             snprintf(message, sizeof(message), "Call Parked at: %d", extout);
04552             transmit_displaynotify(d, message, 10);
04553          } else {
04554             transmit_displaynotify(d, "Call Park failed", 10);
04555          }
04556       } else {
04557          transmit_displaynotify(d, "Call Park not available", 10);
04558       }
04559       }
04560       break;
04561    case STIMULUS_DND:
04562       if (skinnydebug)
04563          ast_verb(1, "Received Stimulus: DND (%d/%d)\n", instance, callreference);
04564 
04565       /* Do not disturb */
04566       if (l->dnd != 0){
04567          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
04568          l->dnd = 0;
04569          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
04570          transmit_displaynotify(d, "DnD disabled", 10);
04571       } else {
04572          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
04573          l->dnd = 1;
04574          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
04575          transmit_displaynotify(d, "DnD enabled", 10);
04576       }
04577       break;
04578    case STIMULUS_FORWARDALL:
04579       if (skinnydebug)
04580          ast_verb(1, "Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
04581 
04582       if (!sub || !sub->owner) {
04583          c = skinny_new(l, AST_STATE_DOWN);
04584       } else {
04585          c = sub->owner;
04586       }
04587 
04588       if (!c) {
04589          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04590       } else {
04591          sub = c->tech_pvt;
04592          handle_callforward_button(sub, SKINNY_CFWD_ALL);
04593       }
04594       break;
04595    case STIMULUS_FORWARDBUSY:
04596       if (skinnydebug)
04597          ast_verb(1, "Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
04598 
04599       if (!sub || !sub->owner) {
04600          c = skinny_new(l, AST_STATE_DOWN);
04601       } else {
04602          c = sub->owner;
04603       }
04604 
04605       if (!c) {
04606          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04607       } else {
04608          sub = c->tech_pvt;
04609          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
04610       }
04611       break;
04612    case STIMULUS_FORWARDNOANSWER:
04613       if (skinnydebug)
04614          ast_verb(1, "Received Stimulus: Forward No Answer (%d/%d)\n", instance, callreference);
04615 
04616 #if 0 /* Not sure how to handle this yet */
04617       if (!sub || !sub->owner) {
04618          c = skinny_new(l, AST_STATE_DOWN);
04619       } else {
04620          c = sub->owner;
04621       }
04622 
04623       if (!c) {
04624          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04625       } else {
04626          sub = c->tech_pvt;
04627          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
04628       }
04629 #endif
04630       break;
04631    case STIMULUS_DISPLAY:
04632       /* Not sure what this is */
04633       if (skinnydebug)
04634          ast_verb(1, "Received Stimulus: Display(%d/%d)\n", instance, callreference);
04635       break;
04636    case STIMULUS_LINE:
04637       if (skinnydebug)
04638          ast_verb(1, "Received Stimulus: Line(%d/%d)\n", instance, callreference);
04639 
04640       l = find_line_by_instance(d, instance);
04641 
04642       if (!l) {
04643          return 0;
04644       }
04645 
04646       d->activeline = l;
04647 
04648       /* turn the speaker on */
04649       transmit_speaker_mode(d, SKINNY_SPEAKERON);
04650       transmit_ringer_mode(d, SKINNY_RING_OFF);
04651       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04652 
04653       l->hookstate = SKINNY_OFFHOOK;
04654 
04655       if (sub && sub->outgoing) {
04656          /* We're answering a ringing call */
04657          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
04658          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04659          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04660          transmit_callstateonly(d, sub, SKINNY_CONNECTED);
04661          transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
04662          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
04663          start_rtp(sub);
04664          ast_setstate(sub->owner, AST_STATE_UP);
04665       } else {
04666          if (sub && sub->owner) {
04667             ast_debug(1, "Current subchannel [%s] already has owner\n", sub->owner->name);
04668          } else {
04669             c = skinny_new(l, AST_STATE_DOWN);
04670             if (c) {
04671                sub = c->tech_pvt;
04672                transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04673                if (skinnydebug)
04674                   ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04675                transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04676                transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04677                transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
04678 
04679                /* start the switch thread */
04680                if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04681                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04682                   ast_hangup(c);
04683                }
04684             } else {
04685                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04686             }
04687          }
04688       }
04689       break;
04690    default:
04691       if (skinnydebug)
04692          ast_verb(1, "RECEIVED UNKNOWN STIMULUS:  %d(%d/%d)\n", event, instance, callreference);
04693       break;
04694    }
04695    ast_devstate_changed(AST_DEVICE_UNKNOWN, "Skinny/%s@%s", l->name, d->name);
04696 
04697    return 1;
04698 }

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

Definition at line 4962 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().

04963 {
04964    struct timeval now = ast_tvnow();
04965    struct ast_tm cmtime;
04966 
04967    if (!(req = req_alloc(sizeof(struct definetimedate_message), DEFINETIMEDATE_MESSAGE)))
04968       return -1;
04969 
04970    ast_localtime(&now, &cmtime, NULL);
04971    req->data.definetimedate.year = htolel(cmtime.tm_year+1900);
04972    req->data.definetimedate.month = htolel(cmtime.tm_mon+1);
04973    req->data.definetimedate.dayofweek = htolel(cmtime.tm_wday);
04974    req->data.definetimedate.day = htolel(cmtime.tm_mday);
04975    req->data.definetimedate.hour = htolel(cmtime.tm_hour);
04976    req->data.definetimedate.minute = htolel(cmtime.tm_min);
04977    req->data.definetimedate.seconds = htolel(cmtime.tm_sec);
04978    req->data.definetimedate.milliseconds = htolel(cmtime.tm_usec / 1000);
04979    req->data.definetimedate.timestamp = htolel(now.tv_sec);
04980    transmit_response(s->device, req);
04981    return 1;
04982 }

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4108 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, ast_debug, ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_DOWN, ast_verbose, skinny_subchannel::blindxfer, skinny_subchannel::callid, errno, skinny_line::instance, KEYDEF_OFFHOOKWITHFEAT, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::related, SKINNY_DIALTONE, skinny_hold(), skinny_new(), SKINNY_OFFHOOK, skinny_ss(), skinny_transfer(), skinny_line::sub, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), transmit_selectsoftkeys(), transmit_tone(), and skinny_subchannel::xferor.

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

04109 {
04110    struct skinny_line *l = sub->parent;
04111    struct skinny_device *d = l->parent;
04112    struct skinny_subchannel *newsub;
04113    struct ast_channel *c;
04114    pthread_t t;
04115 
04116    if (!sub) {
04117       ast_verbose("Transfer: No subchannel to transfer\n");
04118       return -1;
04119    }
04120    if (!sub->related) {
04121       /* Another sub has not been created so this must be first XFER press */
04122       if (!sub->onhold) {
04123          skinny_hold(sub);
04124       }
04125       c = skinny_new(l, AST_STATE_DOWN);
04126       if (c) {
04127          newsub = c->tech_pvt;
04128          /* point the sub and newsub at each other so we know they are related */
04129          newsub->related = sub;
04130          sub->related = newsub;
04131          newsub->xferor = 1;
04132          l->activesub = newsub;
04133          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, newsub->callid);
04134          if (skinnydebug)
04135             ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04136          transmit_displaymessage(d, NULL, l->instance, newsub->callid); /* clear display */
04137          transmit_tone(d, SKINNY_DIALTONE, l->instance, newsub->callid);
04138          transmit_selectsoftkeys(d, l->instance, newsub->callid, KEYDEF_OFFHOOKWITHFEAT);
04139          /* start the switch thread */
04140          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04141             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04142             ast_hangup(c);
04143          }
04144       } else {
04145          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04146       }
04147    } else {
04148       /* We already have a related sub so we can either complete XFER or go into BLINDXFER (or cancel BLINDXFER */
04149       if (sub->blindxfer) {
04150          /* toggle blindxfer off */
04151          sub->blindxfer = 0;
04152          sub->related->blindxfer = 0;
04153          /* we really need some indications */
04154       } else {
04155          /* We were doing attended transfer */
04156          if (sub->owner->_state == AST_STATE_DOWN || sub->related->owner->_state == AST_STATE_DOWN) {
04157             /* one of the subs so we cant transfer yet, toggle blindxfer on */
04158             sub->blindxfer = 1;
04159             sub->related->blindxfer = 1;
04160          } else {
04161             /* big assumption we have two channels, lets transfer */
04162             skinny_transfer(sub);
04163          }
04164       }
04165    }
04166    return 0;
04167 }

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

Definition at line 5671 of file chan_skinny.c.

References s, and skinny_unregister().

Referenced by handle_message().

05672 {
05673    return skinny_unregister(req, s);
05674 }

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

Definition at line 5132 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().

05133 {
05134    struct skinny_device *d = s->device;
05135    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
05136       return -1;
05137 
05138    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
05139    transmit_response(d, req);
05140    return 1;
05141 }

static int has_voicemail ( struct skinny_line l  )  [static]

Definition at line 2312 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_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), skinny_line::mailbox, mbox(), and strsep().

02313 {
02314    int new_msgs;
02315    struct ast_event *event;
02316    char *mbox, *context;
02317 
02318    context = mbox = ast_strdupa(l->mailbox);
02319    strsep(&context, "@");
02320    if (ast_strlen_zero(context))
02321       context = "default";
02322 
02323    event = ast_event_get_cached(AST_EVENT_MWI,
02324       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
02325       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02326       AST_EVENT_IE_END);
02327 
02328    if (event) {
02329       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02330       ast_event_destroy(event);
02331    } else
02332       new_msgs = ast_app_has_voicemail(l->mailbox, NULL);
02333 
02334    return new_msgs;
02335 }

static int load_module ( void   )  [static]

Definition at line 6392 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, sched_context_create(), skinny_rtp, skinny_tech, and soft_key_template_default.

06393 {
06394    int res = 0;
06395 
06396    for (; res < ARRAY_LEN(soft_key_template_default); res++) {
06397       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
06398    }
06399    /* load and parse config */
06400    res = reload_config();
06401    if (res == -1) {
06402       return AST_MODULE_LOAD_DECLINE;
06403    }
06404 
06405    /* Make sure we can register our skinny channel type */
06406    if (ast_channel_register(&skinny_tech)) {
06407       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
06408       return -1;
06409    }
06410 
06411    ast_rtp_proto_register(&skinny_rtp);
06412    ast_cli_register_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
06413    sched = sched_context_create();
06414    if (!sched) {
06415       ast_log(LOG_WARNING, "Unable to create schedule context\n");
06416    }
06417    io = io_context_create();
06418    if (!io) {
06419       ast_log(LOG_WARNING, "Unable to create I/O context\n");
06420    }
06421    /* And start the monitor for the first time */
06422    restart_monitor();
06423 
06424    return res;
06425 }

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

Definition at line 2304 of file chan_skinny.c.

02305 {
02306    /* This module does not handle MWI in an event-based manner.  However, it
02307     * subscribes to MWI for each mailbox that is configured so that the core
02308     * knows that we care about it.  Then, chan_skinny will get the MWI from the
02309     * event cache instead of checking the mailbox directly. */
02310 }

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 2731 of file chan_skinny.c.

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

02732 {
02733    int x, codec;
02734 
02735    for(x = 0; x < 32 ; x++) {
02736       codec = ast_codec_pref_index(pref, x);
02737       if (!codec)
02738          break;
02739       ast_cli(fd, "%s", ast_getformatname(codec));
02740       ast_cli(fd, ":%d", pref->framing[x]);
02741       if (x < 31 && ast_codec_pref_index(pref, x + 1))
02742          ast_cli(fd, ",");
02743    }
02744    if (!x)
02745       ast_cli(fd, "none");
02746 }

static void register_exten ( struct skinny_line l  )  [static]

Definition at line 1711 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(), ext, LOG_WARNING, skinny_line::name, skinny_line::regexten, S_OR, and strsep().

Referenced by skinny_register().

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

static int reload_config ( void   )  [static]

Definition at line 6173 of file chan_skinny.c.

References 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_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, 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, build_device(), cleanup_stale_contexts(), config_flags, default_jbconf, default_prefs, DEFAULT_SKINNY_BACKLOG, DEFAULT_SKINNY_PORT, errno, global_jbconf, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, skinny_device::name, ast_variable::name, netlock, ast_variable::next, qos, strsep(), and ast_variable::value.

06174 {
06175    int on = 1;
06176    struct ast_config *cfg;
06177    struct ast_variable *v;
06178    char *cat;
06179    struct skinny_device *d;
06180    int oldport = ntohs(bindaddr.sin_port);
06181    char *stringp, *context, *oldregcontext;
06182    char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT];
06183    struct ast_flags config_flags = { 0 };
06184 
06185    if (gethostname(ourhost, sizeof(ourhost))) {
06186       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled\n");
06187       return 0;
06188    }
06189    cfg = ast_config_load(config, config_flags);
06190 
06191    /* We *must* have a config file otherwise stop immediately */
06192    if (!cfg) {
06193       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled\n", config);
06194       return -1;
06195    }
06196    memset(&bindaddr, 0, sizeof(bindaddr));
06197    memset(&default_prefs, 0, sizeof(default_prefs));
06198 
06199    /* Initialize copy of current global_regcontext for later use in removing stale contexts */
06200    ast_copy_string(oldcontexts, regcontext, sizeof(oldcontexts));
06201    oldregcontext = oldcontexts;
06202 
06203    /* Copy the default jb config over global_jbconf */
06204    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
06205 
06206    /* load the general section */
06207    v = ast_variable_browse(cfg, "general");
06208    while (v) {
06209       /* handle jb conf */
06210       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
06211          v = v->next;
06212          continue;
06213       }
06214 
06215       /* Create the interface list */
06216       if (!strcasecmp(v->name, "bindaddr")) {
06217          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
06218             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
06219          } else {
06220             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
06221          }
06222       } else if (!strcasecmp(v->name, "keepalive")) {
06223          keep_alive = atoi(v->value);
06224       } else if (!strcasecmp(v->name, "vmexten")) {
06225          ast_copy_string(vmexten, v->value, sizeof(vmexten));
06226       } else if (!strcasecmp(v->name, "regcontext")) {
06227          ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
06228          stringp = newcontexts;
06229          /* Let's remove any contexts that are no longer defined in regcontext */
06230          cleanup_stale_contexts(stringp, oldregcontext);
06231          /* Create contexts if they don't exist already */
06232          while ((context = strsep(&stringp, "&"))) {
06233             ast_copy_string(used_context, context, sizeof(used_context));
06234             ast_context_find_or_create(NULL, NULL, context, "Skinny");
06235          }
06236          ast_copy_string(regcontext, v->value, sizeof(regcontext));
06237       } else if (!strcasecmp(v->name, "dateformat")) {
06238          memcpy(date_format, v->value, sizeof(date_format));
06239       } else if (!strcasecmp(v->name, "tos")) {
06240          if (ast_str2tos(v->value, &qos.tos))
06241             ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
06242       } else if (!strcasecmp(v->name, "tos_audio")) {
06243          if (ast_str2tos(v->value, &qos.tos_audio))
06244             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06245       } else if (!strcasecmp(v->name, "tos_video")) {
06246          if (ast_str2tos(v->value, &qos.tos_video))
06247             ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno);
06248       } else if (!strcasecmp(v->name, "cos")) {
06249          if (ast_str2cos(v->value, &qos.cos))
06250             ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
06251       } else if (!strcasecmp(v->name, "cos_audio")) {
06252          if (ast_str2cos(v->value, &qos.cos_audio))
06253             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06254       } else if (!strcasecmp(v->name, "cos_video")) {
06255          if (ast_str2cos(v->value, &qos.cos_video))
06256             ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
06257       } else if (!strcasecmp(v->name, "allow")) {
06258          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
06259       } else if (!strcasecmp(v->name, "disallow")) {
06260          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
06261       } else if (!strcasecmp(v->name, "bindport")) {
06262          if (sscanf(v->value, "%5d", &ourport) == 1) {
06263             bindaddr.sin_port = htons(ourport);
06264          } else {
06265             ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
06266          }
06267       }
06268       v = v->next;
06269    }
06270 
06271    if (ntohl(bindaddr.sin_addr.s_addr)) {
06272       __ourip = bindaddr.sin_addr;
06273    } else {
06274       hp = ast_gethostbyname(ourhost, &ahp);
06275       if (!hp) {
06276          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
06277          ast_config_destroy(cfg);
06278          return 0;
06279       }
06280       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
06281    }
06282    if (!ntohs(bindaddr.sin_port)) {
06283       bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
06284    }
06285    bindaddr.sin_family = AF_INET;
06286 
06287    /* load the device sections */
06288    cat = ast_category_browse(cfg, NULL);
06289    while(cat) {
06290       if (!strcasecmp(cat, "general")) {
06291          /* Nothing to do */
06292       } else {
06293          d = build_device(cat, ast_variable_browse(cfg, cat));
06294          if (d) {
06295             ast_verb(3, "Added device '%s'\n", d->name);
06296             AST_LIST_LOCK(&devices);
06297             AST_LIST_INSERT_HEAD(&devices, d, list);
06298             AST_LIST_UNLOCK(&devices);
06299          }
06300       }
06301       cat = ast_category_browse(cfg, cat);
06302    }
06303    ast_mutex_lock(&netlock);
06304    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
06305       close(skinnysock);
06306       skinnysock = -1;
06307    }
06308    if (skinnysock < 0) {
06309       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
06310       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
06311          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
06312          ast_config_destroy(cfg);
06313          ast_mutex_unlock(&netlock);
06314          return 0;
06315       }
06316       if (skinnysock < 0) {
06317          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
06318       } else {
06319          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
06320             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
06321                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
06322                      strerror(errno));
06323             close(skinnysock);
06324             skinnysock = -1;
06325             ast_config_destroy(cfg);
06326             ast_mutex_unlock(&netlock);
06327             return 0;
06328          }
06329          if (listen(skinnysock, DEFAULT_SKINNY_BACKLOG)) {
06330                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
06331                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
06332                      strerror(errno));
06333                close(skinnysock);
06334                skinnysock = -1;
06335                ast_config_destroy(cfg);
06336                ast_mutex_unlock(&netlock);
06337                return 0;
06338          }
06339          ast_verb(2, "Skinny listening on %s:%d\n",
06340                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
06341          ast_netsock_set_qos(skinnysock, qos.tos, qos.cos, "Skinny");
06342          ast_pthread_create_background(&accept_t, NULL, accept_thread, NULL);
06343       }
06344    }
06345    ast_mutex_unlock(&netlock);
06346    ast_config_destroy(cfg);
06347    return 1;
06348 }

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

Definition at line 1442 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_set_rtp_peer(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_callstateonly(), transmit_cfwdstate(), transmit_closereceivechannel(), transmit_connect(), transmit_dialednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stopmediatransmission(), and transmit_tone().

01443 {
01444    struct skinny_req *req;
01445 
01446    if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
01447       return NULL;
01448 
01449    req->len = htolel(size+4);
01450    req->e = htolel(response_message);
01451 
01452    return req;
01453 }

static int restart_monitor ( void   )  [static]

Definition at line 6099 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, and monlock.

06100 {
06101    /* If we're supposed to be stopped -- stay stopped */
06102    if (monitor_thread == AST_PTHREADT_STOP)
06103       return 0;
06104 
06105    ast_mutex_lock(&monlock);
06106    if (monitor_thread == pthread_self()) {
06107       ast_mutex_unlock(&monlock);
06108       ast_log(LOG_WARNING, "Cannot kill myself\n");
06109       return -1;
06110    }
06111    if (monitor_thread != AST_PTHREADT_NULL) {
06112       /* Wake up the thread */
06113       pthread_kill(monitor_thread, SIGURG);
06114    } else {
06115       /* Start a new monitor */
06116       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
06117          ast_mutex_unlock(&monlock);
06118          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06119          return -1;
06120       }
06121    }
06122    ast_mutex_unlock(&monlock);
06123    return 0;
06124 }

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

Definition at line 1653 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().

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

static int skinny_answer ( struct ast_channel ast  )  [static]

Definition at line 3535 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, ast_debug, ast_setstate(), AST_STATE_UP, ast_verb, skinny_subchannel::blindxfer, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, skinny_subchannel::cxmode, skinny_line::instance, KEYDEF_CONNECTED, skinny_line::lastnumberdialed, skinny_device::name, skinny_line::name, ast_channel::name, skinny_line::parent, skinny_subchannel::rtp, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, SKINNY_SILENCE, skinny_transfer(), start_rtp(), skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_selectsoftkeys(), and transmit_tone().

03536 {
03537    int res = 0;
03538    struct skinny_subchannel *sub = ast->tech_pvt;
03539    struct skinny_line *l = sub->parent;
03540    struct skinny_device *d = l->parent;
03541 
03542    if (sub->blindxfer) {
03543       if (skinnydebug)
03544          ast_debug(1, "skinny_answer(%s) on %s@%s-%d with BlindXFER, transferring\n",
03545             ast->name, l->name, d->name, sub->callid);
03546       ast_setstate(ast, AST_STATE_UP);
03547       skinny_transfer(sub);
03548       return 0;
03549    }
03550 
03551    sub->cxmode = SKINNY_CX_SENDRECV;
03552    if (!sub->rtp) {
03553       start_rtp(sub);
03554    }
03555    if (skinnydebug)
03556       ast_verb(1, "skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, d->name, sub->callid);
03557    if (ast->_state != AST_STATE_UP) {
03558       ast_setstate(ast, AST_STATE_UP);
03559    }
03560 
03561    transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03562    /* order matters here...
03563       for some reason, transmit_callinfo must be before transmit_callstate,
03564       or you won't get keypad messages in some situations. */
03565    transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
03566    transmit_callstateonly(d, sub, SKINNY_CONNECTED);
03567    transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
03568    transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
03569    transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
03570    l->activesub = sub;
03571    return res;
03572 }

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

Definition at line 3405 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_device::registered, SKINNY_ALERT, SKINNY_CALLWAITTONE, SKINNY_LAMP_BLINK, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_INSIDE, SKINNY_RINGIN, STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), and transmit_selectsoftkeys().

03406 {
03407    int res = 0;
03408    int tone = 0;
03409    struct skinny_subchannel *sub = ast->tech_pvt;
03410    struct skinny_line *l = sub->parent;
03411    struct skinny_device *d = l->parent;
03412 
03413    if (!d->registered) {
03414       ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
03415       return -1;
03416    }
03417 
03418    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03419       ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast->name);
03420       return -1;
03421    }
03422 
03423    if (skinnydebug)
03424       ast_verb(3, "skinny_call(%s)\n", ast->name);
03425 
03426    if (l->dnd) {
03427       ast_queue_control(ast, AST_CONTROL_BUSY);
03428       return -1;
03429    }
03430 
03431    switch (l->hookstate) {
03432    case SKINNY_OFFHOOK:
03433       tone = SKINNY_CALLWAITTONE;
03434       break;
03435    case SKINNY_ONHOOK:
03436       tone = SKINNY_ALERT;
03437       break;
03438    default:
03439       ast_log(LOG_ERROR, "Don't know how to deal with hookstate %d\n", l->hookstate);
03440       break;
03441    }
03442 
03443    transmit_callstateonly(d, sub, SKINNY_RINGIN);
03444    transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
03445    transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
03446    transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
03447    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03448    transmit_ringer_mode(d, SKINNY_RING_INSIDE);
03449 
03450    ast_setstate(ast, AST_STATE_RINGING);
03451    ast_queue_control(ast, AST_CONTROL_RINGING);
03452    sub->outgoing = 1;
03453    return res;
03454 }

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6126 of file chan_skinny.c.

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

06127 {
06128    struct skinny_line *l;
06129    char *tmp;
06130 
06131    tmp = ast_strdupa(data);
06132 
06133    l = find_line_by_name(tmp);
06134 
06135    return get_devicestate(l);
06136 }

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

Definition at line 2252 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, 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().

Referenced by skinny_register().

02253 {
02254    struct skinny_speeddial *sd = data;
02255    struct skinny_device *d = sd->parent;
02256    char hint[AST_MAX_EXTENSION];
02257    int callstate = SKINNY_CALLREMOTEMULTILINE;
02258    int lamp = SKINNY_LAMP_OFF;
02259 
02260    switch (state) {
02261    case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
02262    case AST_EXTENSION_REMOVED:     /* Extension is gone */
02263       ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
02264       sd->stateid = -1;
02265       callstate = SKINNY_ONHOOK;
02266       lamp = SKINNY_LAMP_OFF;
02267       break;
02268    case AST_EXTENSION_RINGING:
02269    case AST_EXTENSION_UNAVAILABLE:
02270       callstate = SKINNY_RINGIN;
02271       lamp = SKINNY_LAMP_BLINK;
02272       break;
02273    case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
02274    case AST_EXTENSION_INUSE:
02275       callstate = SKINNY_CALLREMOTEMULTILINE;
02276       lamp = SKINNY_LAMP_ON;
02277       break;
02278    case AST_EXTENSION_ONHOLD:
02279       callstate = SKINNY_HOLD;
02280       lamp = SKINNY_LAMP_WINK;
02281       break;
02282    case AST_EXTENSION_NOT_INUSE:
02283    default:
02284       callstate = SKINNY_ONHOOK;
02285       lamp = SKINNY_LAMP_OFF;
02286       break;
02287    }
02288 
02289    if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
02290       /* If they are not registered, we will override notification and show no availability */
02291       if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
02292          callstate = SKINNY_ONHOOK;
02293          lamp = SKINNY_LAMP_FLASH;
02294       }
02295    }
02296 
02297    transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, lamp);
02298    transmit_callstate(d, sd->instance, callstate, 0);
02299    sd->laststate = state;
02300 
02301    return 0;
02302 }

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

Definition at line 3660 of file chan_skinny.c.

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

03661 {
03662    struct skinny_subchannel *sub = newchan->tech_pvt;
03663    ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
03664    if (sub->owner != oldchan) {
03665       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
03666       return -1;
03667    }
03668    sub->owner = newchan;
03669    return 0;
03670 }

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

Definition at line 2381 of file chan_skinny.c.

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

02382 {
02383    struct skinny_subchannel *sub = NULL;
02384    struct skinny_line *l;
02385    enum ast_rtp_get_result res = AST_RTP_TRY_NATIVE;
02386 
02387    if (skinnydebug)
02388       ast_verb(1, "skinny_get_rtp_peer() Channel = %s\n", c->name);
02389 
02390 
02391    if (!(sub = c->tech_pvt))
02392       return AST_RTP_GET_FAILED;
02393 
02394    ast_mutex_lock(&sub->lock);
02395 
02396    if (!(sub->rtp)){
02397       ast_mutex_unlock(&sub->lock);
02398       return AST_RTP_GET_FAILED;
02399    }
02400    
02401    *rtp = sub->rtp;
02402 
02403    l = sub->parent;
02404 
02405    if (!l->canreinvite || l->nat){
02406       res = AST_RTP_TRY_PARTIAL;
02407       if (skinnydebug)
02408          ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_TRY_PARTIAL \n");
02409    }
02410 
02411    ast_mutex_unlock(&sub->lock);
02412 
02413    return res;
02414 
02415 }

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

Definition at line 2369 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.

02370 {
02371    struct skinny_subchannel *sub = NULL;
02372 
02373    if (!(sub = c->tech_pvt) || !(sub->vrtp))
02374       return AST_RTP_GET_FAILED;
02375 
02376    *rtp = sub->vrtp;
02377 
02378    return AST_RTP_TRY_NATIVE;
02379 }

static int skinny_hangup ( struct ast_channel ast  )  [static]

Definition at line 3456 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, skinny_subchannel::alreadygone, ast_debug, ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_NEXT, AST_LIST_REMOVE, ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), skinny_subchannel::callid, skinny_line::hookstate, skinny_line::instance, skinny_subchannel::lock, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_device::registered, skinny_subchannel::related, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_closereceivechannel(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), transmit_stopmediatransmission(), and transmit_tone().

03457 {
03458    struct skinny_subchannel *sub = ast->tech_pvt;
03459    struct skinny_line *l;
03460    struct skinny_device *d;
03461    struct skinnysession *s;
03462 
03463    if (!sub) {
03464       ast_debug(1, "Asked to hangup channel not connected\n");
03465       return 0;
03466    }
03467    l = sub->parent;
03468    d = l->parent;
03469    s = d->session;
03470 
03471    AST_LIST_REMOVE(&l->sub, sub, list);
03472 
03473    if (d->registered) {
03474       /* Ignoring l->type, doesn't seem relevant and previous code 
03475          assigned rather than tested, ie always true */
03476       if (!AST_LIST_EMPTY(&l->sub)) {
03477          if (sub->related) {
03478             sub->related->related = NULL;
03479 
03480          }
03481          if (sub == l->activesub) {      /* we are killing the active sub, but there are other subs on the line*/
03482             if (sub->related) {
03483                l->activesub = sub->related;
03484             } else {
03485                if (AST_LIST_NEXT(sub, list)) {
03486                   l->activesub = AST_LIST_NEXT(sub, list);
03487                } else {
03488                   l->activesub = AST_LIST_FIRST(&l->sub);
03489                }
03490             }
03491             transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
03492             transmit_activatecallplane(d, l);
03493             transmit_closereceivechannel(d, sub);
03494             transmit_stopmediatransmission(d, sub);
03495             transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03496             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03497          } else {    /* we are killing a background sub on the line with other subs*/
03498             if (AST_LIST_NEXT(sub, list)) {
03499                transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03500             } else {
03501                transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
03502             }
03503          }
03504       } else {                                                /* no more subs on line so make idle */
03505 
03506          l->hookstate = SKINNY_ONHOOK;
03507          transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
03508          l->activesub = NULL;
03509          transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
03510          if (sub->parent == d->activeline) {
03511             transmit_activatecallplane(d, l);
03512             transmit_closereceivechannel(d, sub);
03513             transmit_stopmediatransmission(d, sub);
03514             transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
03515             transmit_ringer_mode(d, SKINNY_RING_OFF);
03516             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03517             /* we should check to see if we can start the ringer if another line is ringing */
03518          }
03519       }
03520    }
03521    ast_mutex_lock(&sub->lock);
03522    sub->owner = NULL;
03523    ast->tech_pvt = NULL;
03524    sub->alreadygone = 0;
03525    sub->outgoing = 0;
03526    if (sub->rtp) {
03527       ast_rtp_destroy(sub->rtp);
03528       sub->rtp = NULL;
03529    }
03530    ast_mutex_unlock(&sub->lock);
03531    ast_free(sub);
03532    return 0;
03533 }

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

Definition at line 4036 of file chan_skinny.c.

References AST_CONTROL_HOLD, ast_queue_control_data(), ast_strlen_zero(), ast_verb, skinny_line::instance, skinny_line::mohsuggest, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_line::parent, S_OR, SKINNY_HOLD, SKINNY_LAMP_WINK, STIMULUS_LINE, skinny_line::sub, transmit_activatecallplane(), transmit_callstateonly(), transmit_closereceivechannel(), transmit_lamp_indication(), and transmit_stopmediatransmission().

Referenced by handle_hold_button(), handle_soft_key_event_message(), and handle_transfer_button().

04037 {
04038    struct skinny_line *l = sub->parent;
04039    struct skinny_device *d = l->parent;
04040 
04041    /* Don't try to hold a channel that doesn't exist */
04042    if (!sub || !sub->owner)
04043       return 0;
04044 
04045    /* Channel needs to be put on hold */
04046    if (skinnydebug)
04047       ast_verb(1, "Putting on Hold(%d)\n", l->instance);
04048 
04049    ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
04050       S_OR(l->mohsuggest, NULL),
04051       !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
04052 
04053    transmit_activatecallplane(d, l);
04054    transmit_closereceivechannel(d, sub);
04055    transmit_stopmediatransmission(d, sub);
04056 
04057    transmit_callstateonly(d, sub, SKINNY_HOLD);
04058    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
04059    sub->onhold = 1;
04060    return 1;
04061 }

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

Definition at line 3831 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_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_rtp_change_source(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, ast_verb, skinny_subchannel::blindxfer, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, control2str(), skinny_device::earlyrtp, skinny_line::instance, skinny_line::lastnumberdialed, LOG_NOTICE, LOG_WARNING, skinny_line::mohinterpret, ast_channel::name, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::progress, skinny_subchannel::ringing, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CONGESTION, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RINGOUT, SKINNY_SILENCE, skinny_transfer(), skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_dialednumber(), transmit_displaypromptstatus(), and transmit_tone().

03832 {
03833    struct skinny_subchannel *sub = ast->tech_pvt;
03834    struct skinny_line *l = sub->parent;
03835    struct skinny_device *d = l->parent;
03836    struct skinnysession *s = d->session;
03837 
03838    if (!s) {
03839       ast_log(LOG_NOTICE, "Asked to indicate '%s' condition on channel %s, but session does not exist.\n", control2str(ind), ast->name);
03840       return -1;
03841    }
03842 
03843    if (skinnydebug)
03844       ast_verb(3, "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
03845    switch(ind) {
03846    case AST_CONTROL_RINGING:
03847       if (sub->blindxfer) {
03848          if (skinnydebug)
03849             ast_debug(1, "Channel %s set up for Blind Xfer, so Xfer rather than ring device\n", ast->name);
03850          skinny_transfer(sub);
03851          break;
03852       }
03853       if (ast->_state != AST_STATE_UP) {
03854          if (!sub->progress) {
03855             if (!d->earlyrtp) {
03856                transmit_tone(d, SKINNY_ALERT, l->instance, sub->callid);
03857             }
03858             transmit_callstateonly(d, sub, SKINNY_RINGOUT);
03859             transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
03860             transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
03861             transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
03862             sub->ringing = 1;
03863             if (!d->earlyrtp) {
03864                break;
03865             }
03866          }
03867       }
03868       return -1; /* Tell asterisk to provide inband signalling */
03869    case AST_CONTROL_BUSY:
03870       if (ast->_state != AST_STATE_UP) {
03871          if (!d->earlyrtp) {
03872             transmit_tone(d, SKINNY_BUSYTONE, l->instance, sub->callid);
03873          }
03874          transmit_callstateonly(d, sub, SKINNY_BUSY);
03875          sub->alreadygone = 1;
03876          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
03877          if (!d->earlyrtp) {
03878             break;
03879          }
03880       }
03881       return -1; /* Tell asterisk to provide inband signalling */
03882    case AST_CONTROL_CONGESTION:
03883       if (ast->_state != AST_STATE_UP) {
03884          if (!d->earlyrtp) {
03885             transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03886          }
03887          transmit_callstateonly(d, sub, SKINNY_CONGESTION);
03888          sub->alreadygone = 1;
03889          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
03890          if (!d->earlyrtp) {
03891             break;
03892          }
03893       }
03894       return -1; /* Tell asterisk to provide inband signalling */
03895    case AST_CONTROL_PROGRESS:
03896       if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
03897          if (!d->earlyrtp) {
03898             transmit_tone(d, SKINNY_ALERT, l->instance, sub->callid);
03899          }
03900          transmit_callstateonly(d, sub, SKINNY_PROGRESS);
03901          transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
03902          transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
03903          sub->progress = 1;
03904          if (!d->earlyrtp) {
03905             break;
03906          }
03907       }
03908       return -1; /* Tell asterisk to provide inband signalling */
03909    case -1:  /* STOP_TONE */
03910       transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03911       break;
03912    case AST_CONTROL_HOLD:
03913       ast_moh_start(ast, data, l->mohinterpret);
03914       break;
03915    case AST_CONTROL_UNHOLD:
03916       ast_moh_stop(ast);
03917       break;
03918    case AST_CONTROL_PROCEEDING:
03919       break;
03920    case AST_CONTROL_SRCUPDATE:
03921       ast_rtp_new_source(sub->rtp);
03922       break;
03923    case AST_CONTROL_SRCCHANGE:
03924       ast_rtp_change_source(sub->rtp);
03925       break;
03926    default:
03927       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
03928       return -1; /* Tell asterisk to provide inband signalling */
03929    }
03930    return 0;
03931 }

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

Definition at line 3933 of file chan_skinny.c.

References skinny_line::accountcode, skinny_line::activesub, 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_DEVICE_NOT_INUSE, ast_hangup(), ast_jb_configure(), AST_LIST_INSERT_HEAD, 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(), ast_verb, skinny_line::call_forward_all, skinny_line::callgroup, ast_channel::callgroup, 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, ast_channel::exten, skinny_line::exten, get_devicestate(), global_jbconf, skinny_line::instance, 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::parent, skinny_line::parkinglot, 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, 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(), handle_transfer_button(), and skinny_request().

03934 {
03935    struct ast_channel *tmp;
03936    struct skinny_subchannel *sub;
03937    struct skinny_device *d = l->parent;
03938    struct ast_variable *v = NULL;
03939    int fmt;
03940 
03941    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);
03942    if (!tmp) {
03943       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
03944       return NULL;
03945    } else {
03946       sub = ast_calloc(1, sizeof(*sub));
03947       if (!sub) {
03948          ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
03949          return NULL;
03950       } else {
03951          ast_mutex_init(&sub->lock);
03952 
03953          sub->owner = tmp;
03954          sub->callid = callnums++;
03955          d->lastlineinstance = l->instance;
03956          d->lastcallreference = sub->callid;
03957          sub->cxmode = SKINNY_CX_INACTIVE;
03958          sub->nat = l->nat;
03959          sub->parent = l;
03960          sub->onhold = 0;
03961          sub->blindxfer = 0;
03962          sub->xferor = 0;
03963          sub->related = NULL;
03964 
03965          AST_LIST_INSERT_HEAD(&l->sub, sub, list);
03966          l->activesub = sub;
03967       }
03968       tmp->tech = &skinny_tech;
03969       tmp->tech_pvt = sub;
03970       tmp->nativeformats = l->capability;
03971       if (!tmp->nativeformats)
03972          tmp->nativeformats = default_capability;
03973       fmt = ast_best_codec(tmp->nativeformats);
03974       if (skinnydebug)
03975          ast_verb(1, "skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
03976       if (sub->rtp) {
03977          ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
03978       }
03979       if (state == AST_STATE_RING) {
03980          tmp->rings = 1;
03981       }
03982       tmp->writeformat = fmt;
03983       tmp->rawwriteformat = fmt;
03984       tmp->readformat = fmt;
03985       tmp->rawreadformat = fmt;
03986       if (!ast_strlen_zero(l->language))
03987          ast_string_field_set(tmp, language, l->language);
03988       if (!ast_strlen_zero(l->accountcode))
03989          ast_string_field_set(tmp, accountcode, l->accountcode);
03990       if (!ast_strlen_zero(l->parkinglot))
03991          ast_string_field_set(tmp, parkinglot, l->parkinglot);
03992       if (l->amaflags)
03993          tmp->amaflags = l->amaflags;
03994 
03995       ast_module_ref(ast_module_info->self);
03996       tmp->callgroup = l->callgroup;
03997       tmp->pickupgroup = l->pickupgroup;
03998 
03999       /* XXX Need to figure out how to handle CFwdNoAnswer */
04000       if (l->cfwdtype & SKINNY_CFWD_ALL) {
04001          ast_string_field_set(tmp, call_forward, l->call_forward_all);
04002       } else if (l->cfwdtype & SKINNY_CFWD_BUSY) {
04003          if (get_devicestate(l) != AST_DEVICE_NOT_INUSE) {
04004             ast_string_field_set(tmp, call_forward, l->call_forward_busy);
04005          }
04006       }
04007 
04008       ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
04009       ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
04010 
04011       /* Don't use ast_set_callerid() here because it will
04012        * generate a needless NewCallerID event */
04013       tmp->cid.cid_ani = ast_strdup(l->cid_num);
04014 
04015       tmp->priority = 1;
04016       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
04017 
04018       if (sub->rtp)
04019          ast_jb_configure(tmp, &global_jbconf);
04020 
04021       /* Set channel variables for this call from configuration */
04022       for (v = l->chanvars ; v ; v = v->next)
04023          pbx_builtin_setvar_helper(tmp, v->name, v->value);
04024 
04025       if (state != AST_STATE_DOWN) {
04026          if (ast_pbx_start(tmp)) {
04027             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
04028             ast_hangup(tmp);
04029             tmp = NULL;
04030          }
04031       }
04032    }
04033    return tmp;
04034 }

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

Definition at line 3276 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::rtp, 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().

03277 {
03278    struct ast_channel *c = data;
03279    struct skinny_subchannel *sub = c->tech_pvt;
03280    struct skinny_line *l = sub->parent;
03281    struct skinny_device *d = l->parent;
03282    int res = 0;
03283 
03284    ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed));
03285    ast_set_callerid(c,
03286       l->hidecallerid ? "" : l->cid_num,
03287       l->hidecallerid ? "" : l->cid_name,
03288       c->cid.cid_ani ? NULL : l->cid_num);
03289    ast_setstate(c, AST_STATE_RING);
03290    if (!sub->rtp) {
03291       start_rtp(sub);
03292    }
03293    res = ast_pbx_run(c);
03294    if (res) {
03295       ast_log(LOG_WARNING, "PBX exited non-zero\n");
03296       transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03297    }
03298    return NULL;
03299 }

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

Definition at line 3622 of file chan_skinny.c.

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

03623 {
03624    struct ast_frame *fr;
03625    struct skinny_subchannel *sub = ast->tech_pvt;
03626    ast_mutex_lock(&sub->lock);
03627    fr = skinny_rtp_read(sub);
03628    ast_mutex_unlock(&sub->lock);
03629    return fr;
03630 }

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

Definition at line 1760 of file chan_skinny.c.

References ast_apply_ha(), ast_copy_string(), AST_DEVICE_NOT_INUSE, ast_devstate_changed(), ast_extension_state_add(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), skinny_speeddial::context, skinny_req::data, skinny_speeddial::exten, skinny_device::ha, skinny_device::id, letohl, skinny_device::lines, LOG_WARNING, skinny_device::name, skinny_line::name, register_message::name, skinny_device::ourip, skinny_data::reg, register_exten(), skinny_device::registered, s, skinny_device::session, skinny_extensionstate_cb(), skinny_device::speeddials, skinny_speeddial::stateid, register_message::type, skinny_device::type, and skinny_device::version_id.

Referenced by handle_register_message().

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

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

Definition at line 5970 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, and SKINNY_MAX_PACKET.

Referenced by skinny_session().

05971 {
05972    struct skinny_req *req;
05973    int *bufaddr;
05974 
05975    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
05976       return NULL;
05977 
05978    ast_mutex_lock(&s->lock);
05979    memcpy(req, s->inbuf, skinny_header_size);
05980    bufaddr = (int *)(s->inbuf);
05981    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
05982 
05983    ast_mutex_unlock(&s->lock);
05984 
05985    if (letohl(req->e) < 0) {
05986       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
05987       ast_free(req);
05988       return NULL;
05989    }
05990 
05991    return req;
05992 }

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

Definition at line 6138 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().

06139 {
06140    int oldformat;
06141    
06142    struct skinny_line *l;
06143    struct ast_channel *tmpc = NULL;
06144    char tmp[256];
06145    char *dest = data;
06146 
06147    oldformat = format;
06148    
06149    if (!(format &= AST_FORMAT_AUDIO_MASK)) {
06150       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
06151       return NULL;
06152    }
06153 
06154    ast_copy_string(tmp, dest, sizeof(tmp));
06155    if (ast_strlen_zero(tmp)) {
06156       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
06157       return NULL;
06158    }
06159    l = find_line_by_name(tmp);
06160    if (!l) {
06161       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
06162       return NULL;
06163    }
06164    ast_verb(3, "skinny_request(%s)\n", tmp);
06165    tmpc = skinny_new(l, AST_STATE_DOWN);
06166    if (!tmpc) {
06167       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
06168    }
06169    restart_monitor();
06170    return tmpc;
06171 }

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

Definition at line 3575 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().

03576 {
03577    struct ast_channel *ast = sub->owner;
03578    struct ast_frame *f;
03579 
03580    if (!sub->rtp) {
03581       /* We have no RTP allocated for this channel */
03582       return &ast_null_frame;
03583    }
03584 
03585    switch(ast->fdno) {
03586    case 0:
03587       f = ast_rtp_read(sub->rtp); /* RTP Audio */
03588       break;
03589    case 1:
03590       f = ast_rtcp_read(sub->rtp); /* RTCP Control Channel */
03591       break;
03592    case 2:
03593       f = ast_rtp_read(sub->vrtp); /* RTP Video */
03594       break;
03595    case 3:
03596       f = ast_rtcp_read(sub->vrtp); /* RTCP Control Channel for video */
03597       break;
03598 #if 0
03599    case 5:
03600       /* Not yet supported */
03601       f = ast_udptl_read(sub->udptl); /* UDPTL for T.38 */
03602       break;
03603 #endif
03604    default:
03605       f = &ast_null_frame;
03606    }
03607 
03608    if (ast) {
03609       /* We already hold the channel lock */
03610       if (f->frametype == AST_FRAME_VOICE) {
03611          if (f->subclass != ast->nativeformats) {
03612             ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
03613             ast->nativeformats = f->subclass;
03614             ast_set_read_format(ast, ast->readformat);
03615             ast_set_write_format(ast, ast->writeformat);
03616          }
03617       }
03618    }
03619    return f;
03620 }

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

Definition at line 3672 of file chan_skinny.c.

03673 {
03674    return -1; /* Start inband indications */
03675 }

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

Definition at line 3677 of file chan_skinny.c.

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

03678 {
03679 #if 0
03680    struct skinny_subchannel *sub = ast->tech_pvt;
03681    struct skinny_line *l = sub->parent;
03682    struct skinny_device *d = l->parent;
03683    int tmp;
03684    /* not right */
03685    sprintf(tmp, "%d", digit);
03686    transmit_tone(d, digit, l->instance, sub->callid);
03687 #endif
03688    return -1; /* Stop inband indications */
03689 }

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

Definition at line 5994 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().

05995 {
05996    int res;
05997    struct skinny_req *req;
05998    struct skinnysession *s = data;
05999 
06000    ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
06001 
06002    for (;;) {
06003       res = get_input(s);
06004       if (res < 0) {
06005          break;
06006       }
06007 
06008       if (res > 0)
06009       {
06010          if (!(req = skinny_req_parse(s))) {
06011             destroy_session(s);
06012             return NULL;
06013          }
06014 
06015          res = handle_message(req, s);
06016          if (res < 0) {
06017             destroy_session(s);
06018             return NULL;
06019          }
06020       }
06021    }
06022    ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));
06023 
06024    if (s) 
06025       destroy_session(s);
06026    
06027    return 0;
06028 }

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 2417 of file chan_skinny.c.

References ast_channel::_state, ast_best_codec(), ast_codec_pref_getsize(), ast_inet_ntoa(), ast_rtp_get_peer(), ast_rtp_get_us(), AST_STATE_UP, ast_verb, 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(), skinny_subchannel::rtp, s, skinny_device::session, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, ast_channel::tech_pvt, transmit_response(), and media_qualifier::vad.

02418 {
02419    struct skinny_subchannel *sub;
02420    struct skinny_line *l;
02421    struct skinny_device *d;
02422    struct skinnysession *s;
02423    struct ast_format_list fmt;
02424    struct sockaddr_in us;
02425    struct sockaddr_in them;
02426    struct skinny_req *req;
02427    
02428    sub = c->tech_pvt;
02429 
02430    if (c->_state != AST_STATE_UP)
02431       return 0;
02432 
02433    if (!sub) {
02434       return -1;
02435    }
02436 
02437    l = sub->parent;
02438    d = l->parent;
02439    s = d->session;
02440 
02441    if (rtp){
02442       ast_rtp_get_peer(rtp, &them);
02443 
02444       /* Shutdown any early-media or previous media on re-invite */
02445       if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02446          return -1;
02447 
02448       req->data.stopmedia.conferenceId = htolel(sub->callid);
02449       req->data.stopmedia.passThruPartyId = htolel(sub->callid);
02450       transmit_response(d, req);
02451 
02452       if (skinnydebug)
02453          ast_verb(1, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port));
02454 
02455       if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
02456          return -1;
02457 
02458       fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
02459 
02460       if (skinnydebug)
02461          ast_verb(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
02462 
02463       req->data.startmedia.conferenceId = htolel(sub->callid);
02464       req->data.startmedia.passThruPartyId = htolel(sub->callid);
02465       if (!(l->canreinvite) || (l->nat)){
02466          ast_rtp_get_us(rtp, &us);
02467          req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
02468          req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
02469       } else {
02470          req->data.startmedia.remoteIp = htolel(them.sin_addr.s_addr);
02471          req->data.startmedia.remotePort = htolel(ntohs(them.sin_port));
02472       }
02473       req->data.startmedia.packetSize = htolel(fmt.cur_ms);
02474       req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
02475       req->data.startmedia.qualifier.precedence = htolel(127);
02476       req->data.startmedia.qualifier.vad = htolel(0);
02477       req->data.startmedia.qualifier.packets = htolel(0);
02478       req->data.startmedia.qualifier.bitRate = htolel(0);
02479       transmit_response(d, req);
02480 
02481       return 0;
02482    }
02483    /* Need a return here to break the bridge */
02484    return 0;
02485 }

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

Definition at line 3301 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, skinny_line::getforward, skinny_line::hookstate, skinny_line::instance, skinny_line::lastnumberdialed, len(), LOG_WARNING, ast_channel::name, skinny_device::name, skinny_line::name, skinny_subchannel::owner, skinny_line::parent, set_callforwards(), SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_newcall(), SKINNY_OFFHOOK, 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(), handle_stimulus_message(), and handle_transfer_button().

03302 {
03303    struct ast_channel *c = data;
03304    struct skinny_subchannel *sub = c->tech_pvt;
03305    struct skinny_line *l = sub->parent;
03306    struct skinny_device *d = l->parent;
03307    int len = 0;
03308    int timeout = firstdigittimeout;
03309    int res = 0;
03310    int loop_pause = 100;
03311 
03312    ast_verb(3, "Starting simple switch on '%s@%s'\n", l->name, d->name);
03313 
03314    len = strlen(d->exten);
03315 
03316    while (len < AST_MAX_EXTENSION-1) {
03317       res = 1;  /* Assume that we will get a digit */
03318       while (strlen(d->exten) == len){
03319          ast_safe_sleep(c, loop_pause);
03320          timeout -= loop_pause;
03321          if ( (timeout -= loop_pause) <= 0){
03322              res = 0;
03323              break;
03324          }
03325       res = 1;
03326       }
03327 
03328       timeout = 0;
03329       len = strlen(d->exten);
03330 
03331       if (!ast_ignore_pattern(c->context, d->exten)) {
03332          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03333       }
03334       if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) {
03335          if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) {
03336             if (l->getforward) {
03337                /* Record this as the forwarding extension */
03338                set_callforwards(l, d->exten, l->getforward);
03339                ast_verb(3, "Setting call forward (%d) to '%s' on channel %s\n",
03340                      l->cfwdtype, d->exten, c->name);
03341                transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
03342                transmit_lamp_indication(d, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
03343                transmit_displaynotify(d, "CFwd enabled", 10);
03344                transmit_cfwdstate(d, l);
03345                ast_safe_sleep(c, 500);
03346                ast_indicate(c, -1);
03347                ast_safe_sleep(c, 1000);
03348                memset(d->exten, 0, sizeof(d->exten));
03349                len = 0;
03350                l->getforward = 0;
03351                if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03352                   ast_indicate(c, -1);
03353                   ast_hangup(c);
03354                }
03355                return NULL;
03356             } else {
03357                ast_copy_string(c->exten, d->exten, sizeof(c->exten));
03358                ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed));
03359                memset(d->exten, 0, sizeof(d->exten));
03360                skinny_newcall(c);
03361                return NULL;
03362             }
03363          } else {
03364             /* It's a match, but they just typed a digit, and there is an ambiguous match,
03365                so just set the timeout to matchdigittimeout and wait some more */
03366             timeout = matchdigittimeout;
03367          }
03368       } else if (res == 0) {
03369          ast_debug(1, "Not enough digits (%s) (and no ambiguous match)...\n", d->exten);
03370          memset(d->exten, 0, sizeof(d->exten));
03371          if (l->hookstate == SKINNY_OFFHOOK) {
03372             transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03373          }
03374          if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03375             ast_indicate(c, -1);
03376             ast_hangup(c);
03377          }
03378          return NULL;
03379       } else if (!ast_canmatch_extension(c, c->context, d->exten, 1, c->cid.cid_num) &&
03380             ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
03381          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);
03382          memset(d->exten, 0, sizeof(d->exten));
03383          if (l->hookstate == SKINNY_OFFHOOK) {
03384             transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03385             /* hang out for 3 seconds to let congestion play */
03386             ast_safe_sleep(c, 3000);
03387          }
03388          break;
03389       }
03390       if (!timeout) {
03391          timeout = gendigittimeout;
03392       }
03393       if (len && !ast_ignore_pattern(c->context, d->exten)) {
03394          ast_indicate(c, -1);
03395       }
03396    }
03397    if (c)
03398       ast_hangup(c);
03399    memset(d->exten, 0, sizeof(d->exten));
03400    return NULL;
03401 }

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

Definition at line 3768 of file chan_skinny.c.

References ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_UNHOLD, ast_debug, ast_get_indication_tone(), ast_log(), ast_playtones_start(), ast_queue_control(), AST_STATE_RING, tone_zone_sound::data, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_debug, skinny_subchannel::owner, skinny_subchannel::related, and skinny_subchannel::xferor.

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

03769 {
03770    struct skinny_subchannel *xferor; /* the sub doing the transferring */
03771    struct skinny_subchannel *xferee; /* the sub being transferred */
03772    const struct tone_zone_sound *ts = NULL;
03773       
03774    if (ast_bridged_channel(sub->owner) || ast_bridged_channel(sub->related->owner)) {
03775       if (sub->xferor) {
03776          xferor = sub;
03777          xferee = sub->related;
03778       } else {
03779          xferor = sub;
03780          xferee = sub->related;
03781       }
03782       
03783       if (skinnydebug) {
03784          ast_debug(1, "Transferee channels (local/remote): %s and %s\n",
03785             xferee->owner->name, ast_bridged_channel(xferee->owner)?ast_bridged_channel(xferee->owner)->name:"");
03786          ast_debug(1, "Transferor channels (local/remote): %s and %s\n",
03787             xferor->owner->name, ast_bridged_channel(xferor->owner)?ast_bridged_channel(xferor->owner)->name:"");
03788       }
03789       if (ast_bridged_channel(xferor->owner)) {
03790          if (ast_bridged_channel(xferee->owner)) {
03791             ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
03792          }
03793          if (xferor->owner->_state == AST_STATE_RING) {
03794             /* play ringing inband */
03795             ts = ast_get_indication_tone(xferor->owner->zone, "ring");
03796             ast_playtones_start(xferor->owner, 0, ts->data, 1);
03797          }
03798          if (skinnydebug)
03799             ast_debug(1, "Transfer Masquerading %s to %s\n",
03800                xferee->owner->name, ast_bridged_channel(xferor->owner)?ast_bridged_channel(xferor->owner)->name:"");
03801          if (ast_channel_masquerade(xferee->owner, ast_bridged_channel(xferor->owner))) {
03802             ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03803                ast_bridged_channel(xferor->owner)->name, xferee->owner->name);
03804             return -1;
03805          }
03806       } else if (ast_bridged_channel(xferee->owner)) {
03807          ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
03808          if (xferor->owner->_state == AST_STATE_RING) {
03809             /* play ringing inband */
03810             ts = ast_get_indication_tone(xferor->owner->zone, "ring");
03811             ast_playtones_start(xferor->owner, 0, ts->data, 1);
03812          }
03813          if (skinnydebug)
03814             ast_debug(1, "Transfer Masquerading %s to %s\n",
03815                xferor->owner->name, ast_bridged_channel(xferee->owner)?ast_bridged_channel(xferee->owner)->name:"");
03816          if (ast_channel_masquerade(xferor->owner, ast_bridged_channel(xferee->owner))) {
03817             ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03818                ast_bridged_channel(xferee->owner)->name, xferor->owner->name);
03819             return -1;
03820          }
03821          return 0;
03822       } else {
03823          if (option_debug)
03824             ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03825                xferor->owner->name, xferee->owner->name);
03826       }
03827    }
03828    return 0;
03829 }

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

Definition at line 4063 of file chan_skinny.c.

References AST_CONTROL_UNHOLD, ast_queue_control(), ast_verb, skinny_line::hookstate, skinny_line::instance, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_line::parent, SKINNY_CONNECTED, SKINNY_LAMP_ON, SKINNY_OFFHOOK, STIMULUS_LINE, skinny_line::sub, transmit_activatecallplane(), transmit_callstateonly(), transmit_connect(), and transmit_lamp_indication().

Referenced by handle_hold_button(), and handle_soft_key_event_message().

04064 {
04065    struct skinny_line *l = sub->parent;
04066    struct skinny_device *d = l->parent;
04067 
04068    /* Don't try to unhold a channel that doesn't exist */
04069    if (!sub || !sub->owner)
04070       return 0;
04071 
04072    /* Channel is on hold, so we will unhold */
04073    if (skinnydebug)
04074       ast_verb(1, "Taking off Hold(%d)\n", l->instance);
04075 
04076    ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
04077 
04078    transmit_activatecallplane(d, l);
04079 
04080    transmit_connect(d, sub);
04081    transmit_callstateonly(d, sub, SKINNY_CONNECTED);
04082    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04083    l->hookstate = SKINNY_OFFHOOK;
04084    sub->onhold = 0;
04085    return 1;
04086 }

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

Definition at line 1804 of file chan_skinny.c.

References AST_DEVICE_UNAVAILABLE, ast_devstate_changed(), ast_extension_state_del(), AST_LIST_TRAVERSE, skinny_device::lines, skinny_device::name, skinny_line::name, 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().

01805 {
01806    struct skinny_device *d;
01807    struct skinny_line *l;
01808    struct skinny_speeddial *sd;
01809 
01810    d = s->device;
01811 
01812    if (d) {
01813       d->session = NULL;
01814       d->registered = 0;
01815 
01816       AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01817          if (sd->stateid > -1)
01818             ast_extension_state_del(sd->stateid, NULL);
01819       }
01820       AST_LIST_TRAVERSE(&d->lines, l, list) {
01821          unregister_exten(l);
01822          ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Skinny/%s@%s", l->name, d->name);
01823       }
01824    }
01825 
01826    return -1; /* main loop will destroy the session */
01827 }

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

Definition at line 3632 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.

03633 {
03634    struct skinny_subchannel *sub = ast->tech_pvt;
03635    int res = 0;
03636    if (frame->frametype != AST_FRAME_VOICE) {
03637       if (frame->frametype == AST_FRAME_IMAGE) {
03638          return 0;
03639       } else {
03640          ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
03641          return 0;
03642       }
03643    } else {
03644       if (!(frame->subclass & ast->nativeformats)) {
03645          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
03646             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
03647          return -1;
03648       }
03649    }
03650    if (sub) {
03651       ast_mutex_lock(&sub->lock);
03652       if (sub->rtp) {
03653          res = ast_rtp_write(sub->rtp, frame);
03654       }
03655       ast_mutex_unlock(&sub->lock);
03656    }
03657    return res;
03658 }

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 3239 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(), io, skinny_subchannel::lock, skinny_line::nat, skinny_subchannel::owner, skinny_line::parent, skinny_line::prefs, qos, skinny_subchannel::rtp, sched, skinny_line::sub, transmit_connect(), and skinny_subchannel::vrtp.

03240 {
03241    struct skinny_line *l = sub->parent;
03242    struct skinny_device *d = l->parent;
03243    int hasvideo = 0;
03244 
03245    ast_mutex_lock(&sub->lock);
03246    /* Allocate the RTP */
03247    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
03248    if (hasvideo)
03249       sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
03250    
03251    if (sub->rtp && sub->owner) {
03252       ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
03253       ast_channel_set_fd(sub->owner, 1, ast_rtcp_fd(sub->rtp));
03254    }
03255    if (hasvideo && sub->vrtp && sub->owner) {
03256       ast_channel_set_fd(sub->owner, 2, ast_rtp_fd(sub->vrtp));
03257       ast_channel_set_fd(sub->owner, 3, ast_rtcp_fd(sub->vrtp));
03258    }
03259    if (sub->rtp) {
03260       ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
03261       ast_rtp_setnat(sub->rtp, l->nat);
03262    }
03263    if (sub->vrtp) {
03264       ast_rtp_setqos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
03265       ast_rtp_setnat(sub->vrtp, l->nat);
03266    }
03267    /* Set Frame packetization */
03268    if (sub->rtp)
03269       ast_rtp_codec_setpref(sub->rtp, &l->prefs);
03270 
03271    /* Create the RTP connection */
03272    transmit_connect(d, sub);
03273    ast_mutex_unlock(&sub->lock);
03274 }

static void transmit_activatecallplane ( struct skinny_device d,
struct skinny_line l 
) [static]

Definition at line 2138 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_data::activatecallplane, skinny_req::data, htolel, skinny_line::instance, activate_call_plane_message::lineInstance, req_alloc(), and transmit_response().

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

02139 {
02140    struct skinny_req *req;
02141 
02142    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02143       return;
02144 
02145    req->data.activatecallplane.lineInstance = htolel(l->instance);
02146    transmit_response(d, req);
02147 }

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

Definition at line 1894 of file chan_skinny.c.

References ast_copy_string(), ast_verb, 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, skinny_device::name, call_info_message::reference, req_alloc(), transmit_response(), and call_info_message::type.

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

01895 {
01896    struct skinny_req *req;
01897 
01898    /* We should not be able to get here without a device */
01899    if (!d)
01900       return;
01901 
01902    if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
01903       return;
01904 
01905    if (skinnydebug)
01906          ast_verb(1, "Setting Callinfo to %s(%s) from %s(%s) on %s(%d)\n", fromname, fromnum, toname, tonum, d->name, instance);
01907 
01908    if (fromname) {
01909       ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
01910    }
01911    if (fromnum) {
01912       ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
01913    }
01914    if (toname) {
01915       ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
01916    }
01917    if (tonum) {
01918       ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
01919    }
01920    req->data.callinfo.instance = htolel(instance);
01921    req->data.callinfo.reference = htolel(callid);
01922    req->data.callinfo.type = htolel(calltype);
01923    transmit_response(d, req);
01924 }

static void transmit_callstate ( struct skinny_device d,
int  instance,
int  state,
unsigned  callid 
) [static]

Definition at line 2162 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(), 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(), handle_transfer_button(), skinny_extensionstate_cb(), and skinny_hangup().

02163 {
02164    struct skinny_req *req;
02165 
02166    if (state == SKINNY_ONHOOK) {
02167       if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
02168          return;
02169 
02170       req->data.closereceivechannel.conferenceId = htolel(callid);
02171       req->data.closereceivechannel.partyId = htolel(callid);
02172       transmit_response(d, req);
02173 
02174       if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02175          return;
02176 
02177       req->data.stopmedia.conferenceId = htolel(callid);
02178       req->data.stopmedia.passThruPartyId = htolel(callid);
02179       transmit_response(d, req);
02180 
02181       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
02182 
02183       transmit_displaypromptstatus(d, NULL, 0, instance, callid);
02184    }
02185 
02186    if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
02187       return;
02188 
02189    req->data.callstate.callState = htolel(state);
02190    req->data.callstate.lineInstance = htolel(instance);
02191    req->data.callstate.callReference = htolel(callid);
02192    transmit_response(d, req);
02193 
02194    if (state == SKINNY_ONHOOK) {
02195       transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
02196    }
02197 
02198    if (state == SKINNY_OFFHOOK || state == SKINNY_ONHOOK) {
02199       if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02200          return;
02201 
02202       req->data.activatecallplane.lineInstance = htolel(instance);
02203       transmit_response(d, req);
02204    }
02205 }

static void transmit_callstateonly ( struct skinny_device d,
struct skinny_subchannel sub,
int  state 
) [static]

Definition at line 2149 of file chan_skinny.c.

References CALL_STATE_MESSAGE, skinny_subchannel::callid, call_state_message::callReference, call_state_message::callState, skinny_data::callstate, skinny_req::data, htolel, skinny_line::instance, call_state_message::lineInstance, skinny_subchannel::parent, req_alloc(), and transmit_response().

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_answer(), skinny_call(), skinny_hold(), skinny_indicate(), and skinny_unhold().

02150 {
02151    struct skinny_req *req;
02152 
02153    if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
02154       return;
02155 
02156    req->data.callstate.callState = htolel(state);
02157    req->data.callstate.lineInstance = htolel(sub->parent->instance);
02158    req->data.callstate.callReference = htolel(sub->callid);
02159    transmit_response(d, req);
02160 }

static void transmit_cfwdstate ( struct skinny_device d,
struct skinny_line l 
) [static]

Definition at line 2208 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(), SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, and transmit_response().

Referenced by handle_callforward_button(), and skinny_ss().

02209 {
02210    struct skinny_req *req;
02211    int anyon = 0;
02212 
02213    if (!(req = req_alloc(sizeof(struct forward_stat_message), FORWARD_STAT_MESSAGE)))
02214       return;
02215 
02216    if (l->cfwdtype & SKINNY_CFWD_ALL) {
02217       if (!ast_strlen_zero(l->call_forward_all)) {
02218          ast_copy_string(req->data.forwardstat.fwdallnum, l->call_forward_all, sizeof(req->data.forwardstat.fwdallnum));
02219          req->data.forwardstat.fwdall = htolel(1);
02220          anyon++;
02221       } else {
02222          req->data.forwardstat.fwdall = htolel(0);
02223       }
02224    }
02225    if (l->cfwdtype & SKINNY_CFWD_BUSY) {
02226       if (!ast_strlen_zero(l->call_forward_busy)) {
02227          ast_copy_string(req->data.forwardstat.fwdbusynum, l->call_forward_busy, sizeof(req->data.forwardstat.fwdbusynum));
02228          req->data.forwardstat.fwdbusy = htolel(1);
02229          anyon++;
02230       } else {
02231          req->data.forwardstat.fwdbusy = htolel(0);
02232       }
02233    }
02234    if (l->cfwdtype & SKINNY_CFWD_NOANSWER) {
02235       if (!ast_strlen_zero(l->call_forward_noanswer)) {
02236          ast_copy_string(req->data.forwardstat.fwdnoanswernum, l->call_forward_noanswer, sizeof(req->data.forwardstat.fwdnoanswernum));
02237          req->data.forwardstat.fwdnoanswer = htolel(1);
02238          anyon++;
02239       } else {
02240          req->data.forwardstat.fwdnoanswer = htolel(0);
02241       }
02242    }
02243    req->data.forwardstat.lineNumber = htolel(l->instance);
02244    if (anyon)
02245       req->data.forwardstat.activeforward = htolel(7);
02246    else
02247       req->data.forwardstat.activeforward = htolel(0);
02248 
02249    transmit_response(d, req);
02250 }

static void transmit_closereceivechannel ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]

Definition at line 2114 of file chan_skinny.c.

References skinny_subchannel::callid, CLOSE_RECEIVE_CHANNEL_MESSAGE, skinny_data::closereceivechannel, close_receive_channel_message::conferenceId, skinny_req::data, htolel, close_receive_channel_message::partyId, req_alloc(), and transmit_response().

Referenced by skinny_hangup(), and skinny_hold().

02115 {
02116    struct skinny_req *req;
02117 
02118    if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
02119       return;
02120 
02121    req->data.closereceivechannel.conferenceId = htolel(0);
02122    req->data.closereceivechannel.partyId = htolel(sub->callid);
02123    transmit_response(d, req);
02124 }

static void transmit_connect ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]

Definition at line 1926 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, open_receive_channel_message::partyId, skinny_line::prefs, req_alloc(), skinny_line::sub, and transmit_response().

Referenced by skinny_unhold(), and start_rtp().

01927 {
01928    struct skinny_req *req;
01929    struct skinny_line *l = sub->parent;
01930    struct ast_format_list fmt;
01931 
01932    if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
01933       return;
01934 
01935    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
01936 
01937    req->data.openreceivechannel.conferenceId = htolel(sub->callid);
01938    req->data.openreceivechannel.partyId = htolel(sub->callid);
01939    req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
01940    req->data.openreceivechannel.capability = htolel(codec_ast2skinny(fmt.bits));
01941    req->data.openreceivechannel.echo = htolel(0);
01942    req->data.openreceivechannel.bitrate = htolel(0);
01943    transmit_response(d, req);
01944 }

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

Definition at line 2100 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(), and transmit_response().

Referenced by skinny_answer(), and skinny_indicate().

02101 {
02102    struct skinny_req *req;
02103 
02104    if (!(req = req_alloc(sizeof(struct dialed_number_message), DIALED_NUMBER_MESSAGE)))
02105       return;
02106 
02107    ast_copy_string(req->data.dialednumber.dialedNumber, text, sizeof(req->data.dialednumber.dialedNumber));
02108    req->data.dialednumber.lineInstance = htolel(instance);
02109    req->data.dialednumber.callReference = htolel(callid);
02110 
02111    transmit_response(d, req);
02112 }

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

Definition at line 2028 of file chan_skinny.c.

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

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

02029 {
02030    struct skinny_req *req;
02031 
02032    if (text == 0) {
02033       if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
02034          return;
02035 
02036       //what do we want hear CLEAR_DISPLAY_MESSAGE or CLEAR_PROMPT_STATUS???
02037       //if we are clearing the display, it appears there is no instance and refernece info (size 0)
02038       //req->data.clearpromptstatus.lineInstance = instance;
02039       //req->data.clearpromptstatus.callReference = reference;
02040 
02041       if (skinnydebug)
02042          ast_verb(1, "Clearing Display\n");
02043    } else {
02044       if (!(req = req_alloc(sizeof(struct displaytext_message), DISPLAYTEXT_MESSAGE)))
02045          return;
02046 
02047       ast_copy_string(req->data.displaytext.text, text, sizeof(req->data.displaytext.text));
02048       if (skinnydebug)
02049          ast_verb(1, "Displaying message '%s'\n", req->data.displaytext.text);
02050    }
02051 
02052    transmit_response(d, req);
02053 }

static void transmit_displaynotify ( struct skinny_device d,
const char *  text,
int  t 
) [static]

Definition at line 2055 of file chan_skinny.c.

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

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

02056 {
02057    struct skinny_req *req;
02058 
02059    if (!(req = req_alloc(sizeof(struct display_notify_message), DISPLAY_NOTIFY_MESSAGE)))
02060       return;
02061 
02062    ast_copy_string(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage));
02063    req->data.displaynotify.displayTimeout = htolel(t);
02064 
02065    if (skinnydebug)
02066       ast_verb(1, "Displaying notify '%s'\n", text);
02067 
02068    transmit_response(d, req);
02069 }

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

Definition at line 2071 of file chan_skinny.c.

References ast_copy_string(), ast_verb, 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(), and transmit_response().

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

02072 {
02073    struct skinny_req *req;
02074 
02075    if (text == 0) {
02076       if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
02077          return;
02078 
02079       req->data.clearpromptstatus.lineInstance = htolel(instance);
02080       req->data.clearpromptstatus.callReference = htolel(callid);
02081 
02082       if (skinnydebug)
02083          ast_verb(1, "Clearing Prompt\n");
02084    } else {
02085       if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
02086          return;
02087 
02088       ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
02089       req->data.displaypromptstatus.messageTimeout = htolel(t);
02090       req->data.displaypromptstatus.lineInstance = htolel(instance);
02091       req->data.displaypromptstatus.callReference = htolel(callid);
02092 
02093       if (skinnydebug)
02094          ast_verb(1, "Displaying Prompt Status '%s'\n", text);
02095    }
02096 
02097    transmit_response(d, req);
02098 }

static void transmit_lamp_indication ( struct skinny_device d,
int  stimulus,
int  instance,
int  indication 
) [static]

Definition at line 1990 of file chan_skinny.c.

References skinny_req::data, set_lamp_message::deviceStimulus, htolel, req_alloc(), 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().

01991 {
01992    struct skinny_req *req;
01993 
01994    if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
01995       return;
01996 
01997    req->data.setlamp.stimulus = htolel(stimulus);
01998    req->data.setlamp.stimulusInstance = htolel(instance);
01999    req->data.setlamp.deviceStimulus = htolel(indication);
02000    transmit_response(d, req);
02001 }

static int transmit_response ( struct skinny_device d,
struct skinny_req req 
) [static]

Definition at line 1829 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_device::session, SKINNY_MAX_PACKET, and skinny_unregister().

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

static void transmit_ringer_mode ( struct skinny_device d,
int  mode 
) [static]

Definition at line 2003 of file chan_skinny.c.

References ast_verb, skinny_req::data, htolel, req_alloc(), set_ringer_message::ringerMode, SET_RINGER_MESSAGE, skinny_data::setringer, 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().

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

static void transmit_selectsoftkeys ( struct skinny_device d,
int  instance,
int  callid,
int  softkey 
) [static]

Definition at line 1976 of file chan_skinny.c.

References skinny_req::data, htolel, select_soft_keys_message::instance, select_soft_keys_message::reference, req_alloc(), 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_hold_button(), handle_offhook_message(), handle_soft_key_event_message(), handle_soft_key_set_req_message(), handle_stimulus_message(), handle_transfer_button(), skinny_answer(), skinny_call(), and transmit_callstate().

01977 {
01978    struct skinny_req *req;
01979 
01980    if (!(req = req_alloc(sizeof(struct select_soft_keys_message), SELECT_SOFT_KEYS_MESSAGE)))
01981       return;
01982 
01983    req->data.selectsoftkey.instance = htolel(instance);
01984    req->data.selectsoftkey.reference = htolel(callid);
01985    req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
01986    req->data.selectsoftkey.validKeyMask = htolel(0xFFFFFFFF);
01987    transmit_response(d, req);
01988 }

static void transmit_speaker_mode ( struct skinny_device d,
int  mode 
) [static]

Definition at line 1871 of file chan_skinny.c.

References skinny_req::data, htolel, set_speaker_message::mode, req_alloc(), 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().

01872 {
01873    struct skinny_req *req;
01874 
01875    if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
01876       return;
01877 
01878    req->data.setspeaker.mode = htolel(mode);
01879    transmit_response(d, req);
01880 }

static void transmit_stopmediatransmission ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]

Definition at line 2126 of file chan_skinny.c.

References skinny_subchannel::callid, stop_media_transmission_message::conferenceId, skinny_req::data, htolel, stop_media_transmission_message::passThruPartyId, req_alloc(), STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, and transmit_response().

Referenced by skinny_hangup(), and skinny_hold().

02127 {
02128    struct skinny_req *req;
02129 
02130    if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02131       return;
02132 
02133    req->data.stopmedia.conferenceId = htolel(0);
02134    req->data.stopmedia.passThruPartyId = htolel(sub->callid);
02135    transmit_response(d, req);
02136 }

static void transmit_tone ( struct skinny_device d,
int  tone,
int  instance,
int  reference 
) [static]

Definition at line 1946 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(), 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(), handle_transfer_button(), skinny_answer(), skinny_hangup(), skinny_indicate(), skinny_newcall(), skinny_senddigit_end(), and skinny_ss().

01947 {
01948    struct skinny_req *req;
01949 
01950    if (tone == SKINNY_NOTONE) {
01951       /* This is bad, mmm'kay? */
01952       return;
01953    }
01954 
01955    if (tone > 0) {
01956       if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
01957          return;
01958       req->data.starttone.tone = htolel(tone);
01959       req->data.starttone.instance = htolel(instance);
01960       req->data.starttone.reference = htolel(reference);
01961    } else {
01962       if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
01963          return;
01964       req->data.stoptone.instance = htolel(instance);
01965       req->data.stoptone.reference = htolel(reference);
01966    }
01967 
01968    //Bad, tone is already set so this is redundant and a change to the if above
01969    //may lead to issues where we try to set a tone to a stop_tone_message
01970    //if (tone > 0) {
01971    // req->data.starttone.tone = htolel(tone);
01972    //}
01973    transmit_response(d, req);
01974 }

static int unload_module ( void   )  [static]

Definition at line 6427 of file chan_skinny.c.

References skinny_subchannel::alreadygone, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_context_destroy(), ast_context_find(), ast_event_unsubscribe(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, 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(), free, skinny_device::lines, skinny_subchannel::lock, skinny_line::lock, monlock, skinny_line::mwi_event_sub, netlock, skinny_subchannel::owner, s, sched, sched_context_destroy(), skinny_rtp, skinny_tech, and skinny_line::sub.

06428 {
06429    struct skinnysession *s;
06430    struct skinny_device *d;
06431    struct skinny_line *l;
06432    struct skinny_subchannel *sub;
06433    struct ast_context *con;
06434 
06435    AST_LIST_LOCK(&sessions);
06436    /* Destroy all the interfaces and free their memory */
06437    while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
06438       d = s->device;
06439       AST_LIST_TRAVERSE(&d->lines, l, list){
06440          ast_mutex_lock(&l->lock);
06441          AST_LIST_TRAVERSE(&l->sub, sub, list) {
06442             ast_mutex_lock(&sub->lock);
06443             if (sub->owner) {
06444                sub->alreadygone = 1;
06445                ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
06446             }
06447             ast_mutex_unlock(&sub->lock);
06448          }
06449          if (l->mwi_event_sub)
06450             ast_event_unsubscribe(l->mwi_event_sub);
06451          ast_mutex_unlock(&l->lock);
06452       }
06453       if (s->fd > -1)
06454          close(s->fd);
06455       free(s);
06456    }
06457    AST_LIST_UNLOCK(&sessions);
06458 
06459    delete_devices();
06460 
06461    ast_mutex_lock(&monlock);
06462    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
06463       pthread_cancel(monitor_thread);
06464       pthread_kill(monitor_thread, SIGURG);
06465       pthread_join(monitor_thread, NULL);
06466    }
06467    monitor_thread = AST_PTHREADT_STOP;
06468    ast_mutex_unlock(&monlock);
06469 
06470    ast_mutex_lock(&netlock);
06471    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
06472       pthread_cancel(accept_t);
06473       pthread_kill(accept_t, SIGURG);
06474       pthread_join(accept_t, NULL);
06475    }
06476    accept_t = AST_PTHREADT_STOP;
06477    ast_mutex_unlock(&netlock);
06478 
06479    ast_rtp_proto_unregister(&skinny_rtp);
06480    ast_channel_unregister(&skinny_tech);
06481    ast_cli_unregister_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
06482 
06483    close(skinnysock);
06484    if (sched)
06485       sched_context_destroy(sched);
06486 
06487    con = ast_context_find(used_context);
06488    if (con)
06489       ast_context_destroy(con, "Skinny");
06490    
06491    return 0;
06492 }

static void unregister_exten ( struct skinny_line l  )  [static]

Definition at line 1736 of file chan_skinny.c.

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

Referenced by skinny_unregister().

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


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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 6497 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 966 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 970 of file chan_skinny.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 991 of file chan_skinny.c.

struct ast_hostent ahp

Definition at line 967 of file chan_skinny.c.

Referenced by __ast_http_load(), __init_manager(), __set_address_from_contact(), ast_find_ourip(), ast_get_ip_or_srv(), ast_parse_arg(), check_via(), create_addr(), 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(), rpt_exec(), rtcp_do_debug_ip(), rtp_do_debug_ip(), set_destination(), and sip_do_debug_ip().

int amaflags = 0 [static]

Definition at line 994 of file chan_skinny.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 6497 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 963 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 995 of file chan_skinny.c.

int callreturn = 0 [static]

Definition at line 984 of file chan_skinny.c.

int callwaiting = 0 [static]

Definition at line 983 of file chan_skinny.c.

int cancallforward = 0 [static]

Definition at line 989 of file chan_skinny.c.

int canreinvite = 0 [static]

Definition at line 996 of file chan_skinny.c.

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 976 of file chan_skinny.c.

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 975 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 3001 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 3000 of file chan_skinny.c.

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

Definition at line 77 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 166 of file chan_skinny.c.

Referenced by control2str().

unsigned int cos

Definition at line 100 of file chan_skinny.c.

unsigned int cos_audio

Definition at line 101 of file chan_skinny.c.

unsigned int cos_video

Definition at line 102 of file chan_skinny.c.

ast_group_t cur_callergroup = 0 [static]

Definition at line 980 of file chan_skinny.c.

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 981 of file chan_skinny.c.

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

Definition at line 109 of file chan_skinny.c.

int default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW [static]

Definition at line 79 of file chan_skinny.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 153 of file chan_skinny.c.

struct ast_codec_pref default_prefs [static]

Definition at line 80 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 163 of file chan_skinny.c.

Referenced by device2str().

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.

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

Definition at line 971 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 161 of file chan_skinny.c.

struct hostent* hp

Definition at line 968 of file chan_skinny.c.

Referenced by __ast_http_load(), __init_manager(), __set_address_from_contact(), ast_find_ourip(), ast_get_ip_or_srv(), ast_gethostbyname(), ast_parse_arg(), build_peer(), check_via(), connect_sphinx(), create_addr(), 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(), process_sdp_c(), realtime_peer(), realtime_user(), reload_config(), rpt_exec(), rtcp_do_debug_ip(), rtp_do_debug_ip(), set_config(), set_destination(), and sip_do_debug_ip().

int immediate = 0 [static]

Definition at line 982 of file chan_skinny.c.

struct io_context* io [static]

Definition at line 1105 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 105 of file chan_skinny.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 972 of file chan_skinny.c.

char linelabel[AST_MAX_EXTENSION] = "" [static]

Definition at line 977 of file chan_skinny.c.

Referenced by build_device().

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 992 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 973 of file chan_skinny.c.

char mohsuggest[MAX_MUSICCLASS] = "" [static]

Definition at line 974 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 1109 of file chan_skinny.c.

int mwiblink = 0 [static]

Definition at line 986 of file chan_skinny.c.

int nat = 0 [static]

Definition at line 979 of file chan_skinny.c.

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

Definition at line 1111 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 964 of file chan_skinny.c.

int ourport [static]

Definition at line 965 of file chan_skinny.c.

char parkinglot[AST_MAX_CONTEXT] = "" [static]

Definition at line 978 of file chan_skinny.c.

struct { ... } qos [static]

char regcontext[AST_MAX_CONTEXT] [static]

Definition at line 108 of file chan_skinny.c.

char regexten[AST_MAX_EXTENSION] [static]

Definition at line 993 of file chan_skinny.c.

Referenced by build_peer().

struct sched_context* sched = NULL [static]

Definition at line 1104 of file chan_skinny.c.

int skinny_header_size = 12

Definition at line 954 of file chan_skinny.c.

struct ast_rtp_protocol skinny_rtp [static]

Definition at line 2487 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1282 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 960 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 969 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 749 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 793 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 779 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 788 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 812 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 771 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 802 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 758 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 739 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 765 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 797 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 808 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[]

Definition at line 576 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 76 of file chan_skinny.c.

int threewaycalling = 0 [static]

Definition at line 985 of file chan_skinny.c.

unsigned int tos

Definition at line 97 of file chan_skinny.c.

unsigned int tos_audio

Definition at line 98 of file chan_skinny.c.

unsigned int tos_video

Definition at line 99 of file chan_skinny.c.

int transfer = 0 [static]

Definition at line 988 of file chan_skinny.c.

char used_context[AST_MAX_EXTENSION] [static]

Definition at line 107 of file chan_skinny.c.

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

Definition at line 110 of file chan_skinny.c.

char vmexten[AST_MAX_EXTENSION] [static]

Definition at line 106 of file chan_skinny.c.


Generated on Wed Aug 18 22:34:18 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7