Tue Mar 2 17:33:01 2010

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

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

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] = ""
struct 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 = AST_CLI_DEFINE(handle_skinny_set_debug_deprecated, "Enable/Disable Skinny debugging")
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
struct 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 []
struct 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)
#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
#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
#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
#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)
#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)
#define SKINNY_CFWD_BUSY   (1 << 1)
#define SKINNY_CFWD_NOANSWER   (1 << 2)
#define SKINNY_CONGESTION   7

Definition at line 1048 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5
#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
#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
#define SKINNY_LAMP_FLASH   4

Definition at line 1068 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1
#define SKINNY_LAMP_ON   2
#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
#define SKINNY_ONHOOK   2
#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
#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
#define SKINNY_SPEAKEROFF   2
#define SKINNY_SPEAKERON   1
#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
#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
#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

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

static void __unreg_module ( void   )  [static]

Definition at line 6493 of file chan_skinny.c.

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

Definition at line 6026 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, skinnysession::fd, skinnysession::lock, LOG_NOTICE, LOG_WARNING, s, skinnysession::sin, and skinny_session().

Referenced by reload_config().

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

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

implement the setvar config line

Definition at line 1526 of file chan_skinny.c.

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

Referenced by build_device().

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, read]

Definition at line 3010 of file chan_skinny.c.

References skinny_device::activeline, add_var(), skinny_device::addons, skinny_device::addr, 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, skinny_line::callgroup, skinny_line::callreturn, skinny_line::callwaiting, skinny_line::cancallforward, skinny_line::canreinvite, skinny_line::capability, skinny_device::capability, skinny_line::chanvars, skinny_line::cid_name, skinny_line::cid_num, skinny_line::context, skinny_speeddial::context, default_prefs, DEFAULT_SKINNY_PORT, skinny_device::earlyrtp, skinny_speeddial::exten, skinny_line::getforward, skinny_device::ha, skinny_line::hookstate, skinny_device::id, skinny_line::immediate, skinny_line::instance, skinny_speeddial::instance, skinny_speeddial::isHint, skinny_line::label, skinny_speeddial::label, skinny_line::language, skinny_device::lastlineinstance, ast_variable::lineno, skinny_device::lines, skinny_line::lock, skinny_addon::lock, skinny_speeddial::lock, LOG_ERROR, LOG_WARNING, skinny_line::mailbox, skinny_line::mohinterpret, skinny_line::mohsuggest, skinny_line::msgstate, mwi_event_cb(), skinny_line::mwi_event_sub, skinny_line::mwiblink, skinny_line::name, ast_variable::name, skinny_device::name, skinny_line::nat, ast_variable::next, skinny_line::onhooktime, skinny_line::parent, skinny_speeddial::parent, skinny_line::parkinglot, skinny_line::pickupgroup, skinny_line::prefs, skinny_device::prefs, skinny_line::regexten, S_OR, set_callforwards(), SKINNY_ONHOOK, skinny_device::speeddials, strsep(), skinny_line::threewaycalling, skinny_line::transfer, skinny_line::type, skinny_addon::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, skinny_device::version_id, and skinny_line::vmexten.

Referenced by reload_config().

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

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

Referenced by reload_config().

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

Referenced by skinny_indicate().

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

static void delete_devices ( void   )  [static]

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

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

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 5868 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(), skinnysession::fd, skinnysession::lock, and LOG_WARNING.

Referenced by accept_thread(), and skinny_session().

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

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, skinnysession::device, handle_time_date_req_message(), has_voicemail(), skinny_line::instance, skinny_device::lines, skinny_line::mwiblink, skinny_device::name, skinny_line::name, 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 6069 of file chan_skinny.c.

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

Referenced by restart_monitor().

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

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

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, read]

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, read]

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, read]

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, read]

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, skinnysession::device, LOG_WARNING, 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 3690 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().

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

static int get_input ( struct skinnysession s  )  [static]

Definition at line 5889 of file chan_skinny.c.

References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_poll, ast_verb, errno, skinnysession::fd, htolel, skinnysession::inbuf, letohl, skinnysession::lock, LOG_WARNING, and skinny_unregister().

Referenced by skinny_session().

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

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

Definition at line 5153 of file chan_skinny.c.

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

Referenced by handle_message().

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

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

