Fri Jun 19 12:10:25 2009

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

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

Referenced by transmit_activatecallplane(), and transmit_callstate().

#define ALARM_MESSAGE   0x0020

Definition at line 251 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 458 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 461 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 462 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 460 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 469 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 468 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 455 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 459 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 452 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 453 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 454 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 450 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 456 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 463 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 448 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 449 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 451 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 457 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 247 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 418 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 356 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 855 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_callstateonly().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 491 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 219 of file chan_skinny.c.

Referenced by handle_message().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 489 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 488 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 872 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 527 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

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

Referenced by handle_time_date_req_message().

#define DEVICE2STR_BUFSIZE   15

Definition at line 163 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 889 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 878 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 863 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 483 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 195 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 378 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

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

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 514 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 172 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

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

#define KEYDEF_CONNWITHTRANS   5

Definition at line 546 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 547 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

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

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 543 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0

Definition at line 541 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), and transmit_callstate().

#define KEYDEF_RINGIN   3

Definition at line 544 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

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

#define KEYPAD_BUTTON_MESSAGE   0x0003

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

Referenced by handle_line_state_req_message().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 241 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 207 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 213 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 259 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 516 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 281 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 279 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 175 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 493 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 509 of file chan_skinny.c.

Referenced by handle_skinny_reset().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 847 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 249 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 498 of file chan_skinny.c.

Referenced by handle_server_request_message().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 312 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 325 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 304 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 319 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1060 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1047 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1059 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1054 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1050 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1062 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CFWD_ALL   (1 << 0)

Definition at line 1076 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 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_NOANSWER   (1 << 2)

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(), and transmit_cfwdstate().

#define SKINNY_CONGESTION   7

Definition at line 1048 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

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

#define SKINNY_CX_CONFERENCE   3

Definition at line 1088 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1090 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1089 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1085 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1084 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1086 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 1002 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1001 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1000 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 999 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1003 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1029 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1025 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1018 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1004 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1013 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1028 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1011 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1026 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1017 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1016 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1007 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1032 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1020 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1006 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1009 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1015 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1021 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1022 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1005 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1031 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1014 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1019 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1023 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1027 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1010 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1024 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1012 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1008 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1030 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 998 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1033 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1034 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 997 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DIALTONE   0x21

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

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1055 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

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

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1

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

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_MAX_CAPABILITIES   18

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

#define SKINNY_MICON   1

Definition at line 1039 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1063 of file chan_skinny.c.

Referenced by transmit_tone().

#define SKINNY_OFFHOOK   1

Definition at line 1042 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 1043 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 1052 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1053 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER   0x25

Definition at line 1061 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1074 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1072 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

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

#define SKINNY_RINGIN   4

Definition at line 1045 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_extensionstate_cb().

#define SKINNY_RINGOUT   3

Definition at line 1044 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE   0x00

Definition at line 1057 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 1037 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 1036 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 1051 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 269 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 267 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 832 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 277 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 534 of file chan_skinny.c.

Referenced by handle_soft_key_template_req_message().

#define SOFTKEY_ANSWER   0x0B

Definition at line 564 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 561 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 558 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 559 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 560 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 566 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 572 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 562 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 571 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 556 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 573 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 565 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 568 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 569 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 555 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 553 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 567 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 570 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 554 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 563 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 557 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 236 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 390 of file chan_skinny.c.

Referenced by handle_speed_dial_stat_req_message().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

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

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 440 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 443 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 444 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 442 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 437 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 441 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 434 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 435 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 436 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 432 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

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

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 445 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 430 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 431 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 433 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 439 of file chan_skinny.c.

Referenced by do_housekeeping(), and handle_stimulus_message().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 349 of file chan_skinny.c.

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

#define STOP_TONE_MESSAGE   0x0083

Definition at line 298 of file chan_skinny.c.

Referenced by transmit_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 246 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_LINE   2

Definition at line 1081 of file chan_skinny.c.

#define TYPE_TRUNK   1

Definition at line 1080 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 276 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 248 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

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

00176 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 162 of file chan_skinny.c.

00176 {

static void __reg_module ( void   )  [static]

Definition at line 6486 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

Definition at line 6486 of file chan_skinny.c.

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

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

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

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

implement the setvar config line

Definition at line 1526 of file chan_skinny.c.

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

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

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

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

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

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

Definition at line 1687 of file chan_skinny.c.

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

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

static int codec_ast2skinny ( int  astcodec  )  [static]

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

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

static int codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

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

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

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

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

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

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

Definition at line 2570 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

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

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

Definition at line 2565 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

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

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

Definition at line 2575 of file chan_skinny.c.

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

Referenced by handle_skinny_show_line().

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

static char* control2str ( int  ind  )  [static]

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

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

static void delete_devices ( void   )  [static]

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

06340 {
06341    struct skinny_device *d;
06342    struct skinny_line *l;
06343    struct skinny_speeddial *sd;
06344    struct skinny_addon *a;
06345 
06346    AST_LIST_LOCK(&devices);
06347 
06348    /* Delete all devices */
06349    while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
06350       /* Delete all lines for this device */
06351       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
06352          free(l);
06353       }
06354       /* Delete all speeddials for this device */
06355       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
06356          free(sd);
06357       }
06358       /* Delete all addons for this device */
06359       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
06360          free(a);
06361       } 
06362       free(d);
06363    }
06364    AST_LIST_UNLOCK(&devices);
06365 }

static void destroy_session ( struct skinnysession s  )  [static]

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

05866 {
05867    struct skinnysession *cur;
05868    AST_LIST_LOCK(&sessions);
05869    AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, cur, list) {
05870       if (cur == s) {
05871          AST_LIST_REMOVE_CURRENT(list);
05872          if (s->fd > -1) 
05873             close(s->fd);
05874          
05875          ast_mutex_destroy(&s->lock);
05876          
05877          ast_free(s);
05878       } else {
05879          ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
05880       }
05881    }
05882    AST_LIST_TRAVERSE_SAFE_END
05883    AST_LIST_UNLOCK(&sessions);
05884 }

static char* device2str ( int  type  )  [static]

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

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

static void do_housekeeping ( struct skinnysession s  )  [static]

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

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

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

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