Definition at line 4980 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, skinnysession::device, get_button_template(), htolel, skinny_speeddial::instance, skinny_line::instance, button_definition::instanceNumber, skinny_speeddial::isHint, skinny_device::lines, skinny_device::name, req_alloc(), skinny_device::speeddials, button_template_res_message::totalButtonCount, transmit_response(), and skinny_device::type.

Referenced by handle_message().

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

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

Definition at line 4240 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, skinny_subchannel::parent, set_callforwards(), SKINNY_DIALTONE, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), 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().

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

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

Definition at line 4860 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, skinnysession::device, letohl, skinny_device::lines, skinny_line::lock, LOG_WARNING, and SKINNY_MAX_CAPABILITIES.

Referenced by handle_message().

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

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

Definition at line 5229 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, skinnysession::device, 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, 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().

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

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

Definition at line 5687 of file chan_skinny.c.

Referenced by handle_message().

05688 {
05689    /* XXX umm...okay?  Why do I care? */
05690    return 1;
05691 }

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

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

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

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

Definition at line 4278 of file chan_skinny.c.

Referenced by handle_message().

04279 {
04280    /* no response necessary */
04281    return 1;
04282 }

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

Definition at line 4165 of file chan_skinny.c.

References skinnysession::device, do_housekeeping(), KEEP_ALIVE_ACK_MESSAGE, req_alloc(), and transmit_response().

Referenced by handle_message().

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

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

Definition at line 4284 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, skinnysession::device, find_subchannel_by_instance_reference(), ast_frame::frametype, skinny_data::keypad, letohl, keypad_button_message::lineInstance, LOG_WARNING, skinny_line::name, skinny_subchannel::owner, skinny_subchannel::parent, ast_frame::src, and ast_frame::subclass.

Referenced by handle_message().

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

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

Definition at line 4920 of file chan_skinny.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, skinny_req::data, skinnysession::device, 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(), and transmit_response().

Referenced by handle_message().

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

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

Definition at line 5699 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, skinnysession::device, 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, 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().

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

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

Definition at line 4696 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_subchannel::callid, skinny_req::data, skinnysession::device, 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, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, offhook_message::reference, SKINNY_CONNECTED, SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, skinny_ss(), start_rtp(), STIMULUS_LINE, 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().

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

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

Definition at line 4785 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, skinnysession::device, 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, SKINNY_CX_RECVONLY, SKINNY_ONHOOK, skinny_line::sub, skinny_line::transfer, transmit_callstate(), and skinny_subchannel::xferor.

Referenced by handle_message().

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

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

Definition at line 5162 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, skinnysession::device, 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, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, open_receive_channel_ack_message::status, status, transmit_response(), and media_qualifier::vad.

Referenced by handle_message().

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

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

Definition at line 5693 of file chan_skinny.c.

Referenced by handle_message().

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

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

Definition at line 4175 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, skinnysession::device, register_rej_message::errMsg, errno, skinnysession::fd, htolel, register_ack_message::keepAlive, skinny_req::len, letohl, skinnysession::lock, LOG_ERROR, LOG_WARNING, register_message::name, skinnysession::outbuf, 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, register_ack_message::secondaryKeepAlive, SKINNY_MAX_PACKET, skinny_register(), and transmit_response().

Referenced by handle_message().

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

static int handle_server_request_message ( struct skinny_req req,
struct skinnysession s 
) [static]
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, ast_cli_entry::command, complete_skinny_reset(), skinny_req::data, 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(), ast_cli_entry::usage, 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::parkinglot, skinny_line::pickupgroup, ast_cli_args::pos, skinny_line::prefs, print_codec_to_cli(), skinny_line::regcontext, skinny_line::regexten, S_COR, S_OR, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, skinny_line::threewaycalling, skinny_line::transfer, ast_cli_entry::usage, skinny_line::vmexten, and ast_cli_args::word.

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, "Parkinglot:       %s\n", S_OR(l->parkinglot, "<not set>"));
02951          ast_cli(a->fd, "Codecs:           ");
02952          ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->capability);
02953          ast_cli(a->fd, "%s\n", codec_buf);
02954          ast_cli(a->fd, "Codec Order:      (");
02955          print_codec_to_cli(a->fd, &l->prefs);
02956          ast_cli(a->fd, ")\n");
02957          ast_cli(a->fd, "\n");
02958       }
02959    }
02960    
02961    AST_LIST_UNLOCK(&devices);
02962    return CLI_SUCCESS;
02963 }

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

References ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, ast_test_flag, bindaddr, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, 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.

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

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

Definition at line 5312 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, skinnysession::device, 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, 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().

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

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

Definition at line 5279 of file chan_skinny.c.

References soft_key_definitions::count, skinny_req::data, soft_key_definitions::defaults, skinnysession::device, htolel, KEYDEF_ONHOOK, soft_key_definitions::mode, req_alloc(), SOFT_KEY_SET_RES_MESSAGE, 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_definition::softKeyTemplateIndex, soft_key_set_res_message::totalSoftKeySetCount, transmit_response(), and transmit_selectsoftkeys().

Referenced by handle_message().

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

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

Definition at line 4355 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, skinnysession::device, 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, skinny_device::name, skinny_line::name, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, 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().

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

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

Definition at line 4958 of file chan_skinny.c.

References ast_localtime(), ast_tvnow(), skinny_req::data, definetimedate_message::day, definetimedate_message::dayofweek, skinny_data::definetimedate, DEFINETIMEDATE_MESSAGE, skinnysession::device, definetimedate_message::hour, htolel, definetimedate_message::milliseconds, definetimedate_message::minute, definetimedate_message::month, req_alloc(), 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().

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

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4104 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::parent, skinny_subchannel::related, SKINNY_DIALTONE, skinny_hold(), skinny_new(), SKINNY_OFFHOOK, skinny_ss(), skinny_transfer(), 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().

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

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

Definition at line 5667 of file chan_skinny.c.

References skinny_unregister().

Referenced by handle_message().

05668 {
05669    return skinny_unregister(req, s);
05670 }

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

Definition at line 5128 of file chan_skinny.c.

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

Referenced by handle_message().

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

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

Referenced by do_housekeeping().

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 6388 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(), htolel, io_context_create(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), skinny_tech, and soft_key_template_definition::softKeyEvent.

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

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

Definition at line 2303 of file chan_skinny.c.

Referenced by build_device().

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.

Referenced by handle_skinny_show_line().

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

References __ourip, 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, bindaddr, build_device(), cleanup_stale_contexts(), 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.

Referenced by load_module().

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

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

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

Referenced by load_module(), and skinny_request().

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

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 3534 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, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, SKINNY_SILENCE, skinny_transfer(), start_rtp(), ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_selectsoftkeys(), and transmit_tone().

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

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

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

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

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6122 of file chan_skinny.c.

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

06123 {
06124    struct skinny_line *l;
06125    char *tmp;
06126 
06127    tmp = ast_strdupa(data);
06128 
06129    l = find_line_by_name(tmp);
06130 
06131    return get_devicestate(l);
06132 }

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

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

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

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, skinny_subchannel::lock, skinny_line::nat, skinny_subchannel::parent, skinny_subchannel::rtp, 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, 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 3455 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().

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

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

Definition at line 4032 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, skinny_subchannel::parent, S_OR, SKINNY_HOLD, SKINNY_LAMP_WINK, STIMULUS_LINE, 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().

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

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

Definition at line 3830 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, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::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(), ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_dialednumber(), transmit_displaypromptstatus(), and transmit_tone().

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

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

Definition at line 3929 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_subchannel::blindxfer, skinny_line::call_forward_all, skinny_line::call_forward_busy, skinny_line::callgroup, ast_channel::callgroup, skinny_subchannel::callid, 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, skinny_subchannel::cxmode, ast_channel::exten, skinny_line::exten, get_devicestate(), global_jbconf, skinny_line::instance, skinny_line::language, skinny_device::lastcallreference, skinny_device::lastlineinstance, skinny_subchannel::lock, LOG_WARNING, ast_variable::name, skinny_device::name, skinny_line::name, skinny_line::nat, skinny_subchannel::nat, ast_channel::nativeformats, ast_variable::next, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_subchannel::parent, skinny_line::parent, skinny_line::parkinglot, pbx_builtin_setvar_helper(), skinny_line::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, skinny_subchannel::related, ast_channel::rings, skinny_subchannel::rtp, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CX_INACTIVE, skinny_tech, skinny_line::sub, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, ast_channel::writeformat, and skinny_subchannel::xferor.

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

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

static void* skinny_newcall ( void *  data  )  [static]
static struct ast_frame * skinny_read ( struct ast_channel ast  )  [static, read]

Definition at line 3621 of file chan_skinny.c.

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

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

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