06063 {
06064    int res;
06065 
06066    /* This thread monitors all the interfaces which are not yet in use
06067       (and thus do not have a separate thread) indefinitely */
06068    /* From here on out, we die whenever asked */
06069    for(;;) {
06070       pthread_testcancel();
06071       /* Wait for sched or io */
06072       res = ast_sched_wait(sched);
06073       if ((res < 0) || (res > 1000)) {
06074          res = 1000;
06075       }
06076       res = ast_io_wait(io, res);
06077       ast_mutex_lock(&monlock);
06078       if (res >= 0) {
06079          ast_sched_runq(sched);
06080       }
06081       ast_mutex_unlock(&monlock);
06082    }
06083    /* Never reached */
06084    return NULL;
06085 
06086 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int get_devicestate ( struct skinny_line l  )  [static]

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

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

static int get_input ( struct skinnysession s  )  [static]

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

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

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

Definition at line 5150 of file chan_skinny.c.

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

Referenced by handle_message().

05151 {
05152    /* no response necessary */
05153    if (skinnydebug)
05154       ast_verb(1, "Received Alarm Message: %s\n", req->data.alarm.displayMessage);
05155 
05156    return 1;
05157 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 5684 of file chan_skinny.c.

Referenced by handle_message().

05685 {
05686    /* XXX umm...okay?  Why do I care? */
05687    return 1;
05688 }

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

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

04082 {
04083    if (!sub)
04084       return -1;
04085    if (sub->related) {
04086       skinny_hold(sub);
04087       skinny_unhold(sub->related);
04088       sub->parent->activesub = sub->related;
04089    } else {
04090       if (sub->onhold) {
04091          skinny_unhold(sub);
04092          transmit_selectsoftkeys(sub->parent->parent, sub->parent->instance, sub->callid, KEYDEF_CONNECTED);
04093       } else {
04094          skinny_hold(sub);
04095          transmit_selectsoftkeys(sub->parent->parent, sub->parent->instance, sub->callid, KEYDEF_ONHOLD);
04096       }
04097    }
04098    return 1;
04099 }

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

Definition at line 4275 of file chan_skinny.c.

Referenced by handle_message().

04276 {
04277    /* no response necessary */
04278    return 1;
04279 }

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

Definition at line 4162 of file chan_skinny.c.

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

Referenced by handle_message().

04163 {
04164    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
04165       return -1;
04166 
04167    transmit_response(s->device, req);
04168    do_housekeeping(s);
04169    return 1;
04170 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 5690 of file chan_skinny.c.

Referenced by handle_message().

05691 {
05692    /* XXX I have no clue what this is for, but my phone was sending it, so... */
05693    return 1;
05694 }

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

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

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

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

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

05137 {
05138    struct skinny_device *d = s->device;
05139    if (!(req = req_alloc(sizeof(struct server_res_message), SERVER_RES_MESSAGE)))
05140       return -1;
05141 
05142    memcpy(req->data.serverres.server[0].serverName, ourhost,
05143          sizeof(req->data.serverres.server[0].serverName));
05144    req->data.serverres.serverListenPort[0] = htolel(ourport);
05145    req->data.serverres.serverIpAddr[0] = htolel(d->ourip.s_addr);
05146    transmit_response(d, req);
05147    return 1;
05148 }

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

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

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

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

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

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

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

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

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

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 2789 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.

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

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

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

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

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 2887 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::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.

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

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

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

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

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 2965 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.

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

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

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

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

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

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

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

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

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

05670 {
05671    if (!(req = req_alloc(sizeof(struct soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
05672       return -1;
05673 
05674    req->data.softkeytemplate.softKeyOffset = htolel(0);
05675    req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
05676    req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
05677    memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
05678       soft_key_template_default,
05679       sizeof(soft_key_template_default));
05680    transmit_response(s->device, req);
05681    return 1;
05682 }

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

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

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

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

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

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

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

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

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

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

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

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

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

Definition at line 5664 of file chan_skinny.c.

References s, and skinny_unregister().

Referenced by handle_message().

05665 {
05666    return skinny_unregister(req, s);
05667 }

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

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

05126 {
05127    struct skinny_device *d = s->device;
05128    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
05129       return -1;
05130 
05131    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
05132    transmit_response(d, req);
05133    return 1;
05134 }

static int has_voicemail ( struct skinny_line l  )  [static]

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

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

static int load_module ( void   )  [static]

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

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

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

Definition at line 2303 of file chan_skinny.c.

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

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

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

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

static void register_exten ( struct skinny_line l  )  [static]

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

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

static int reload_config ( void   )  [static]

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

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

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

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

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

static int restart_monitor ( void   )  [static]

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

06089 {
06090    /* If we're supposed to be stopped -- stay stopped */
06091    if (monitor_thread == AST_PTHREADT_STOP)
06092       return 0;
06093 
06094    ast_mutex_lock(&monlock);
06095    if (monitor_thread == pthread_self()) {
06096       ast_mutex_unlock(&monlock);
06097       ast_log(LOG_WARNING, "Cannot kill myself\n");
06098       return -1;
06099    }
06100    if (monitor_thread != AST_PTHREADT_NULL) {
06101       /* Wake up the thread */
06102       pthread_kill(monitor_thread, SIGURG);
06103    } else {
06104       /* Start a new monitor */
06105       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
06106          ast_mutex_unlock(&monlock);
06107          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06108          return -1;
06109       }
06110    }
06111    ast_mutex_unlock(&monlock);
06112    return 0;
06113 }

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

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

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

static int skinny_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6115 of file chan_skinny.c.

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

06116 {
06117    struct skinny_line *l;
06118    char *tmp;
06119 
06120    tmp = ast_strdupa(data);
06121 
06122    l = find_line_by_name(tmp);
06123 
06124    return get_devicestate(l);
06125 }

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

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

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

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

Definition at line 3658 of file chan_skinny.c.

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

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

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

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

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

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

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

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

static int skinny_hangup ( struct ast_channel ast  )  [static]

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

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

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

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

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

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

Definition at line 3829 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), 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().

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

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

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

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

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

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

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

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

Definition at line 3620 of file chan_skinny.c.

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

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

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

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

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

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

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

05962 {
05963    struct skinny_req *req;
05964 
05965    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
05966       return NULL;
05967 
05968    ast_mutex_lock(&s->lock);
05969    memcpy(req, s->inbuf, skinny_header_size);
05970    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*(int*)(s->inbuf))-4);
05971 
05972    ast_mutex_unlock(&s->lock);
05973 
05974    if (letohl(req->e) < 0) {
05975       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
05976       ast_free(req);
05977       return NULL;
05978    }
05979 
05980    return req;
05981 }

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

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

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

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

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

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

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

Definition at line 3670 of file chan_skinny.c.

03671 {
03672    return -1; /* Start inband indications */
03673 }

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

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

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

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

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

05984 {
05985    int res;
05986    struct skinny_req *req;
05987    struct skinnysession *s = data;
05988 
05989    ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
05990 
05991    for (;;) {
05992       res = get_input(s);
05993       if (res < 0) {
05994          break;
05995       }
05996 
05997       if (res > 0)
05998       {
05999          if (!(req = skinny_req_parse(s))) {
06000             destroy_session(s);
06001             return NULL;
06002          }
06003 
06004          res = handle_message(req, s);
06005          if (res < 0) {
06006             destroy_session(s);
06007             return NULL;
06008          }
06009       }
06010    }
06011    ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));
06012 
06013    if (s) 
06014       destroy_session(s);
06015    
06016    return 0;
06017 }

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 2416 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.

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

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

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

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

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

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

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

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