Definition at line 1759 of file chan_skinny.c.

References __ourip, 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, skinnysession::device, skinny_speeddial::exten, skinnysession::fd, 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, skinny_device::session, skinnysession::sin, 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, read]

Definition at line 5966 of file chan_skinny.c.

References ast_calloc, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), skinny_req::data, skinny_req::e, skinnysession::fd, skinnysession::inbuf, letohl, skinnysession::lock, LOG_ERROR, and SKINNY_MAX_PACKET.

Referenced by skinny_session().

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

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

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

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

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

Definition at line 3574 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_frame::frametype, ast_channel::nativeformats, skinny_subchannel::owner, ast_channel::readformat, skinny_subchannel::rtp, ast_frame::subclass, skinny_subchannel::vrtp, and ast_channel::writeformat.

Referenced by skinny_read().

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

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

Definition at line 3671 of file chan_skinny.c.

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

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

Definition at line 3676 of file chan_skinny.c.

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

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

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

Definition at line 5990 of file chan_skinny.c.

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

Referenced by accept_thread().

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

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(), 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 3300 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, skinny_device::name, skinny_line::name, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, set_callforwards(), SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_newcall(), SKINNY_OFFHOOK, SKINNY_REORDER, SKINNY_SILENCE, STIMULUS_FORWARDALL, 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().

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

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

Definition at line 3767 of file chan_skinny.c.

References ast_channel::_state, 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, option_debug, skinny_subchannel::owner, skinny_subchannel::related, skinny_subchannel::xferor, and ast_channel::zone.

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

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

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

Definition at line 4059 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_subchannel::parent, SKINNY_CONNECTED, SKINNY_LAMP_ON, SKINNY_OFFHOOK, STIMULUS_LINE, transmit_activatecallplane(), transmit_callstateonly(), transmit_connect(), and transmit_lamp_indication().

Referenced by handle_hold_button(), and handle_soft_key_event_message().

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

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, skinnysession::device, skinny_device::lines, skinny_device::name, skinny_line::name, skinny_device::registered, 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 3631 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.

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

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 3238 of file chan_skinny.c.

References ast_channel_set_fd(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_setnat(), ast_rtp_setqos(), bindaddr, skinny_subchannel::lock, skinny_line::nat, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_line::prefs, qos, skinny_subchannel::rtp, transmit_connect(), and skinny_subchannel::vrtp.

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

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

static void transmit_activatecallplane ( struct skinny_device d,
struct skinny_line l 
) [static]
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]
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]
static void transmit_connect ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
static void transmit_dialednumber ( struct skinny_device d,
const char *  text,
int  instance,
int  callid 
) [static]
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]
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]
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, skinnysession::fd, skinny_req::len, letohl, skinnysession::lock, LOG_VERBOSE, LOG_WARNING, skinnysession::outbuf, s, skinny_device::session, SKINNY_MAX_PACKET, and skinny_unregister().

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

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]
static void transmit_speaker_mode ( struct skinny_device d,
int  mode 
) [static]
static void transmit_stopmediatransmission ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
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 6423 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, delete_devices(), skinnysession::device, skinnysession::fd, free, skinny_device::lines, skinny_subchannel::lock, skinny_line::lock, monlock, skinny_line::mwi_event_sub, netlock, skinny_subchannel::owner, s, sched_context_destroy(), skinny_tech, and skinny_line::sub.

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

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

struct in_addr __ourip [static]

Definition at line 965 of file chan_skinny.c.

Referenced by reload_config(), and skinny_register().

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 __init_manager(), reload_config(), and rpt_exec().

int amaflags = 0 [static]

Definition at line 993 of file chan_skinny.c.

Definition at line 6493 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 962 of file chan_skinny.c.

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

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

struct ast_cli_entry cli_skinny_set_debug_deprecated = AST_CLI_DEFINE(handle_skinny_set_debug_deprecated, "Enable/Disable Skinny debugging") [static]

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

Definition at line 979 of file chan_skinny.c.

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.

Referenced by build_device(), and reload_config().

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.

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

struct hostent* hp
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.

Referenced by do_monitor(), restart_monitor(), and unload_module().

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.

Referenced by reload_config(), and unload_module().

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]

Referenced by reload_config(), and start_rtp().

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.

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.

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.

Definition at line 811 of file chan_skinny.c.

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.

Definition at line 575 of file chan_skinny.c.

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 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1