static void start_rtp ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

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

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

static void unregister_exten ( struct skinny_line l  )  [static]

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

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


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

struct in_addr __ourip [static]

Definition at line 965 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 969 of file chan_skinny.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 990 of file chan_skinny.c.

struct ast_hostent ahp

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

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 6486 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 962 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 994 of file chan_skinny.c.

int callreturn = 0 [static]

Definition at line 983 of file chan_skinny.c.

int callwaiting = 0 [static]

Definition at line 982 of file chan_skinny.c.

int cancallforward = 0 [static]

Definition at line 988 of file chan_skinny.c.

int canreinvite = 0 [static]

Definition at line 995 of file chan_skinny.c.

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 975 of file chan_skinny.c.

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 974 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 2999 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 2998 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 165 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 979 of file chan_skinny.c.

ast_group_t cur_pickupgroup = 0 [static]

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

Referenced by device2str().

int firstdigittimeout = 16000 [static]

Definition at line 1117 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1120 of file chan_skinny.c.

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

Definition at line 970 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 160 of file chan_skinny.c.

struct hostent* hp

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_gethostbyname(), ast_parse_arg(), build_peer(), check_via(), connect_sphinx(), create_addr(), gtalk_load_config(), gtalk_update_stun(), handle_cli_udptl_debug_deprecated(), handle_cli_udptl_set_debug(), iax_template_parse(), jingle_load_config(), jingle_update_stun(), launch_netscript(), parse_register_contact(), process_sdp(), realtime_peer(), realtime_user(), reload_config(), 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 981 of file chan_skinny.c.

struct io_context* io [static]

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

char linelabel[AST_MAX_EXTENSION] = "" [static]

Definition at line 976 of file chan_skinny.c.

Referenced by build_device().

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 991 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 1123 of file chan_skinny.c.

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

Definition at line 972 of file chan_skinny.c.

char mohsuggest[MAX_MUSICCLASS] = "" [static]

Definition at line 973 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 1114 of file chan_skinny.c.

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

Definition at line 1108 of file chan_skinny.c.

int mwiblink = 0 [static]

Definition at line 985 of file chan_skinny.c.

int nat = 0 [static]

Definition at line 978 of file chan_skinny.c.

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

Definition at line 1110 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 963 of file chan_skinny.c.

int ourport [static]

Definition at line 964 of file chan_skinny.c.

char parkinglot[AST_MAX_CONTEXT] = "" [static]

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

Referenced by build_peer().

struct sched_context* sched = NULL [static]

Definition at line 1103 of file chan_skinny.c.

int skinny_header_size = 12

Definition at line 953 of file chan_skinny.c.

struct ast_rtp_protocol skinny_rtp [static]

Definition at line 2486 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1281 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 959 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 968 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 748 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 792 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 778 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 787 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 811 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 770 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 801 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 757 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 738 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 764 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 796 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 807 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[]

Definition at line 575 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 984 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 987 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 Fri Jun 19 12:10:26 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7