Sat Apr 26 2014 22:02:35

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_engine.h"
#include "asterisk/netsock2.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/manager.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  bksp_req_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_display_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  lines
struct  media_qualifier
struct  offhook_message
struct  onhook_message
struct  open_receive_channel_ack_message_ip4
struct  open_receive_channel_ack_message_ip6
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
struct  skinny_container
union  skinny_data
struct  skinny_device
struct  skinny_device_options
struct  skinny_line
struct  skinny_line_options
struct  skinny_req
struct  skinny_speeddial
struct  skinny_subchannel
struct  skinny_subline
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_ip4
struct  start_media_transmission_message_ip6
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 BKSP_REQ_MESSAGE   0x0119
#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 /* line or speeddial with hint only */
#define BT_CUST_LINESPEEDDIAL   0xB0 /* line or speeddial with/without hint */
#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 CALLSTATE2STR_BUFSIZE   15
#define CAPABILITIES_REQ_MESSAGE   0x009B
#define CAPABILITIES_RES_MESSAGE   0x0010
#define CDEV   ((struct skinny_device *)item)
#define CDEV_OPTS   ((struct skinny_device_options *)item)
#define CLEAR_DISPLAY_MESSAGE   0x009A
#define CLEAR_NOTIFY_MESSAGE   0x0115
#define CLEAR_PROMPT_MESSAGE   0x0113
#define CLINE   ((struct skinny_line *)item)
#define CLINE_OPTS   ((struct skinny_line_options *)item)
#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106
#define CONTROL2STR_BUFSIZE   100
#define DEFAULT_AUTH_LIMIT   50
#define DEFAULT_AUTH_TIMEOUT   30
#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 /* Digits After Dialing First Digit */
#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_SLACONNECTEDNOTACTIVE   12
#define KEYDEF_SLAHOLD   11
#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_BARGIN   0x43
#define SKINNY_BEEPBONK   0x33
#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_DEBUG(type, verb_level, text,...)
#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 /* Expansion module */
#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 /* Not found */
#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 /* Cisco ATA-186 */
#define SKINNY_DEVICE_CIPC   30016 /* Cisco IP Communicator */
#define SKINNY_DEVICE_NONE   0
#define SKINNY_DEVICE_OPTIONS
#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027 /* Analog gateway */
#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028 /* BRI gateway */
#define SKINNY_DEVICE_UNKNOWN   -1
#define SKINNY_DEVICECONTAINER   1
#define SKINNY_DIALTONE   0x21
#define SKINNY_HOLD   8
#define SKINNY_INCOMING   1
#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_LINE_OPTIONS
#define SKINNY_LINECONTAINER   2
#define SKINNY_MAX_CAPABILITIES   18
#define SKINNY_MAX_PACKET   2000
#define SKINNY_MICOFF   2
#define SKINNY_MICON   1
#define SKINNY_NOTONE   0x7F
#define SKINNY_OFFHOOK   1
#define SKINNY_ONHOOK   2
#define SKINNY_OUTGOING   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_SDCONTAINER   4
#define SKINNY_SILENCE   0x00 /* Note sure this is part of the protocol, remove? */
#define SKINNY_SPEAKEROFF   2
#define SKINNY_SPEAKERON   1
#define SKINNY_SUBLINECONTAINER   3
#define SKINNY_TRANSFER   10
#define SKINNY_ZIP   0x32
#define SKINNY_ZIPZIP   0x31
#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 SUBSTATE2STR_BUFSIZE   15
#define SUBSTATE_BUSY   6
#define SUBSTATE_CALLWAIT   9
#define SUBSTATE_CONGESTION   7
#define SUBSTATE_CONNECTED   5
#define SUBSTATE_DIALING   101
#define SUBSTATE_HOLD   8
#define SUBSTATE_OFFHOOK   1
#define SUBSTATE_ONHOOK   2
#define SUBSTATE_PROGRESS   12
#define SUBSTATE_RINGIN   4
#define SUBSTATE_RINGOUT   3
#define SUBSTATE_UNSET   0
#define TIME_DATE_REQ_MESSAGE   0x000D
#define TYPE_DEF_DEVICE   2
#define TYPE_DEF_LINE   4
#define TYPE_DEVICE   8
#define TYPE_GENERAL   1
#define TYPE_LINE   16
#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_callstate2str_threadbuf (void)
static void __init_control2str_threadbuf (void)
static void __init_device2str_threadbuf (void)
static void __init_substate2str_threadbuf (void)
static void __reg_module (void)
static void __unreg_module (void)
static char * _skinny_show_device (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
static char * _skinny_show_devices (int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
static char * _skinny_show_line (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
static char * _skinny_show_lines (int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
static void * accept_thread (void *ignore)
static void activatesub (struct skinny_subchannel *sub, int state)
static struct ast_variableadd_var (const char *buf, struct ast_variable *list)
static void cleanup_stale_contexts (char *new, char *old)
static int codec_ast2skinny (const struct ast_format *astcodec)
static struct ast_formatcodec_skinny2ast (enum skinny_codecs skinnycodec, struct ast_format *result)
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 struct skinny_deviceconfig_device (const char *dname, struct ast_variable *v)
static struct skinny_lineconfig_line (const char *lname, struct ast_variable *v)
static int config_load (void)
static void config_parse_variables (int type, void *item, struct ast_variable *vptr)
static char * control2str (int ind)
static void delete_devices (void)
static void destroy_rtp (struct skinny_subchannel *sub)
static void destroy_session (struct skinnysession *s)
static char * device2str (int type)
static void dialandactivatesub (struct skinny_subchannel *sub, char exten[AST_MAX_EXTENSION])
static void dumpsub (struct skinny_subchannel *sub, int forcehangup)
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 struct skinny_sublinefind_subline_by_callid (struct skinny_device *d, int callid)
static struct skinny_sublinefind_subline_by_name (const char *dest)
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_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_hold_button (struct skinny_subchannel *sub)
static int handle_ip_port_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keypad_button_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 char * handle_skinny_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_reset (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_stimulus_message (struct skinny_req *req, struct skinnysession *s)
static int handle_transfer_button (struct skinny_subchannel *sub)
static int load_module (void)
static int manager_skinny_show_device (struct mansession *s, const struct message *m)
static int manager_skinny_show_devices (struct mansession *s, const struct message *m)
 Show SKINNY devices in the manager API.
static int manager_skinny_show_line (struct mansession *s, const struct message *m)
static int manager_skinny_show_lines (struct mansession *s, const struct message *m)
 Show Skinny lines in the manager API.
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 push_callinfo (struct skinny_subline *subline, struct skinny_subchannel *sub)
static void register_exten (struct skinny_line *l)
static int reload (void)
static struct skinny_reqreq_alloc (size_t size, int response_message)
static void send_callinfo (struct skinny_subchannel *sub)
static int set_callforwards (struct skinny_line *l, const char *cfwd, int cfwdtype)
static void setsubstate (struct skinny_subchannel *sub, int state)
static int skinny_answer (struct ast_channel *ast)
static int skinny_autoanswer_cb (const void *data)
static int skinny_call (struct ast_channel *ast, const char *dest, int timeout)
static struct skinny_deviceskinny_device_alloc (void)
static struct skinny_deviceskinny_device_destroy (struct skinny_device *d)
static int skinny_devicestate (const char *data)
static void skinny_dialer (struct skinny_subchannel *sub, int timedout)
static int skinny_dialer_cb (const void *data)
static int skinny_extensionstate_cb (char *context, char *id, struct ast_state_cb_info *info, void *data)
static int skinny_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_glue_result skinny_get_rtp_peer (struct ast_channel *c, struct ast_rtp_instance **instance)
static enum ast_rtp_glue_result skinny_get_vrtp_peer (struct ast_channel *c, struct ast_rtp_instance **instance)
static int skinny_hangup (struct ast_channel *ast)
static int skinny_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct skinny_lineskinny_line_alloc (void)
static struct skinny_lineskinny_line_destroy (struct skinny_line *l)
static struct ast_channelskinny_new (struct skinny_line *l, struct skinny_subline *subline, int state, const char *linkedid, int direction)
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 int skinny_reload (void)
static struct skinny_reqskinny_req_parse (struct skinnysession *s)
static struct ast_channelskinny_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause)
static struct ast_frameskinny_rtp_read (struct skinny_subchannel *sub)
static int skinny_sched_add (int when, ast_sched_cb callback, struct skinny_subchannel *sub)
static int skinny_sched_del (int sched_id, 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_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active)
static int skinny_transfer (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 char * substate2str (int ind)
static void transmit_activatecallplane (struct skinny_device *d, struct skinny_line *l)
static void transmit_backspace (struct skinny_device *d, int instance, unsigned callid)
static void transmit_callinfo (struct skinny_device *d, int instance, int callid, char *fromname, char *fromnum, char *toname, char *tonum, int calldirection)
static void transmit_callstate (struct skinny_device *d, int buttonInstance, unsigned callid, int state)
static void transmit_capabilitiesreq (struct skinny_device *d)
static void transmit_cfwdstate (struct skinny_device *d, struct skinny_line *l)
static void transmit_clear_display_message (struct skinny_device *d, int instance, int reference)
static void transmit_clearpromptmessage (struct skinny_device *d, int instance, int callid)
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_definetimedate (struct skinny_device *d)
static void transmit_dialednumber (struct skinny_device *d, const char *text, int instance, int callid)
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_keepaliveack (struct skinny_device *d)
static void transmit_lamp_indication (struct skinny_device *d, int stimulus, int instance, int indication)
static void transmit_linestatres (struct skinny_device *d, int instance)
static void transmit_microphone_mode (struct skinny_device *d, int mode)
static void transmit_registerack (struct skinny_device *d)
static void transmit_registerrej (struct skinnysession *s)
static void transmit_reset (struct skinny_device *d, int fullrestart)
static void transmit_response (struct skinny_device *d, struct skinny_req *req)
static int transmit_response_bysession (struct skinnysession *s, 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_serverres (struct skinny_device *d)
static void transmit_softkeysetres (struct skinny_device *d)
static void transmit_softkeytemplateres (struct skinny_device *d)
static void transmit_speaker_mode (struct skinny_device *d, int mode)
static void transmit_speeddialstatres (struct skinny_device *d, struct skinny_speeddial *sd)
static void transmit_start_tone (struct skinny_device *d, int tone, int instance, int reference)
static void transmit_startmediatransmission (struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, struct ast_format_list fmt)
static void transmit_stop_tone (struct skinny_device *d, int instance, int reference)
static void transmit_stopmediatransmission (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_versionres (struct skinny_device *d)
static int unload_module (void)
static void unregister_exten (struct skinny_line *l)
static void update_connectedline (struct skinny_subchannel *sub, const void *data, size_t datalen)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static struct in_addr __ourip
static pthread_t accept_t
static struct ast_hostent ahp
static struct ast_module_infoast_module_info = &__mod_info
static int auth_limit = DEFAULT_AUTH_LIMIT
static int auth_timeout = DEFAULT_AUTH_TIMEOUT
static struct sockaddr_in bindaddr
static int callnums = 1
static struct ast_threadstorage callstate2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_callstate2str_threadbuf , .custom_init = NULL , }
static struct ast_cli_entry cli_skinny []
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 char date_format [6] = "D-M-Y"
static struct ast_format_capdefault_cap
static struct
skinny_device_options
default_device = &default_device_struct
static struct skinny_device_options default_device_struct
static struct ast_jb_conf default_jbconf
static struct skinny_line_optionsdefault_line = &default_line_struct
static struct skinny_line_options default_line_struct
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 struct devices devices
static int firstdigittimeout = 16000
static int gendigittimeout = 8000
static struct ast_jb_conf global_jbconf
static struct hostent * hp
static int keep_alive = 120
static struct lines lines
static int matchdigittimeout = 3000
static ast_mutex_t netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static char ourhost [256]
static int ourport
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 struct ast_sched_contextsched = NULL
static struct sessions sessions
static int skinny_header_size = 12
static struct ast_rtp_glue skinny_rtp_glue
static struct ast_channel_tech skinny_tech
static int skinnyreload = 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_SLAconnectednotactive []
static const uint8_t soft_key_default_SLAhold []
static const uint8_t soft_key_default_unknown []
static struct
soft_key_template_definition 
soft_key_template_default []
static struct ast_threadstorage substate2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_substate2str_threadbuf , .custom_init = NULL , }
static const char tdesc [] = "Skinny Client Control Protocol (Skinny)"
static int unauth_sessions = 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 1036 of file chan_skinny.c.

Referenced by transmit_activatecallplane().

#define ALARM_MESSAGE   0x0020

Definition at line 358 of file chan_skinny.c.

Referenced by handle_message().

#define BKSP_REQ_MESSAGE   0x0119

Definition at line 671 of file chan_skinny.c.

Referenced by transmit_backspace().

Definition at line 586 of file chan_skinny.c.

Definition at line 589 of file chan_skinny.c.

Referenced by get_button_template().

Definition at line 590 of file chan_skinny.c.

Definition at line 588 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1 /* line or speeddial with hint only */

Definition at line 597 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0 /* line or speeddial with/without hint */

Definition at line 596 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

Definition at line 583 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 587 of file chan_skinny.c.

Definition at line 580 of file chan_skinny.c.

Referenced by get_button_template().

Definition at line 581 of file chan_skinny.c.

Definition at line 582 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 578 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 584 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 591 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 576 of file chan_skinny.c.

Referenced by get_button_template().

Definition at line 579 of file chan_skinny.c.

Referenced by get_button_template().

Definition at line 585 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 354 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 546 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 484 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 1007 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CALLSTATE2STR_BUFSIZE   15

Definition at line 269 of file chan_skinny.c.

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 622 of file chan_skinny.c.

Referenced by transmit_capabilitiesreq().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 326 of file chan_skinny.c.

Referenced by handle_message().

#define CDEV   ((struct skinny_device *)item)

Definition at line 7110 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CDEV_OPTS   ((struct skinny_device_options *)item)

Definition at line 7109 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 617 of file chan_skinny.c.

Referenced by transmit_clear_display_message().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 616 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 1024 of file chan_skinny.c.

Referenced by transmit_clearpromptmessage().

#define CLINE   ((struct skinny_line *)item)

Definition at line 7108 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLINE_OPTS   ((struct skinny_line_options *)item)

Definition at line 7107 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 658 of file chan_skinny.c.

Referenced by transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 263 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_AUTH_LIMIT   50

Definition at line 181 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_AUTH_TIMEOUT   30

Definition at line 180 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 178 of file chan_skinny.c.

Referenced by config_load().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 177 of file chan_skinny.c.

Referenced by config_device(), and config_load().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 533 of file chan_skinny.c.

Referenced by transmit_definetimedate().

#define DEVICE2STR_BUFSIZE   15

Definition at line 260 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 1041 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 1030 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 1015 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 611 of file chan_skinny.c.

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 302 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 506 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 392 of file chan_skinny.c.

Referenced by handle_message().

#define htoles (   x)    bswap_16(x)

Definition at line 213 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define IP_PORT_MESSAGE   0x0002

Definition at line 292 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 645 of file chan_skinny.c.

Referenced by transmit_keepaliveack().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 275 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

Definition at line 678 of file chan_skinny.c.

Referenced by setsubstate(), and skinny_extensionstate_cb().

#define KEYDEF_CONNWITHCONF   7

Definition at line 684 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 682 of file chan_skinny.c.

#define KEYDEF_DADFD   6 /* Digits After Dialing First Digit */

Definition at line 683 of file chan_skinny.c.

Referenced by handle_keypad_button_message().

#define KEYDEF_OFFHOOK   4

Definition at line 681 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and setsubstate().

#define KEYDEF_OFFHOOKWITHFEAT   9

Definition at line 686 of file chan_skinny.c.

#define KEYDEF_ONHOLD   2

Definition at line 679 of file chan_skinny.c.

Referenced by setsubstate().

#define KEYDEF_ONHOOK   0
#define KEYDEF_RINGIN   3

Definition at line 680 of file chan_skinny.c.

Referenced by setsubstate().

#define KEYDEF_RINGOUT   8

Definition at line 685 of file chan_skinny.c.

Referenced by setsubstate().

Definition at line 689 of file chan_skinny.c.

Referenced by setsubstate(), and skinny_extensionstate_cb().

#define KEYDEF_SLAHOLD   11

Definition at line 688 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define KEYDEF_UNKNOWN   10

Definition at line 687 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 294 of file chan_skinny.c.

Referenced by handle_message().

#define letohs (   x)    bswap_16(x)

Definition at line 211 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 525 of file chan_skinny.c.

Referenced by transmit_linestatres().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 348 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 314 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 320 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 366 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 647 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 395 of file chan_skinny.c.

Referenced by transmit_registerack().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 393 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 278 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 624 of file chan_skinny.c.

Referenced by transmit_registerrej().

#define RESET_MESSAGE   0x009F

Definition at line 640 of file chan_skinny.c.

Referenced by transmit_reset().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 999 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 356 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 629 of file chan_skinny.c.

Referenced by transmit_serverres().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 427 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 440 of file chan_skinny.c.

Referenced by transmit_microphone_mode().

#define SET_RINGER_MESSAGE   0x0085

Definition at line 419 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 434 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1194 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_BARGIN   0x43

Definition at line 1200 of file chan_skinny.c.

#define SKINNY_BEEPBONK   0x33

Definition at line 1199 of file chan_skinny.c.

#define SKINNY_BUSY   6

Definition at line 1178 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1193 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1185 of file chan_skinny.c.

Referenced by setsubstate(), and skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1181 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1196 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_CONGESTION   7

Definition at line 1179 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_CONNECTED   5

Definition at line 1177 of file chan_skinny.c.

Referenced by setsubstate(), skinny_autoanswer_cb(), and skinny_extensionstate_cb().

#define SKINNY_CX_CONF   3

Definition at line 1222 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 1223 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1225 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1224 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1220 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_CX_SENDONLY   0

Definition at line 1219 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1221 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEBUG (   type,
  verb_level,
  text,
  ... 
)

Definition at line 155 of file chan_skinny.c.

Referenced by accept_thread(), activatesub(), destroy_rtp(), dialandactivatesub(), dumpsub(), handle_button_template_req_message(), handle_capabilities_res_message(), handle_keypad_button_message(), handle_message(), handle_open_receive_channel_ack_message(), handle_soft_key_event_message(), handle_stimulus_message(), setsubstate(), skinny_answer(), skinny_call(), skinny_dialer(), skinny_dialer_cb(), skinny_extensionstate_cb(), skinny_get_rtp_peer(), skinny_hangup(), skinny_indicate(), skinny_new(), skinny_sched_add(), skinny_sched_del(), skinny_set_rtp_peer(), skinny_transfer(), transmit_activatecallplane(), transmit_backspace(), transmit_callinfo(), transmit_callstate(), transmit_capabilitiesreq(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_keepaliveack(), transmit_lamp_indication(), transmit_linestatres(), transmit_microphone_mode(), transmit_registerack(), transmit_registerrej(), transmit_reset(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speaker_mode(), transmit_speeddialstatres(), transmit_start_tone(), transmit_startmediatransmission(), transmit_stop_tone(), transmit_stopmediatransmission(), transmit_versionres(), and update_connectedline().

#define SKINNY_DEVICE_12   4

Definition at line 1133 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1132 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1131 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 1130 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1134 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1160 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1156 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1149 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1135 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1144 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1159 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124 /* Expansion module */

Definition at line 1142 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1157 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1148 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1147 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1138 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1163 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1151 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1137 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1140 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1146 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1152 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1153 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1136 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1162 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1145 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404 /* Not found */

Definition at line 1150 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1154 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1158 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1141 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1155 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1143 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12 /* Cisco ATA-186 */

Definition at line 1139 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016 /* Cisco IP Communicator */

Definition at line 1161 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 1129 of file chan_skinny.c.

Referenced by device2str().

Definition at line 1426 of file chan_skinny.c.

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027 /* Analog gateway */

Definition at line 1164 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028 /* BRI gateway */

Definition at line 1165 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 1128 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICECONTAINER   1

Definition at line 1409 of file chan_skinny.c.

#define SKINNY_DIALTONE   0x21

Definition at line 1192 of file chan_skinny.c.

Referenced by dialandactivatesub(), handle_soft_key_event_message(), and setsubstate().

#define SKINNY_HOLD   8

Definition at line 1180 of file chan_skinny.c.

Referenced by setsubstate(), and skinny_extensionstate_cb().

#define SKINNY_INVALID   14

Definition at line 1186 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 1207 of file chan_skinny.c.

Referenced by mwi_event_cb(), setsubstate(), and skinny_extensionstate_cb().

#define SKINNY_LAMP_FLASH   4

Definition at line 1206 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_WINK   3

Definition at line 1205 of file chan_skinny.c.

Referenced by setsubstate(), and skinny_extensionstate_cb().

Definition at line 1293 of file chan_skinny.c.

#define SKINNY_LINECONTAINER   2

Definition at line 1410 of file chan_skinny.c.

Referenced by config_line().

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 336 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   2000

Definition at line 179 of file chan_skinny.c.

Referenced by get_input(), skinny_req_parse(), and transmit_response_bysession().

#define SKINNY_MICOFF   2

Definition at line 1171 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_MICON   1

Definition at line 1170 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1201 of file chan_skinny.c.

#define SKINNY_PARK   11

Definition at line 1183 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1184 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_REORDER   0x25

Definition at line 1195 of file chan_skinny.c.

Referenced by setsubstate(), skinny_dialer(), and skinny_newcall().

#define SKINNY_RING_FEATURE   4

Definition at line 1212 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1210 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_RING_OUTSIDE   3

Definition at line 1211 of file chan_skinny.c.

#define SKINNY_RINGIN   4

Definition at line 1176 of file chan_skinny.c.

Referenced by setsubstate(), and skinny_extensionstate_cb().

#define SKINNY_RINGOUT   3

Definition at line 1175 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_SDCONTAINER   4

Definition at line 1412 of file chan_skinny.c.

Referenced by config_parse_variables(), and skinny_extensionstate_cb().

#define SKINNY_SILENCE   0x00 /* Note sure this is part of the protocol, remove? */

Definition at line 1191 of file chan_skinny.c.

#define SKINNY_SPEAKEROFF   2

Definition at line 1168 of file chan_skinny.c.

Referenced by dumpsub(), and handle_callforward_button().

#define SKINNY_SUBLINECONTAINER   3

Definition at line 1411 of file chan_skinny.c.

Referenced by config_parse_variables(), and skinny_extensionstate_cb().

#define SKINNY_TRANSFER   10

Definition at line 1182 of file chan_skinny.c.

#define SKINNY_ZIP   0x32

Definition at line 1198 of file chan_skinny.c.

Referenced by setsubstate().

#define SKINNY_ZIPZIP   0x31

Definition at line 1197 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 383 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 381 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 984 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 391 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 665 of file chan_skinny.c.

Referenced by transmit_softkeytemplateres().

#define SOFTKEY_ANSWER   0x0B

Definition at line 702 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 699 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 696 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 697 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 698 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 704 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 710 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 700 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 709 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 694 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 711 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 703 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 706 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 707 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 693 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 691 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 705 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 708 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 692 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 701 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 695 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 343 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 518 of file chan_skinny.c.

Referenced by transmit_speeddialstatres().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 445 of file chan_skinny.c.

Referenced by transmit_startmediatransmission().

#define START_TONE_MESSAGE   0x0082

Definition at line 404 of file chan_skinny.c.

Referenced by transmit_start_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 568 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 571 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 572 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 570 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 565 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 569 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 562 of file chan_skinny.c.

Referenced by dialandactivatesub(), and handle_stimulus_message().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 563 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 564 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 560 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_MESSAGE   0x0005

Definition at line 307 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 573 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 558 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 559 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 561 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 567 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and mwi_event_cb().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 477 of file chan_skinny.c.

Referenced by transmit_stopmediatransmission().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 412 of file chan_skinny.c.

Referenced by transmit_stop_tone().

#define SUBSTATE2STR_BUFSIZE   15

Definition at line 266 of file chan_skinny.c.

Referenced by substate2str().

#define SUBSTATE_BUSY   6

Definition at line 1258 of file chan_skinny.c.

Referenced by setsubstate(), skinny_indicate(), and substate2str().

#define SUBSTATE_CALLWAIT   9

Definition at line 1261 of file chan_skinny.c.

Referenced by activatesub(), dumpsub(), setsubstate(), and substate2str().

#define SUBSTATE_CONGESTION   7

Definition at line 1259 of file chan_skinny.c.

Referenced by setsubstate(), skinny_indicate(), and substate2str().

#define SUBSTATE_DIALING   101

Definition at line 1263 of file chan_skinny.c.

Referenced by dialandactivatesub(), setsubstate(), and substate2str().

#define SUBSTATE_ONHOOK   2

Definition at line 1254 of file chan_skinny.c.

Referenced by activatesub(), dumpsub(), setsubstate(), and substate2str().

#define SUBSTATE_PROGRESS   12

Definition at line 1262 of file chan_skinny.c.

Referenced by setsubstate(), skinny_indicate(), and substate2str().

#define SUBSTATE_RINGIN   4

Definition at line 1256 of file chan_skinny.c.

Referenced by activatesub(), dumpsub(), setsubstate(), skinny_call(), and substate2str().

#define SUBSTATE_RINGOUT   3

Definition at line 1255 of file chan_skinny.c.

Referenced by setsubstate(), skinny_indicate(), and substate2str().

#define SUBSTATE_UNSET   0

Definition at line 1252 of file chan_skinny.c.

Referenced by handle_stimulus_message(), skinny_request(), and substate2str().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 353 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_DEF_DEVICE   2

Definition at line 7102 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEF_LINE   4

Definition at line 7103 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEVICE   8

Definition at line 7104 of file chan_skinny.c.

Referenced by config_device(), and config_parse_variables().

#define TYPE_GENERAL   1

Definition at line 7101 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_LINE   16

Definition at line 7105 of file chan_skinny.c.

Referenced by config_line(), and config_parse_variables().

#define UNREGISTER_MESSAGE   0x0027

Definition at line 390 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 355 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

Definition at line 606 of file chan_skinny.c.

Referenced by transmit_versionres().


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

                   {
   SKINNY_CODEC_ALAW = 2,
   SKINNY_CODEC_ULAW = 4,
   SKINNY_CODEC_G723_1 = 9,
   SKINNY_CODEC_G729A = 12,
   SKINNY_CODEC_G726_32 = 82, /* XXX Which packing order does this translate to? */
   SKINNY_CODEC_H261 = 100,
   SKINNY_CODEC_H263 = 101
};

Function Documentation

static void __init_callstate2str_threadbuf ( void  ) [static]

Definition at line 268 of file chan_skinny.c.

{
static void __init_control2str_threadbuf ( void  ) [static]

Definition at line 262 of file chan_skinny.c.

{
static void __init_device2str_threadbuf ( void  ) [static]

Definition at line 259 of file chan_skinny.c.

{
static void __init_substate2str_threadbuf ( void  ) [static]

Definition at line 265 of file chan_skinny.c.

{
static void __reg_module ( void  ) [static]

Definition at line 8085 of file chan_skinny.c.

static void __unreg_module ( void  ) [static]

Definition at line 8085 of file chan_skinny.c.

static char* _skinny_show_device ( int  type,
int  fd,
struct mansession s,
const struct message m,
int  argc,
const char *  argv[] 
) [static]

Definition at line 3715 of file chan_skinny.c.

References skinny_device::addons, ast_cli(), ast_getformatname_multiple(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, astman_append(), skinny_device::cap, CLI_SHOWUSAGE, CLI_SUCCESS, skinny_device::confcap, device2str(), skinny_speeddial::exten, skinny_speeddial::isHint, skinny_speeddial::label, skinny_device::lines, S_OR, skinny_device::session, skinnysession::sin, skinny_device::speeddials, and skinny_addon::type.

Referenced by handle_skinny_show_device(), and manager_skinny_show_device().

{
   struct skinny_device *d;
   struct skinny_line *l;
   struct skinny_speeddial *sd;
   struct skinny_addon *sa;
   char codec_buf[512];

   if (argc < 4) {
      return CLI_SHOWUSAGE;
   }

   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, d, list) {
      if (!strcasecmp(argv[3], d->id) || !strcasecmp(argv[3], d->name)) {
         int numlines = 0, numaddons = 0, numspeeddials = 0;

         AST_LIST_TRAVERSE(&d->lines, l, list){
            numlines++;
         }

         AST_LIST_TRAVERSE(&d->addons, sa, list) {
            numaddons++;
         }

         AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
            numspeeddials++;
         }

         if (type == 0) { /* CLI */
            ast_cli(fd, "Name:        %s\n", d->name);
            ast_cli(fd, "Id:          %s\n", d->id);
            ast_cli(fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
            ast_cli(fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
            ast_cli(fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
            ast_cli(fd, "Device Type: %s\n", device2str(d->type));
            ast_cli(fd, "Conf Codecs:");
            ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->confcap);
            ast_cli(fd, "%s\n", codec_buf);
            ast_cli(fd, "Neg Codecs: ");
            ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->cap);
            ast_cli(fd, "%s\n", codec_buf);
            ast_cli(fd, "Registered:  %s\n", (d->session ? "Yes" : "No"));
            ast_cli(fd, "Lines:       %d\n", numlines);
            AST_LIST_TRAVERSE(&d->lines, l, list) {
               ast_cli(fd, "  %s (%s)\n", l->name, l->label);
            }
            AST_LIST_TRAVERSE(&d->addons, sa, list) {
               numaddons++;
            }  
            ast_cli(fd, "Addons:      %d\n", numaddons);
            AST_LIST_TRAVERSE(&d->addons, sa, list) {
               ast_cli(fd, "  %s\n", sa->type);
            }
            AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
               numspeeddials++;
            }
            ast_cli(fd, "Speeddials:  %d\n", numspeeddials);
            AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
               ast_cli(fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
            }
         } else { /* manager */
            astman_append(s, "Channeltype: SKINNY\r\n");
            astman_append(s, "ObjectName: %s\r\n", d->name);
            astman_append(s, "ChannelObjectType: device\r\n");
            astman_append(s, "Id: %s\r\n", d->id);
            astman_append(s, "version: %s\r\n", S_OR(d->version_id, "Unknown"));
            astman_append(s, "Ipaddress: %s\r\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
            astman_append(s, "Port: %d\r\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
            astman_append(s, "DeviceType: %s\r\n", device2str(d->type));
            astman_append(s, "Codecs: ");
            ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->confcap);
            astman_append(s, "%s\r\n", codec_buf);
            astman_append(s, "CodecOrder: ");
            ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->cap);
            astman_append(s, "%s\r\n", codec_buf);
            astman_append(s, "Devicestatus: %s\r\n", (d->session?"registered":"unregistered"));
            astman_append(s, "NumberOfLines: %d\r\n", numlines);
            AST_LIST_TRAVERSE(&d->lines, l, list) {
               astman_append(s, "Line: %s (%s)\r\n", l->name, l->label);
            }
            astman_append(s, "NumberOfAddons: %d\r\n", numaddons);
            AST_LIST_TRAVERSE(&d->addons, sa, list) {
               astman_append(s, "Addon: %s\r\n", sa->type);
            }
            astman_append(s, "NumberOfSpeeddials: %d\r\n", numspeeddials);
            AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
               astman_append(s, "Speeddial: %s (%s) ishint: %d\r\n", sd->exten, sd->label, sd->isHint);
            }
         }
      }
   }
   AST_LIST_UNLOCK(&devices);
   return CLI_SUCCESS;
}
static char* _skinny_show_devices ( int  fd,
int *  total,
struct mansession s,
const struct message m,
int  argc,
const char *  argv[] 
) [static]

Definition at line 3604 of file chan_skinny.c.

References ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), astman_append(), astman_get_header(), CLI_SHOWUSAGE, CLI_SUCCESS, device2str(), id, skinny_device::lines, skinny_device::session, and skinnysession::sin.

Referenced by handle_skinny_show_devices(), and manager_skinny_show_devices().

{
   struct skinny_device *d;
   struct skinny_line *l;
   const char *id;
   char idtext[256] = "";
   int total_devices = 0;

   if (s) { /* Manager - get ActionID */
      id = astman_get_header(m, "ActionID");
      if (!ast_strlen_zero(id))
         snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
   }

   switch (argc) {
   case 3:
      break;
   default:
      return CLI_SHOWUSAGE;
   }

   if (!s) {
      ast_cli(fd, "Name                 DeviceId         IP              Type            R NL\n");
      ast_cli(fd, "-------------------- ---------------- --------------- --------------- - --\n");
   }

   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, d, list) {
      int numlines = 0;
      total_devices++;
      AST_LIST_TRAVERSE(&d->lines, l, list) {
         numlines++;
      }
      if (!s) {
         ast_cli(fd, "%-20s %-16s %-15s %-15s %c %2d\n",
            d->name,
            d->id,
            d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
            device2str(d->type),
            d->session?'Y':'N',
            numlines);
      } else {
         astman_append(s,
            "Event: DeviceEntry\r\n%s"
            "Channeltype: SKINNY\r\n"
            "ObjectName: %s\r\n"
            "ChannelObjectType: device\r\n"
            "DeviceId: %s\r\n"
            "IPaddress: %s\r\n"
            "Type: %s\r\n"
            "Devicestatus: %s\r\n"
            "NumberOfLines: %d\r\n",
            idtext,
            d->name,
            d->id,
            d->session?ast_inet_ntoa(d->session->sin.sin_addr):"-none-",
            device2str(d->type),
            d->session?"registered":"unregistered",
            numlines);
      }
   }
   AST_LIST_UNLOCK(&devices);

   if (total)
      *total = total_devices;
   
   return CLI_SUCCESS;
}
static char* _skinny_show_line ( int  type,
int  fd,
struct mansession s,
const struct message m,
int  argc,
const char *  argv[] 
) [static]

Definition at line 3972 of file chan_skinny.c.

References ast_callerid_merge(), ast_cdr_flags2str(), ast_cli(), ast_codec_pref_index(), ast_getformatname(), ast_getformatname_multiple(), AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_print_group(), astman_append(), skinny_line::cap, CLI_SHOWUSAGE, CLI_SUCCESS, skinny_line::confcap, skinny_subline::context, skinny_subline::exten, ast_format::id, skinny_device::lines, skinny_subline::name, print_codec_to_cli(), S_COR, S_OR, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, skinny_subchannel::subline, and skinny_line::sublines.

Referenced by handle_skinny_show_line(), and manager_skinny_show_line().

{
   struct skinny_device *d;
   struct skinny_line *l;
   struct skinny_subline *subline;
   struct ast_codec_pref *pref;
   int x = 0;
   char codec_buf[512];
   char group_buf[256];
   char cbuf[256];

   switch (argc) {
   case 4:
      break;
   case 6:
      break;
   default:
      return CLI_SHOWUSAGE;
   }

   AST_LIST_LOCK(&devices);

   /* Show all lines matching the one supplied */
   AST_LIST_TRAVERSE(&devices, d, list) {
      if (argc == 6 && (strcasecmp(argv[5], d->id) && strcasecmp(argv[5], d->name))) {
         continue;
      }
      AST_LIST_TRAVERSE(&d->lines, l, list) {
         if (strcasecmp(argv[3], l->name)) {
            continue;
         }
         if (type == 0) { /* CLI */
            ast_cli(fd, "Line:             %s\n", l->name);
            ast_cli(fd, "On Device:        %s\n", d->name);
            ast_cli(fd, "Line Label:       %s\n", l->label);
            ast_cli(fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
            ast_cli(fd, "Context:          %s\n", l->context);
            ast_cli(fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
            ast_cli(fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
            ast_cli(fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
            ast_cli(fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
            ast_cli(fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
            ast_cli(fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
            ast_cli(fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
            ast_cli(fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
            ast_cli(fd, "CFwdAll:          %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
            ast_cli(fd, "CFwdBusy:         %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
            ast_cli(fd, "CFwdNoAnswer:     %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
            ast_cli(fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
            ast_cli(fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
            ast_cli(fd, "MWIblink:         %d\n", l->mwiblink);
            ast_cli(fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
            ast_cli(fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
            ast_cli(fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
            ast_cli(fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
            ast_cli(fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
            ast_cli(fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
            ast_cli(fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
            ast_cli(fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
            ast_cli(fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
            ast_cli(fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
            ast_cli(fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
            ast_cli(fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
            ast_cli(fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
            ast_cli(fd, "Group:            %d\n", l->group);
            ast_cli(fd, "Parkinglot:       %s\n", S_OR(l->parkinglot, "<not set>"));
            ast_cli(fd, "Conf Codecs:      ");
            ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap);
            ast_cli(fd, "%s\n", codec_buf);
            ast_cli(fd, "Neg Codecs:       ");
            ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->cap);
            ast_cli(fd, "%s\n", codec_buf);
            ast_cli(fd, "Codec Order:      (");
            print_codec_to_cli(fd, &l->prefs);
            ast_cli(fd, ")\n");
            if  (AST_LIST_FIRST(&l->sublines)) {
               ast_cli(fd, "Sublines:\n");
               AST_LIST_TRAVERSE(&l->sublines, subline, list) {
                  ast_cli(fd, "     %s, %s@%s\n", subline->name, subline->exten, subline->context);
               }
            }
            ast_cli(fd, "\n");
         } else { /* manager */
            astman_append(s, "Channeltype: SKINNY\r\n");
            astman_append(s, "ObjectName: %s\r\n", l->name);
            astman_append(s, "ChannelObjectType: line\r\n");
            astman_append(s, "Device: %s\r\n", d->name);
            astman_append(s, "LineLabel: %s\r\n", l->label);
            astman_append(s, "Extension: %s\r\n", S_OR(l->exten, "<not set>"));
            astman_append(s, "Context: %s\r\n", l->context);
            astman_append(s, "CallGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
            astman_append(s, "PickupGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
            astman_append(s, "Language: %s\r\n", S_OR(l->language, "<not set>"));
            astman_append(s, "Accountcode: %s\r\n", S_OR(l->accountcode, "<not set>"));
            astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(l->amaflags));
            astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), l->cid_name, l->cid_num, ""));
            astman_append(s, "HideCallerId: %s\r\n", (l->hidecallerid ? "Yes" : "No"));
            astman_append(s, "CFwdAll: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
            astman_append(s, "CFwdBusy: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
            astman_append(s, "CFwdNoAnswer: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
            astman_append(s, "VoicemailBox: %s\r\n", S_OR(l->mailbox, "<not set>"));
            astman_append(s, "VoicemailNumber: %s\r\n", S_OR(l->vmexten, "<not set>"));
            astman_append(s, "MWIblink: %d\r\n", l->mwiblink);
            astman_append(s, "RegExtension: %s\r\n", S_OR(l->regexten, "<not set>"));
            astman_append(s, "Regcontext: %s\r\n", S_OR(l->regcontext, "<not set>"));
            astman_append(s, "MoHInterpret: %s\r\n", S_OR(l->mohinterpret, "<not set>"));
            astman_append(s, "MoHSuggest: %s\r\n", S_OR(l->mohsuggest, "<not set>"));
            astman_append(s, "LastDialedNr: %s\r\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
            astman_append(s, "LastCallerID: %s\r\n", S_OR(l->lastcallerid, "<not set>"));
            astman_append(s, "Transfer: %s\r\n", (l->transfer ? "Yes" : "No"));
            astman_append(s, "Callwaiting: %s\r\n", (l->callwaiting ? "Yes" : "No"));
            astman_append(s, "3WayCalling: %s\r\n", (l->threewaycalling ? "Yes" : "No"));
            astman_append(s, "CanForward: %s\r\n", (l->cancallforward ? "Yes" : "No"));
            astman_append(s, "DoNotDisturb: %s\r\n", (l->dnd ? "Yes" : "No"));
            astman_append(s, "NAT: %s\r\n", (l->nat ? "Yes" : "No"));
            astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No"));
            astman_append(s, "Group: %d\r\n", l->group);
            astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>"));
            ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcap);
            astman_append(s, "Codecs: %s\r\n", codec_buf);
            astman_append(s, "CodecOrder: ");
            pref = &l->prefs;
            for(x = 0; x < 32 ; x++) {
               struct ast_format tmpfmt;
               ast_codec_pref_index(pref, x, &tmpfmt);
               if (!tmpfmt.id)
                  break;
               astman_append(s, "%s", ast_getformatname(&tmpfmt));
               if (x < 31 && ast_codec_pref_index(pref, x+1, &tmpfmt))
                  astman_append(s, ",");
            }
            astman_append(s, "\r\n");
         }
      }
   }
   
   AST_LIST_UNLOCK(&devices);
   return CLI_SUCCESS;
}
static char* _skinny_show_lines ( int  fd,
int *  total,
struct mansession s,
const struct message m,
int  argc,
const char *  argv[] 
) [static]

Definition at line 3848 of file chan_skinny.c.

References skinny_line::activesub, ast_bridged_channel(), ast_channel_name(), ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), astman_append(), astman_get_header(), CLI_SHOWUSAGE, CLI_SUCCESS, skinny_line::device, id, skinny_subchannel::owner, sub, and skinny_line::sub.

Referenced by handle_skinny_show_lines(), and manager_skinny_show_lines().

{
   struct skinny_line *l;
   struct skinny_subchannel *sub;
   int total_lines = 0;
   int verbose = 0;
   const char *id;
   char idtext[256] = "";

   if (s) { /* Manager - get ActionID */
      id = astman_get_header(m, "ActionID");
      if (!ast_strlen_zero(id))
         snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
   }

   switch (argc) {
   case 4:
      verbose = 1;
      break;
   case 3:
      verbose = 0;
      break;
   default:
      return CLI_SHOWUSAGE;
   }

   if (!s) {
      ast_cli(fd, "Name                 Device Name          Instance Label               \n");
      ast_cli(fd, "-------------------- -------------------- -------- --------------------\n");
   }
   AST_LIST_LOCK(&lines);
   AST_LIST_TRAVERSE(&lines, l, all) {
      total_lines++;
      if (!s) {
         ast_cli(fd, "%-20s %-20s %8d %-20s\n",
            l->name,
            (l->device ? l->device->name : "Not connected"),
            l->instance,
            l->label);
         if (verbose) {
            AST_LIST_TRAVERSE(&l->sub, sub, list) {
               ast_cli(fd, "  %s> %s to %s\n",
                  (sub == l->activesub?"Active  ":"Inactive"),
                  ast_channel_name(sub->owner),
                  (ast_bridged_channel(sub->owner)?ast_channel_name(ast_bridged_channel(sub->owner)):"")
               );
            }
         }
      } else {
         astman_append(s,
            "Event: LineEntry\r\n%s"
            "Channeltype: SKINNY\r\n"
            "ObjectName: %s\r\n"
            "ChannelObjectType: line\r\n"
            "Device: %s\r\n"
            "Instance: %d\r\n"
            "Label: %s\r\n",
            idtext,
            l->name,
            (l->device ? l->device->name : "None"),
            l->instance,
            l->label);
      }
   }
   AST_LIST_UNLOCK(&lines);

   if (total) {
      *total = total_lines;
   }

   return CLI_SUCCESS;
}
static void* accept_thread ( void *  ignore) [static]

Definition at line 6990 of file chan_skinny.c.

References ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_init, ast_pthread_create, destroy_session(), errno, skinnysession::fd, skinnysession::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, skinnysession::sin, SKINNY_DEBUG, skinny_session(), skinnysession::start, and skinnysession::t.

Referenced by config_load().

{
   int as;
   struct sockaddr_in sin;
   socklen_t sinlen;
   struct skinnysession *s;
   struct protoent *p;
   int arg = 1;

   for (;;) {
      sinlen = sizeof(sin);
      as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
      if (as < 0) {
         ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
         continue;
      }

      if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= auth_limit) {
         close(as);
         ast_atomic_fetchadd_int(&unauth_sessions, -1);
         continue;
      }

      p = getprotobyname("tcp");
      if(p) {
         if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
            ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
         }
      }
      if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) {
         close(as);
         ast_atomic_fetchadd_int(&unauth_sessions, -1);
         continue;
      }

      memcpy(&s->sin, &sin, sizeof(sin));
      ast_mutex_init(&s->lock);
      s->fd = as;

      if(time(&s->start) == -1) {
         ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
         destroy_session(s);
         continue;
      }

      AST_LIST_LOCK(&sessions);
      AST_LIST_INSERT_HEAD(&sessions, s, list);
      AST_LIST_UNLOCK(&sessions);

      if (ast_pthread_create(&s->t, NULL, skinny_session, s)) {
         destroy_session(s);
      }
   }
   SKINNY_DEBUG(DEBUG_THREAD, 3, "Killing accept thread\n");
   close(as);
   return 0;
}
static struct ast_variable* add_var ( const char *  buf,
struct ast_variable list 
) [static, read]

implement the setvar config line

Definition at line 1844 of file chan_skinny.c.

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

Referenced by config_parse_variables().

{
   struct ast_variable *tmpvar = NULL;
   char *varname = ast_strdupa(buf), *varval = NULL;

   if ((varval = strchr(varname,'='))) {
      *varval++ = '\0';
      if ((tmpvar = ast_variable_new(varname, varval, ""))) {
         tmpvar->next = list;
         list = tmpvar;
      }
   }
   return list;
}
static void cleanup_stale_contexts ( char *  new,
char *  old 
) [static]

Definition at line 2022 of file chan_skinny.c.

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

Referenced by config_parse_variables().

{
   char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT];

   while ((oldcontext = strsep(&old, "&"))) {
      stalecontext = '\0';
      ast_copy_string(newlist, new, sizeof(newlist));
      stringp = newlist;
      while ((newcontext = strsep(&stringp, "&"))) {
         if (strcmp(newcontext, oldcontext) == 0) {
            /* This is not the context you're looking for */
            stalecontext = '\0';
            break;
         } else if (strcmp(newcontext, oldcontext)) {
            stalecontext = oldcontext;
         }
         
      }
      if (stalecontext)
         ast_context_destroy(ast_context_find(stalecontext), "Skinny");
   }
}
static char* complete_skinny_devices ( const char *  word,
int  state 
) [static]

Definition at line 3417 of file chan_skinny.c.

References AST_LIST_TRAVERSE, and ast_strdup.

Referenced by complete_skinny_reset(), and complete_skinny_show_device().

{
   struct skinny_device *d;
   char *result = NULL;
   int wordlen = strlen(word), which = 0;

   AST_LIST_TRAVERSE(&devices, d, list) {
      if (!strncasecmp(word, d->id, wordlen) && ++which > state)
         result = ast_strdup(d->id);
   }

   return result;
}
static char* complete_skinny_reset ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 3436 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

{
   return (pos == 2 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
}
static char* complete_skinny_show_device ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 3431 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

{
   return (pos == 3 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
}
static char* complete_skinny_show_line ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 3441 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, and skinny_device::lines.

Referenced by handle_skinny_show_line().

{
   struct skinny_device *d;
   struct skinny_line *l;
   char *result = NULL;
   int wordlen = strlen(word), which = 0;

   if (pos != 3)
      return NULL;
   
   AST_LIST_TRAVERSE(&devices, d, list) {
      AST_LIST_TRAVERSE(&d->lines, l, list) {
         if (!strncasecmp(word, l->name, wordlen) && ++which > state)
            result = ast_strdup(l->name);
      }
   }

   return result;
}
static struct skinny_device* config_device ( const char *  dname,
struct ast_variable v 
) [static, read]

Definition at line 7635 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, skinny_device::addr, ast_copy_string(), ast_format_cap_copy(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_verb, skinny_device::confcap, config_parse_variables(), default_device, DEFAULT_SKINNY_PORT, skinnysession::device, skinny_subchannel::line, skinny_device::lines, skinny_line::lock, skinny_device::lock, LOG_ERROR, LOG_NOTICE, skinny_device::session, skinny_device_alloc(), sub, skinny_line::sub, TYPE_DEVICE, and update().

Referenced by config_load().

 {
   struct skinny_device *d, *temp;
   struct skinny_line *l, *ltemp;
   struct skinny_subchannel *sub;
   int update = 0;
 
   ast_log(LOG_NOTICE, "Configuring skinny device %s.\n", dname);

   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, temp, list) {
      if (!strcasecmp(dname, temp->name) && temp->prune) {
         update = 1;
         break;
      }
   }

   if (!(d = skinny_device_alloc())) {
      ast_verb(1, "Unable to allocate memory for device %s.\n", dname);
      AST_LIST_UNLOCK(&devices);
      return NULL;
   }
   memcpy(d, default_device, sizeof(*default_device));
   ast_mutex_init(&d->lock);
   ast_copy_string(d->name, dname, sizeof(d->name));
   ast_format_cap_copy(d->confcap, default_cap);
   AST_LIST_INSERT_TAIL(&devices, d, list);

   ast_mutex_lock(&d->lock);
   AST_LIST_UNLOCK(&devices);
 
   config_parse_variables(TYPE_DEVICE, d, v);
 
   if (!AST_LIST_FIRST(&d->lines)) {
      ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
      ast_mutex_unlock(&d->lock);
      return NULL;
   }
   if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
      d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
   }
 
   if (skinnyreload){
      AST_LIST_LOCK(&devices);
      AST_LIST_TRAVERSE(&devices, temp, list) {
         if (strcasecmp(d->id, temp->id) || !temp->prune || !temp->session) {
            continue;
         }
         ast_mutex_lock(&d->lock);
         d->session = temp->session;
         d->session->device = d;
         d->hookstate = temp->hookstate;

         AST_LIST_LOCK(&d->lines);
         AST_LIST_TRAVERSE(&d->lines, l, list){

            AST_LIST_LOCK(&temp->lines);
            AST_LIST_TRAVERSE(&temp->lines, ltemp, list) {
               if (strcasecmp(l->name, ltemp->name)) {
                  continue;
               }
               ast_mutex_lock(&ltemp->lock);
               l->instance = ltemp->instance;
               if (l == temp->activeline) {
                  d->activeline = l;
               }
               if (!AST_LIST_EMPTY(&ltemp->sub)) {
                  ast_mutex_lock(&l->lock);
                  l->sub = ltemp->sub;
                  l->activesub = ltemp->activesub;
                  AST_LIST_TRAVERSE(&l->sub, sub, list) {
                     sub->line = l;
                  }
                  ast_mutex_unlock(&l->lock);
               }
               ast_mutex_unlock(&ltemp->lock);
            }
            AST_LIST_UNLOCK(&temp->lines);
         }
         AST_LIST_UNLOCK(&d->lines);
         ast_mutex_unlock(&d->lock);
      }
      AST_LIST_UNLOCK(&devices);
   }

   ast_mutex_unlock(&d->lock);

   ast_verb(3, "%s config for device '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), d->name);
   
   return d;

 }
static struct skinny_line* config_line ( const char *  lname,
struct ast_variable v 
) [static, read]

Definition at line 7561 of file chan_skinny.c.

References ast_calloc, 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_format_cap_copy(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_verb, skinny_line::confcap, config_parse_variables(), container, skinny_line::container, skinny_container::data, default_line, skinny_line::lock, LOG_NOTICE, LOG_WARNING, mwi_event_cb(), skinny_line::mwi_event_sub, skinny_line_alloc(), skinny_line_destroy(), SKINNY_LINECONTAINER, skinny_container::type, TYPE_LINE, and update().

Referenced by config_load().

 {
   struct skinny_line *l, *temp;
   int update = 0;
   struct skinny_container *container;
 
   ast_log(LOG_NOTICE, "Configuring skinny line %s.\n", lname);

   /* We find the old line and remove it just before the new
      line is created */
   AST_LIST_LOCK(&lines);
   AST_LIST_TRAVERSE(&lines, temp, all) {
      if (!strcasecmp(lname, temp->name) && temp->prune) {
         update = 1;
         break;
      }
   }

   if (!(l = skinny_line_alloc())) {
      ast_verb(1, "Unable to allocate memory for line %s.\n", lname);
      AST_LIST_UNLOCK(&lines);
      return NULL;
   }
   if (!(container = ast_calloc(1, sizeof(*container)))) {
      ast_log(LOG_WARNING, "Unable to allocate memory for line %s container.\n", lname);
      skinny_line_destroy(l);
      AST_LIST_UNLOCK(&lines);
      return NULL;
   }

   container->type = SKINNY_LINECONTAINER;
   container->data = l;
   l->container = container;
   
   memcpy(l, default_line, sizeof(*default_line));
   ast_mutex_init(&l->lock);
   ast_copy_string(l->name, lname, sizeof(l->name));
   ast_format_cap_copy(l->confcap, default_cap);
   AST_LIST_INSERT_TAIL(&lines, l, all);

   ast_mutex_lock(&l->lock);
   AST_LIST_UNLOCK(&lines);

   config_parse_variables(TYPE_LINE, l, v);
         
   if (!ast_strlen_zero(l->mailbox)) {
      char *cfg_mailbox, *cfg_context;
      cfg_context = cfg_mailbox = ast_strdupa(l->mailbox);
      ast_verb(3, "Setting mailbox '%s' on line %s\n", cfg_mailbox, l->name);
      strsep(&cfg_context, "@");
      if (ast_strlen_zero(cfg_context))
          cfg_context = "default";
      l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "skinny MWI subsciption", l,
         AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
         AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
         AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
         AST_EVENT_IE_END);
   }

   if (!ast_strlen_zero(vmexten) && ast_strlen_zero(l->vmexten)) {
      ast_copy_string(l->vmexten, vmexten, sizeof(l->vmexten));
   }
 
   ast_mutex_unlock(&l->lock);
   
   /* We do not want to unlink or free the line yet, it needs
      to be available to detect a device reconfig when we load the
      devices.  Old lines will be pruned after the reload completes */

   ast_verb(3, "%s config for line '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), l->name);

   return l;
 }
static int config_load ( void  ) [static]

Definition at line 7728 of file chan_skinny.c.

References __ourip, accept_thread(), ahp, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, ast_set_qos(), ast_variable_browse(), ast_verb, bindaddr, config_device(), config_line(), config_parse_variables(), CONFIG_STATUS_FILEINVALID, default_device, default_line, default_prefs, DEFAULT_SKINNY_BACKLOG, DEFAULT_SKINNY_PORT, errno, global_jbconf, LOG_ERROR, LOG_NOTICE, LOG_WARNING, netlock, qos, TYPE_DEF_DEVICE, TYPE_DEF_LINE, and TYPE_GENERAL.

Referenced by load_module(), and skinny_reload().

 {
   int on = 1;
   struct ast_config *cfg;
   char *cat;
   int oldport = ntohs(bindaddr.sin_port);
   struct ast_flags config_flags = { 0 };
   
   ast_log(LOG_NOTICE, "Configuring skinny from %s\n", config);
  
   if (gethostname(ourhost, sizeof(ourhost))) {
      ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled.\n");
      return 0;
   }
   cfg = ast_config_load(config, config_flags);
  
   /* We *must* have a config file otherwise stop immediately */
   if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
      ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled.\n", config);
      return -1;
   }
   memset(&bindaddr, 0, sizeof(bindaddr));
   memset(&default_prefs, 0, sizeof(default_prefs));
   memset(&vmexten, '\0', sizeof(vmexten));

   /* Copy the default jb config over global_jbconf */
   memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));

   /* load the general section */
   cat = ast_category_browse(cfg, "general");
   config_parse_variables(TYPE_GENERAL, NULL, ast_variable_browse(cfg, "general"));

   if (ntohl(bindaddr.sin_addr.s_addr)) {
      __ourip = bindaddr.sin_addr;
   } else {
      hp = ast_gethostbyname(ourhost, &ahp);
      if (!hp) {
         ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
         ast_config_destroy(cfg);
         return 0;
      }
      memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
   }
   if (!ntohs(bindaddr.sin_port)) {
      bindaddr.sin_port = htons(DEFAULT_SKINNY_PORT);
   }
   bindaddr.sin_family = AF_INET;

   /* load the lines sections */
   default_line->confprefs = default_prefs;
   config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines"));
   cat = ast_category_browse(cfg, "lines");
   while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) {
      config_line(cat, ast_variable_browse(cfg, cat));
      cat = ast_category_browse(cfg, cat);
   }
      
   /* load the devices sections */
   default_device->confprefs = default_prefs;
   config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices"));
   cat = ast_category_browse(cfg, "devices");
   while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) {
      config_device(cat, ast_variable_browse(cfg, cat));
      cat = ast_category_browse(cfg, cat);
   }

   ast_mutex_lock(&netlock);
   if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
      close(skinnysock);
      skinnysock = -1;
   }
   if (skinnysock < 0) {
      skinnysock = socket(AF_INET, SOCK_STREAM, 0);
      if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
         ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
         ast_config_destroy(cfg);
         ast_mutex_unlock(&netlock);
         return 0;
      }
      if (skinnysock < 0) {
         ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
      } else {
         if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
            ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
                  ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
                     strerror(errno));
            close(skinnysock);
            skinnysock = -1;
            ast_config_destroy(cfg);
            ast_mutex_unlock(&netlock);
            return 0;
         }
         if (listen(skinnysock, DEFAULT_SKINNY_BACKLOG)) {
               ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
                  ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
                     strerror(errno));
               close(skinnysock);
               skinnysock = -1;
               ast_config_destroy(cfg);
               ast_mutex_unlock(&netlock);
               return 0;
         }
         ast_verb(2, "Skinny listening on %s:%d\n",
               ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
         ast_set_qos(skinnysock, qos.tos, qos.cos, "Skinny");
         ast_pthread_create_background(&accept_t, NULL, accept_thread, NULL);
      }
   }
   ast_mutex_unlock(&netlock);
   ast_config_destroy(cfg);
   return 1;
}
static void config_parse_variables ( int  type,
void *  item,
struct ast_variable vptr 
) [static]

Definition at line 7112 of file chan_skinny.c.

References add_var(), ahp, skinny_line::all, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_context_find_or_create(), ast_copy_string(), ast_free, ast_get_group(), ast_get_ip(), ast_gethostbyname(), ast_jb_read_conf(), AST_LIST_FIRST, AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), AST_MAX_CONTEXT, ast_mutex_init, ast_parse_allow_disallow(), ast_sockaddr_to_sin, ast_str2cos(), ast_str2tos(), ast_strip(), ast_strlen_zero(), ast_true(), bindaddr, CDEV, CDEV_OPTS, cleanup_stale_contexts(), CLINE, CLINE_OPTS, container, skinny_subline::container, skinny_speeddial::container, context, skinny_subline::context, skinny_speeddial::context, skinny_container::data, DEFAULT_AUTH_LIMIT, DEFAULT_AUTH_TIMEOUT, default_prefs, skinny_line::device, skinny_subchannel::exten, skinny_subline::exten, skinny_speeddial::exten, global_jbconf, skinny_speeddial::instance, skinny_speeddial::isHint, skinny_speeddial::label, skinny_subline::line, ast_variable::lineno, skinny_device::lines, skinny_subline::lnname, skinny_speeddial::lock, skinny_addon::lock, LOG_WARNING, ast_variable::name, skinny_subline::name, ast_variable::next, skinny_speeddial::parent, qos, S_OR, SKINNY_SDCONTAINER, SKINNY_SUBLINECONTAINER, ast_sockaddr::ss, skinny_subline::stname, skinny_subline::sub, skinny_subchannel::subline, skinny_container::type, skinny_addon::type, TYPE_DEF_DEVICE, TYPE_DEF_LINE, TYPE_DEVICE, TYPE_GENERAL, TYPE_LINE, and ast_variable::value.

Referenced by config_device(), config_line(), and config_load().

 {
   struct ast_variable *v;
   int lineInstance = 1;
   int speeddialInstance = 1;
   
   while(vptr) {
      v = vptr;
      vptr = vptr->next;
 
      if (type & (TYPE_GENERAL)) {
         char newcontexts[AST_MAX_CONTEXT];
         char oldcontexts[AST_MAX_CONTEXT];
         char *stringp, *context, *oldregcontext;
         if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
            v = v->next;
            continue;
         }
         if (!strcasecmp(v->name, "bindaddr")) {
            if (!(hp = ast_gethostbyname(v->value, &ahp))) {
               ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
            } else {
               memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
            }
            continue;
         } else if (!strcasecmp(v->name, "keepalive")) {
            keep_alive = atoi(v->value);
            continue;
         } else if (!strcasecmp(v->name, "authtimeout")) {
            int timeout = atoi(v->value);

            if (timeout < 1) {
               ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", v->value);
               auth_timeout = DEFAULT_AUTH_TIMEOUT;
            } else {
               auth_timeout = timeout;
            }
            continue;
         } else if (!strcasecmp(v->name, "authlimit")) {
            int limit = atoi(v->value);

            if (limit < 1) {
               ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", v->value);
               auth_limit = DEFAULT_AUTH_LIMIT;
            } else {
               auth_limit = limit;
            }
            continue;
         } else if (!strcasecmp(v->name, "regcontext")) {
            ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
            stringp = newcontexts;
            /* Initialize copy of current global_regcontext for later use in removing stale contexts */
            ast_copy_string(oldcontexts, regcontext, sizeof(oldcontexts));
            oldregcontext = oldcontexts;
            /* Let's remove any contexts that are no longer defined in regcontext */
            cleanup_stale_contexts(stringp, oldregcontext);
            /* Create contexts if they don't exist already */
            while ((context = strsep(&stringp, "&"))) {
               ast_copy_string(used_context, context, sizeof(used_context));
               ast_context_find_or_create(NULL, NULL, context, "Skinny");
            }
            ast_copy_string(regcontext, v->value, sizeof(regcontext));
            continue;
         } else if (!strcasecmp(v->name, "vmexten")) {
            ast_copy_string(vmexten, v->value, sizeof(vmexten));
            continue;
         } else if (!strcasecmp(v->name, "dateformat")) {
            memcpy(date_format, v->value, sizeof(date_format));
            continue;
         } else if (!strcasecmp(v->name, "tos")) {
            if (ast_str2tos(v->value, &qos.tos))
               ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
            continue;
         } else if (!strcasecmp(v->name, "tos_audio")) {
            if (ast_str2tos(v->value, &qos.tos_audio))
               ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
            continue;
         } else if (!strcasecmp(v->name, "tos_video")) {
            if (ast_str2tos(v->value, &qos.tos_video))
               ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno);
            continue;
         } else if (!strcasecmp(v->name, "cos")) {
            if (ast_str2cos(v->value, &qos.cos))
               ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
            continue;
         } else if (!strcasecmp(v->name, "cos_audio")) {
            if (ast_str2cos(v->value, &qos.cos_audio))
               ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
            continue;
         } else if (!strcasecmp(v->name, "cos_video")) {
            if (ast_str2cos(v->value, &qos.cos_video))
               ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
            continue;
         } else if (!strcasecmp(v->name, "bindport")) {
            if (sscanf(v->value, "%5d", &ourport) == 1) {
               bindaddr.sin_port = htons(ourport);
            } else {
               ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
            }
            continue;
         } else if (!strcasecmp(v->name, "allow")) {
            ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 1);
            continue;
         } else if (!strcasecmp(v->name, "disallow")) {
            ast_parse_allow_disallow(&default_prefs, default_cap, v->value, 0);
            continue;
         } 
      }
 
      if (!strcasecmp(v->name, "transfer")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            CDEV_OPTS->transfer = ast_true(v->value);
            continue;
         } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->transfer = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "callwaiting")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            CDEV_OPTS->callwaiting = ast_true(v->value);
            continue;
         } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->callwaiting = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->directmedia = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "nat")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->nat = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "context")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->context, v->value, sizeof(CLINE_OPTS->context));
            continue;
         }
      }else if (!strcasecmp(v->name, "vmexten")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            ast_copy_string(CDEV_OPTS->vmexten, v->value, sizeof(CDEV_OPTS->vmexten));
            continue;
         } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->vmexten, v->value, sizeof(CLINE_OPTS->vmexten));
            continue;
         }
      } else if (!strcasecmp(v->name, "mwiblink")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            CDEV_OPTS->mwiblink = ast_true(v->value);
            continue;
         } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->mwiblink = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "linelabel")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->label, v->value, sizeof(CLINE_OPTS->label));
            continue;
         }
      } else if (!strcasecmp(v->name, "callerid")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            if (!strcasecmp(v->value, "asreceived")) {
               CLINE_OPTS->cid_num[0] = '\0';
               CLINE_OPTS->cid_name[0] = '\0';
            } else {
               ast_callerid_split(v->value, CLINE_OPTS->cid_name, sizeof(CLINE_OPTS->cid_name), CLINE_OPTS->cid_num, sizeof(CLINE_OPTS->cid_num));
            }
            continue;
         }
      } else if (!strcasecmp(v->name, "amaflags")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            int tempamaflags = ast_cdr_amaflags2int(v->value);
            if (tempamaflags < 0) {
               ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
            } else {
               CLINE_OPTS->amaflags = tempamaflags;
            }
            continue;
         }
      } else if (!strcasecmp(v->name, "regexten")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->regexten, v->value, sizeof(CLINE_OPTS->regexten));
            continue;
         }
      } else if (!strcasecmp(v->name, "language")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->language, v->value, sizeof(CLINE_OPTS->language));
            continue;
         }
      } else if (!strcasecmp(v->name, "accountcode")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->accountcode, v->value, sizeof(CLINE_OPTS->accountcode));
            continue;
         }
      } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->mohinterpret, v->value, sizeof(CLINE_OPTS->mohinterpret));
            continue;
         }
      } else if (!strcasecmp(v->name, "mohsuggest")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->mohsuggest, v->value, sizeof(CLINE_OPTS->mohsuggest));
            continue;
         }
      } else if (!strcasecmp(v->name, "callgroup")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->callgroup = ast_get_group(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "pickupgroup")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->pickupgroup = ast_get_group(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "immediate")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE | TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->immediate = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "cancallforward")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->cancallforward = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "mailbox")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->mailbox, v->value, sizeof(CLINE_OPTS->mailbox));
            continue;
         }
      } else if ( !strcasecmp(v->name, "parkinglot")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->parkinglot, v->value, sizeof(CLINE_OPTS->parkinglot));
            continue;
         }
      } else if (!strcasecmp(v->name, "hasvoicemail")) {
         if (type & (TYPE_LINE)) {
            if (ast_true(v->value) && ast_strlen_zero(CLINE->mailbox)) {
               ast_copy_string(CLINE->mailbox, CLINE->name, sizeof(CLINE->mailbox));
            }
            continue;
         }
      } else if (!strcasecmp(v->name, "threewaycalling")) {
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            CLINE_OPTS->threewaycalling = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "setvar")) {
         if (type & (TYPE_LINE)) {
            CLINE->chanvars = add_var(v->value, CLINE->chanvars);
            continue;
         }
      } else if (!strcasecmp(v->name, "earlyrtp")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            CDEV_OPTS->earlyrtp = ast_true(v->value);
            continue;
         }
      } else if (!strcasecmp(v->name, "host")) {
         if (type & (TYPE_DEVICE)) {
            struct ast_sockaddr CDEV_addr_tmp;

            CDEV_addr_tmp.ss.ss_family = AF_INET;
            if (ast_get_ip(&CDEV_addr_tmp, v->value)) {
               ast_log(LOG_WARNING, "Bad IP '%s' at line %d.\n", v->value, v->lineno);
            }
            ast_sockaddr_to_sin(&CDEV_addr_tmp,
                      &CDEV->addr);
            continue;
         }
      } else if (!strcasecmp(v->name, "port")) {
         if (type & (TYPE_DEF_DEVICE)) {
            CDEV->addr.sin_port = htons(atoi(v->value));
            continue;
         }
      } else if (!strcasecmp(v->name, "device")) {
         if (type & (TYPE_DEVICE)) {
            ast_copy_string(CDEV_OPTS->id, v->value, sizeof(CDEV_OPTS->id));
            continue;
         }
      } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
         if (type & (TYPE_DEVICE)) {
            CDEV->ha = ast_append_ha(v->name, v->value, CDEV->ha, NULL);
            continue;
         }
      } else if (!strcasecmp(v->name, "allow")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 1);
            continue;
         }
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 1);
            continue;
         }
      } else if (!strcasecmp(v->name, "disallow")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            ast_parse_allow_disallow(&CDEV->confprefs, CDEV->confcap, v->value, 0);
            continue;
         }
         if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
            ast_parse_allow_disallow(&CLINE->confprefs, CLINE->confcap, v->value, 0);
            continue;
         }
      } else if (!strcasecmp(v->name, "version")) {
         if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
            ast_copy_string(CDEV_OPTS->version_id, v->value, sizeof(CDEV_OPTS->version_id));
            continue;
         }
      } else if (!strcasecmp(v->name, "line")) {
         if (type & (TYPE_DEVICE)) {
            struct skinny_line *l;
            AST_LIST_TRAVERSE(&lines, l, all) {
               if (!strcasecmp(v->value, l->name) && !l->prune) {

                  /* FIXME: temp solution about line conflicts */
                  struct skinny_device *d;
                  struct skinny_line *l2;
                  int lineinuse = 0;
                  AST_LIST_TRAVERSE(&devices, d, list) {
                     AST_LIST_TRAVERSE(&d->lines, l2, list) {
                        if (l2 == l && strcasecmp(d->id, CDEV->id)) {
                           ast_log(LOG_WARNING, "Line %s already used by %s. Not connecting to %s.\n", l->name, d->name, CDEV->name);
                           lineinuse++;
                        }
                     }
                  }
                  if (!lineinuse) {
                     if (!AST_LIST_FIRST(&CDEV->lines)) {
                        CDEV->activeline = l;
                     }
                     lineInstance++;
                     AST_LIST_INSERT_HEAD(&CDEV->lines, l, list);
                     l->device = CDEV;
                  }
                  break;
               }
            }
            continue;
         }
      } else if (!strcasecmp(v->name, "subline")) {
         if (type & (TYPE_LINE)) {
            struct skinny_subline *subline;
            struct skinny_container *container;
            char buf[256];
            char *stringp = buf, *exten, *stname, *context;

            if (!(subline = ast_calloc(1, sizeof(*subline)))) {
               ast_log(LOG_WARNING, "Unable to allocate memory for subline %s. Ignoring subline.\n", v->value);
               continue;
            }
            if (!(container = ast_calloc(1, sizeof(*container)))) {
               ast_log(LOG_WARNING, "Unable to allocate memory for subline %s container. Ignoring subline.\n", v->value);
               ast_free(subline);
               continue;
            }
            
            ast_copy_string(buf, v->value, sizeof(buf));
            exten = strsep(&stringp, "@");
            ast_copy_string(subline->exten, ast_strip(exten), sizeof(subline->exten));
            stname = strsep(&exten, "_");
            ast_copy_string(subline->stname, ast_strip(stname), sizeof(subline->stname));
            ast_copy_string(subline->lnname, ast_strip(exten), sizeof(subline->lnname));
            context = strsep(&stringp, ",");
            ast_copy_string(subline->name, ast_strip(stringp), sizeof(subline->name));
            ast_copy_string(subline->context, ast_strip(context), sizeof(subline->context));

            subline->line = CLINE;
            subline->sub = NULL;

            container->type = SKINNY_SUBLINECONTAINER;
            container->data = subline;
            subline->container = container;
            AST_LIST_INSERT_HEAD(&CLINE->sublines, subline, list);
            continue;
         }
      } else if (!strcasecmp(v->name, "dialoutcontext")) {
         if (type & (TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->dialoutcontext, v->value, sizeof(CLINE_OPTS->dialoutcontext));
            continue;
         }
      } else if (!strcasecmp(v->name, "dialoutexten")) {
         if (type & (TYPE_LINE)) {
            ast_copy_string(CLINE_OPTS->dialoutexten, v->value, sizeof(CLINE_OPTS->dialoutexten));
            continue;
         }
      } else if (!strcasecmp(v->name, "speeddial")) {
         if (type & (TYPE_DEVICE)) {
            struct skinny_speeddial *sd;
            struct skinny_container *container;
            char buf[256];
            char *stringp = buf, *exten, *context, *label;

            if (!(sd = ast_calloc(1, sizeof(*sd)))) {
               ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s. Ignoring speeddial.\n", v->name);
               continue;
            }
            if (!(container = ast_calloc(1, sizeof(*container)))) {
               ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s container. Ignoring speeddial.\n", v->name);
               ast_free(sd);
               continue;
            }

            ast_copy_string(buf, v->value, sizeof(buf));
            exten = strsep(&stringp, ",");
            if ((context = strchr(exten, '@'))) {
               *context++ = '\0';
            }
            label = stringp;
            ast_mutex_init(&sd->lock);
            ast_copy_string(sd->exten, exten, sizeof(sd->exten));
            if (!ast_strlen_zero(context)) {
               sd->isHint = 1;
               sd->instance = lineInstance++;
               ast_copy_string(sd->context, context, sizeof(sd->context));
            } else {
               sd->isHint = 0;
               sd->instance = speeddialInstance++;
               sd->context[0] = '\0';
            }
            ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
            sd->parent = CDEV;
            container->type = SKINNY_SDCONTAINER;
            container->data = sd;
            sd->container = container;
            AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list);
            continue;
         }
      } else if (!strcasecmp(v->name, "addon")) {
         if (type & (TYPE_DEVICE)) {
            struct skinny_addon *a;
            if (!(a = ast_calloc(1, sizeof(*a)))) {
               ast_log(LOG_WARNING, "Unable to allocate memory for addon %s. Ignoring addon.\n", v->name);
               continue;
            } else {
               ast_mutex_init(&a->lock);
               ast_copy_string(a->type, v->value, sizeof(a->type));
               AST_LIST_INSERT_HEAD(&CDEV->addons, a, list);
            }
            continue;
         }

      } else {
         ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
         continue;
      }
      ast_log(LOG_WARNING, "Invalid category used: %s at line %d\n", v->name, v->lineno);
   }
 }
static char* control2str ( int  ind) [static]

Definition at line 4605 of file chan_skinny.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CC, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_REDIRECTING, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_TRANSFER, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_CONTROL_WINK, ast_threadstorage_get(), CONTROL2STR_BUFSIZE, and control2str_threadbuf.

Referenced by skinny_indicate().

                                  {
   char *tmp;

   switch (ind) {
   case AST_CONTROL_HANGUP:
      return "Other end has hungup";
   case AST_CONTROL_RING:
      return "Local ring";
   case AST_CONTROL_RINGING:
      return "Remote end is ringing";
   case AST_CONTROL_ANSWER:
      return "Remote end has answered";
   case AST_CONTROL_BUSY:
      return "Remote end is busy";
   case AST_CONTROL_TAKEOFFHOOK:
      return "Make it go off hook";
   case AST_CONTROL_OFFHOOK:
      return "Line is off hook";
   case AST_CONTROL_CONGESTION:
      return "Congestion (circuits busy)";
   case AST_CONTROL_FLASH:
      return "Flash hook";
   case AST_CONTROL_WINK:
      return "Wink";
   case AST_CONTROL_OPTION:
      return "Set a low-level option";
   case AST_CONTROL_RADIO_KEY:
      return "Key Radio";
   case AST_CONTROL_RADIO_UNKEY:
      return "Un-Key Radio";
   case AST_CONTROL_PROGRESS:
      return "Remote end is making Progress";
   case AST_CONTROL_PROCEEDING:
      return "Remote end is proceeding";
   case AST_CONTROL_HOLD:
      return "Hold";
   case AST_CONTROL_UNHOLD:
      return "Unhold";
   case AST_CONTROL_VIDUPDATE:
      return "VidUpdate";
   case AST_CONTROL_SRCUPDATE:
      return "Media Source Update";
   case AST_CONTROL_TRANSFER:
      return "Transfer";
   case AST_CONTROL_CONNECTED_LINE:
      return "Connected Line";
   case AST_CONTROL_REDIRECTING:
      return "Redirecting";
   case AST_CONTROL_T38_PARAMETERS:
      return "T38_Parameters";
   case AST_CONTROL_CC:
      return "CC Not Possible";
   case AST_CONTROL_SRCCHANGE:
      return "Media Source Change";
   case AST_CONTROL_INCOMPLETE:
      return "Incomplete";
   case -1:
      return "Stop tone";
   default:
      if (!(tmp = ast_threadstorage_get(&control2str_threadbuf, CONTROL2STR_BUFSIZE)))
                        return "Unknown";
      snprintf(tmp, CONTROL2STR_BUFSIZE, "UNKNOWN-%d", ind);
      return tmp;
   }
}
static void delete_devices ( void  ) [static]

Definition at line 7841 of file chan_skinny.c.

References skinny_device::addons, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, skinny_speeddial::container, free, skinny_device::lines, skinny_device_destroy(), skinny_line_destroy(), and skinny_device::speeddials.

Referenced by unload_module().

{
   struct skinny_device *d;
   struct skinny_line *l;
   struct skinny_speeddial *sd;
   struct skinny_addon *a;

   AST_LIST_LOCK(&devices);
   AST_LIST_LOCK(&lines);

   /* Delete all devices */
   while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
      /* Delete all lines for this device */
      while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
         AST_LIST_REMOVE(&lines, l, all);
         AST_LIST_REMOVE(&d->lines, l, list);
         l = skinny_line_destroy(l);
      }
      /* Delete all speeddials for this device */
      while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
         free(sd->container);
         free(sd);
      }
      /* Delete all addons for this device */
      while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
         free(a);
      }
      d = skinny_device_destroy(d);
   }
   AST_LIST_UNLOCK(&lines);
   AST_LIST_UNLOCK(&devices);
}
static void destroy_rtp ( struct skinny_subchannel sub) [static]

Definition at line 4247 of file chan_skinny.c.

References ast_rtp_instance_destroy(), ast_rtp_instance_stop(), skinny_subchannel::callid, skinny_subchannel::rtp, SKINNY_DEBUG, and skinny_subchannel::vrtp.

Referenced by setsubstate(), and skinny_hangup().

{
   if (sub->rtp) {
      SKINNY_DEBUG(DEBUG_AUDIO, 3, "Sub %d - Destroying RTP\n", sub->callid);
      ast_rtp_instance_stop(sub->rtp);
      ast_rtp_instance_destroy(sub->rtp);
      sub->rtp = NULL;
   }
   if (sub->vrtp) {
      SKINNY_DEBUG(DEBUG_AUDIO, 3, "Sub %d - Destroying VRTP\n", sub->callid);
      ast_rtp_instance_stop(sub->vrtp);
      ast_rtp_instance_destroy(sub->vrtp);
      sub->vrtp = NULL;
   }
}
static char* device2str ( int  type) [static]

Definition at line 3496 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 _skinny_show_device(), and _skinny_show_devices().

{
   char *tmp;

   switch (type) {
   case SKINNY_DEVICE_NONE:
      return "No Device";
   case SKINNY_DEVICE_30SPPLUS:
      return "30SP Plus";
   case SKINNY_DEVICE_12SPPLUS:
      return "12SP Plus";
   case SKINNY_DEVICE_12SP:
      return "12SP";
   case SKINNY_DEVICE_12:
      return "12";
   case SKINNY_DEVICE_30VIP:
      return "30VIP";
   case SKINNY_DEVICE_7910:
      return "7910";
   case SKINNY_DEVICE_7960:
      return "7960";
   case SKINNY_DEVICE_7940:
      return "7940";
   case SKINNY_DEVICE_7935:
      return "7935";
   case SKINNY_DEVICE_ATA186:
      return "ATA186";
   case SKINNY_DEVICE_7941:
      return "7941";
   case SKINNY_DEVICE_7971:
      return "7971";
   case SKINNY_DEVICE_7914:
      return "7914";
   case SKINNY_DEVICE_7985:
      return "7985";
   case SKINNY_DEVICE_7911:
      return "7911";
   case SKINNY_DEVICE_7961GE:
      return "7961GE";
   case SKINNY_DEVICE_7941GE:
      return "7941GE";
   case SKINNY_DEVICE_7931:
      return "7931";
   case SKINNY_DEVICE_7921:
      return "7921";
   case SKINNY_DEVICE_7906:
      return "7906";
   case SKINNY_DEVICE_7962:
      return "7962";
   case SKINNY_DEVICE_7937:
      return "7937";
   case SKINNY_DEVICE_7942:
      return "7942";
   case SKINNY_DEVICE_7945:
      return "7945";
   case SKINNY_DEVICE_7965:
      return "7965";
   case SKINNY_DEVICE_7975:
      return "7975";
   case SKINNY_DEVICE_7905:
      return "7905";
   case SKINNY_DEVICE_7920:
      return "7920";
   case SKINNY_DEVICE_7970:
      return "7970";
   case SKINNY_DEVICE_7912:
      return "7912";
   case SKINNY_DEVICE_7902:
      return "7902";
   case SKINNY_DEVICE_CIPC:
      return "IP Communicator";
   case SKINNY_DEVICE_7961:
      return "7961";
   case SKINNY_DEVICE_7936:
      return "7936";
   case SKINNY_DEVICE_SCCPGATEWAY_AN:
      return "SCCPGATEWAY_AN";
   case SKINNY_DEVICE_SCCPGATEWAY_BRI:
      return "SCCPGATEWAY_BRI";
   case SKINNY_DEVICE_UNKNOWN:
      return "Unknown";
   default:
      if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE)))
         return "Unknown";
      snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type);
      return tmp;
   }
}
static void dialandactivatesub ( struct skinny_subchannel sub,
char  exten[AST_MAX_EXTENSION] 
) [static]
static void dumpsub ( struct skinny_subchannel sub,
int  forcehangup 
) [static]

Definition at line 5365 of file chan_skinny.c.

References skinny_line::activesub, AST_LIST_TRAVERSE, ast_log(), skinny_subchannel::callid, skinny_line::device, skinny_subchannel::line, LOG_WARNING, skinny_subchannel::related, setsubstate(), SKINNY_DEBUG, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, skinny_line::sub, skinny_subchannel::substate, SUBSTATE_CALLWAIT, SUBSTATE_HOLD, SUBSTATE_ONHOOK, SUBSTATE_RINGIN, and transmit_speaker_mode().

Referenced by dialandactivatesub(), handle_onhook_message(), handle_soft_key_event_message(), skinny_dialer(), and skinny_hangup().

{
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;
   struct skinny_subchannel *activate_sub = NULL;
   struct skinny_subchannel *tsub;

   SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Dumping\n", sub->callid);

   if (!forcehangup && sub->substate == SUBSTATE_HOLD) {
      l->activesub = NULL;
      return;
   }

   if (sub == l->activesub) {
      d->hookstate = SKINNY_ONHOOK;
      transmit_speaker_mode(d, SKINNY_SPEAKEROFF); 
      if (sub->related) {
         activate_sub = sub->related;
         setsubstate(sub, SUBSTATE_ONHOOK);
         l->activesub = activate_sub;
         if (l->activesub->substate != SUBSTATE_HOLD) {
            ast_log(LOG_WARNING, "Sub-%d was related but not at SUBSTATE_HOLD\n", sub->callid);
            return;
         }
         setsubstate(l->activesub, SUBSTATE_HOLD);
      } else {
         setsubstate(sub, SUBSTATE_ONHOOK);
         AST_LIST_TRAVERSE(&l->sub, tsub, list) {
            if (tsub->substate == SUBSTATE_CALLWAIT) {
               activate_sub = tsub;
            }
         }
         if (activate_sub) {
            setsubstate(activate_sub, SUBSTATE_RINGIN);
            return;
         }
         AST_LIST_TRAVERSE(&l->sub, tsub, list) {
            if (tsub->substate == SUBSTATE_HOLD) {
               activate_sub = tsub;
            }
         }
         if (activate_sub) {
            setsubstate(activate_sub, SUBSTATE_HOLD);
            return;
         }
      }
   } else {
      setsubstate(sub, SUBSTATE_ONHOOK);
   }
}
static struct skinny_line* find_line_by_instance ( struct skinny_device d,
int  instance 
) [static, read]

Definition at line 1733 of file chan_skinny.c.

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

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

{
   struct skinny_line *l;

   /*Dialing from on hook or on a 7920 uses instance 0 in requests
     but we need to start looking at instance 1 */

   if (!instance)
      instance = 1;

   AST_LIST_TRAVERSE(&d->lines, l, list){
      if (l->instance == instance)
         break;
   }

   if (!l) {
      ast_log(LOG_WARNING, "Could not find line with instance '%d' on device '%s'\n", instance, d->name);
   }
   return l;
}
static struct skinny_line* find_line_by_name ( const char *  dest) [static, read]

Definition at line 1754 of file chan_skinny.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), skinny_device::lines, and LOG_WARNING.

Referenced by skinny_devicestate(), and skinny_request().

{
   struct skinny_line *l;
   struct skinny_line *tmpl = NULL;
   struct skinny_device *d;
   char line[256];
   char *at;
   char *device;
   int checkdevice = 0;

   ast_copy_string(line, dest, sizeof(line));
   at = strchr(line, '@');
   if (at)
      *at++ = '\0';
   device = at;

   if (!ast_strlen_zero(device))
      checkdevice = 1;

   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, d, list){
      if (checkdevice && tmpl)
         break;
      else if (!checkdevice) {
         /* This is a match, since we're checking for line on every device. */
      } else if (!strcasecmp(d->name, device)) {
      } else
         continue;

      /* Found the device (or we don't care which device) */
      AST_LIST_TRAVERSE(&d->lines, l, list){
         /* Search for the right line */
         if (!strcasecmp(l->name, line)) {
            if (tmpl) {
               ast_log(LOG_WARNING, "Ambiguous line name: %s\n", line);
               AST_LIST_UNLOCK(&devices);
               return NULL;
            } else
               tmpl = l;
         }
      }
   }
   AST_LIST_UNLOCK(&devices);
   return tmpl;
}
static struct skinny_speeddial* find_speeddial_by_instance ( struct skinny_device d,
int  instance,
int  isHint 
) [static, read]

Definition at line 1927 of file chan_skinny.c.

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

Referenced by handle_message(), handle_stimulus_message(), and transmit_linestatres().

{
   struct skinny_speeddial *sd;

   AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
      if (sd->isHint == isHint && sd->instance == instance)
         break;
   }

   if (!sd) {
      ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
   }
   return sd;
}
static struct skinny_subchannel* find_subchannel_by_instance_reference ( struct skinny_device d,
int  instance,
int  reference 
) [static, read]

Definition at line 1876 of file chan_skinny.c.

References AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_log(), skinny_subchannel::callid, find_line_by_instance(), LOG_WARNING, sub, and skinny_line::sub.

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

{
   struct skinny_line *l = find_line_by_instance(d, instance);
   struct skinny_subchannel *sub;

   if (!l) {
      return NULL;
   }

   /* 7920 phones set call reference to 0, so use the first
      sub-channel on the list.
           This MIGHT need more love to be right */
   if (!reference)
      sub = AST_LIST_FIRST(&l->sub);
   else {
      AST_LIST_TRAVERSE(&l->sub, sub, list) {
         if (sub->callid == reference)
            break;
      }
   }
   if (!sub) {
      ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s'\n", reference, d->name);
   }
   return sub;
}
static struct skinny_subchannel* find_subchannel_by_reference ( struct skinny_device d,
int  reference 
) [static, read]

Definition at line 1903 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message().

{
   struct skinny_line *l;
   struct skinny_subchannel *sub = NULL;

   AST_LIST_TRAVERSE(&d->lines, l, list){
      AST_LIST_TRAVERSE(&l->sub, sub, list){
         if (sub->callid == reference)
            break;
      }
      if (sub)
         break;
   }

   if (!l) {
      ast_log(LOG_WARNING, "Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
   } else {
      if (!sub) {
         ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
      }
   }
   return sub;
}
static struct skinny_subline* find_subline_by_callid ( struct skinny_device d,
int  callid 
) [static, read]

Definition at line 1826 of file chan_skinny.c.

References AST_LIST_TRAVERSE, skinny_subline::callid, skinny_device::lines, skinny_subchannel::subline, and skinny_line::sublines.

Referenced by handle_soft_key_event_message().

{
   struct skinny_subline *subline;
   struct skinny_line *l;
   
   AST_LIST_TRAVERSE(&d->lines, l, list){
      AST_LIST_TRAVERSE(&l->sublines, subline, list){
         if (subline->callid == callid) {
            return subline;
         }
      }
   }
   return NULL;
}
static struct skinny_subline* find_subline_by_name ( const char *  dest) [static, read]

Definition at line 1800 of file chan_skinny.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_verb, skinny_device::lines, skinny_subline::name, skinny_subchannel::subline, and skinny_line::sublines.

Referenced by skinny_request().

{
   struct skinny_line *l;
   struct skinny_subline *subline;
   struct skinny_subline *tmpsubline = NULL;
   struct skinny_device *d;

   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, d, list){
      AST_LIST_TRAVERSE(&d->lines, l, list){
         AST_LIST_TRAVERSE(&l->sublines, subline, list){
            if (!strcasecmp(subline->name, dest)) {
               if (tmpsubline) {
                  ast_verb(2, "Ambiguous subline name: %s\n", dest);
                  AST_LIST_UNLOCK(&devices);
                  return NULL;
               } else
                  tmpsubline = subline;
            }
         }
      }
   }
   AST_LIST_UNLOCK(&devices);
   return tmpsubline;
}
static void* get_button_template ( struct skinnysession s,
struct button_definition_template btn 
) [static]

Definition at line 1582 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, and skinny_addon::type.

Referenced by handle_button_template_req_message().

{
   struct skinny_device *d = s->device;
   struct skinny_addon *a;
   int i;

   switch (d->type) {
      case SKINNY_DEVICE_30SPPLUS:
      case SKINNY_DEVICE_30VIP:
         /* 13 rows, 2 columns */
         for (i = 0; i < 4; i++)
            (btn++)->buttonDefinition = BT_CUST_LINE;
         (btn++)->buttonDefinition = BT_REDIAL;
         (btn++)->buttonDefinition = BT_VOICEMAIL;
         (btn++)->buttonDefinition = BT_CALLPARK;
         (btn++)->buttonDefinition = BT_FORWARDALL;
         (btn++)->buttonDefinition = BT_CONFERENCE;
         for (i = 0; i < 4; i++)
            (btn++)->buttonDefinition = BT_NONE;
         for (i = 0; i < 13; i++)
            (btn++)->buttonDefinition = BT_SPEEDDIAL;
         
         break;
      case SKINNY_DEVICE_12SPPLUS:
      case SKINNY_DEVICE_12SP:
      case SKINNY_DEVICE_12:
         /* 6 rows, 2 columns */
         for (i = 0; i < 2; i++)
            (btn++)->buttonDefinition = BT_CUST_LINE;
         for (i = 0; i < 4; i++)
            (btn++)->buttonDefinition = BT_SPEEDDIAL;
         (btn++)->buttonDefinition = BT_HOLD;
         (btn++)->buttonDefinition = BT_REDIAL;
         (btn++)->buttonDefinition = BT_TRANSFER;
         (btn++)->buttonDefinition = BT_FORWARDALL;
         (btn++)->buttonDefinition = BT_CALLPARK;
         (btn++)->buttonDefinition = BT_VOICEMAIL;
         break;
      case SKINNY_DEVICE_7910:
         (btn++)->buttonDefinition = BT_LINE;
         (btn++)->buttonDefinition = BT_HOLD;
         (btn++)->buttonDefinition = BT_TRANSFER;
         (btn++)->buttonDefinition = BT_DISPLAY;
         (btn++)->buttonDefinition = BT_VOICEMAIL;
         (btn++)->buttonDefinition = BT_CONFERENCE;
         (btn++)->buttonDefinition = BT_FORWARDALL;
         for (i = 0; i < 2; i++)
            (btn++)->buttonDefinition = BT_SPEEDDIAL;
         (btn++)->buttonDefinition = BT_REDIAL;
         break;
      case SKINNY_DEVICE_7960:
      case SKINNY_DEVICE_7961:
      case SKINNY_DEVICE_7961GE:
      case SKINNY_DEVICE_7962:
      case SKINNY_DEVICE_7965:
         for (i = 0; i < 6; i++)
            (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
         break;
      case SKINNY_DEVICE_7940:
      case SKINNY_DEVICE_7941:
      case SKINNY_DEVICE_7941GE:
      case SKINNY_DEVICE_7942:
      case SKINNY_DEVICE_7945:
         for (i = 0; i < 2; i++)
            (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
         break;
      case SKINNY_DEVICE_7935:
      case SKINNY_DEVICE_7936:
         for (i = 0; i < 2; i++)
            (btn++)->buttonDefinition = BT_LINE;
         break;
      case SKINNY_DEVICE_ATA186:
         (btn++)->buttonDefinition = BT_LINE;
         break;
      case SKINNY_DEVICE_7970:
      case SKINNY_DEVICE_7971:
      case SKINNY_DEVICE_7975:
      case SKINNY_DEVICE_CIPC:
         for (i = 0; i < 8; i++)
            (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
         break;
      case SKINNY_DEVICE_7985:
         /* XXX I have no idea what the buttons look like on these. */
         ast_log(LOG_WARNING, "Unsupported device type '%d (7985)' found.\n", d->type);
         break;
      case SKINNY_DEVICE_7912:
      case SKINNY_DEVICE_7911:
      case SKINNY_DEVICE_7905:
         (btn++)->buttonDefinition = BT_LINE;
         (btn++)->buttonDefinition = BT_HOLD;
         break;
      case SKINNY_DEVICE_7920:
         /* XXX I don't know if this is right. */
         for (i = 0; i < 4; i++)
            (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
         break;
      case SKINNY_DEVICE_7921:
         for (i = 0; i < 6; i++)
            (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
         break;
      case SKINNY_DEVICE_7902:
         ast_log(LOG_WARNING, "Unsupported device type '%d (7902)' found.\n", d->type);
         break;
      case SKINNY_DEVICE_7906:
         ast_log(LOG_WARNING, "Unsupported device type '%d (7906)' found.\n", d->type);
         break;
      case SKINNY_DEVICE_7931:
         ast_log(LOG_WARNING, "Unsupported device type '%d (7931)' found.\n", d->type);
         break;
      case SKINNY_DEVICE_7937:
         ast_log(LOG_WARNING, "Unsupported device type '%d (7937)' found.\n", d->type);
         break;
      case SKINNY_DEVICE_7914:
         ast_log(LOG_WARNING, "Unsupported device type '%d (7914)' found.  Expansion module registered by itself?\n", d->type);
         break;
      case SKINNY_DEVICE_SCCPGATEWAY_AN:
      case SKINNY_DEVICE_SCCPGATEWAY_BRI:
         ast_log(LOG_WARNING, "Unsupported device type '%d (SCCP gateway)' found.\n", d->type);
         break;
      default:
         ast_log(LOG_WARNING, "Unknown device type '%d' found.\n", d->type);
         break;
   }

   AST_LIST_LOCK(&d->addons);
   AST_LIST_TRAVERSE(&d->addons, a, list) {
      if (!strcasecmp(a->type, "7914")) {
         for (i = 0; i < 14; i++)
            (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
      } else {
         ast_log(LOG_WARNING, "Unknown addon type '%s' found.  Skipping.\n", a->type);
      }
   }
   AST_LIST_UNLOCK(&d->addons);

   return btn;
}
static int get_input ( struct skinnysession s) [static]

Definition at line 6831 of file chan_skinny.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_poll, skinnysession::device, errno, skinnysession::fd, htolel, skinnysession::inbuf, letohl, skinnysession::lock, LOG_ERROR, LOG_WARNING, SKINNY_MAX_PACKET, skinny_unregister(), and skinnysession::start.

Referenced by skinny_session().

{
   int res;
   int dlen = 0;
   int timeout = keep_alive * 1100;
   time_t now;
   int *bufaddr;
   struct pollfd fds[1];

   if (!s->device) {
      if(time(&now) == -1) {
         ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
         return -1;
      }

      timeout = (auth_timeout - (now - s->start)) * 1000;
      if (timeout < 0) {
         /* we have timed out */
         ast_log(LOG_WARNING, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
         return -1;
      }
   }

   fds[0].fd = s->fd;
   fds[0].events = POLLIN;
   fds[0].revents = 0;
   res = ast_poll(fds, 1, timeout); /* If nothing has happen, client is dead */
                   /* we add 10% to the keep_alive to deal */
                   /* with network delays, etc */
   if (res < 0) {
      if (errno != EINTR) {
         ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
         return res;
      }
   } else if (res == 0) {
      if (s->device) {
         ast_log(LOG_WARNING, "Skinny Client was lost, unregistering\n");
      } else {
         ast_log(LOG_WARNING, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
      }
      skinny_unregister(NULL, s);
      return -1;
   }

   if (fds[0].revents) {
      ast_mutex_lock(&s->lock);
      memset(s->inbuf, 0, sizeof(s->inbuf));
      res = read(s->fd, s->inbuf, 4);
      if (res < 0) {
         ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));

         ast_log(LOG_WARNING, "Skinny Client was lost, unregistering\n");

         skinny_unregister(NULL, s);
         ast_mutex_unlock(&s->lock);
         return res;
      } else if (res != 4) {
         ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
         ast_mutex_unlock(&s->lock);

         if (res == 0) {
            ast_log(LOG_WARNING, "Skinny Client was lost, unregistering\n");
            skinny_unregister(NULL, s);
         }

         return -1;
      }

      bufaddr = (int *)s->inbuf;
      dlen = letohl(*bufaddr);
      if (dlen < 4) {
         ast_log(LOG_WARNING, "Skinny Client sent invalid data.\n");
         ast_mutex_unlock(&s->lock);
         return -1;
      }
      if (dlen+8 > sizeof(s->inbuf)) {
         ast_log(LOG_WARNING, "Skinny packet too large (%d bytes), max length(%d bytes)\n", dlen+8, SKINNY_MAX_PACKET);
         dlen = sizeof(s->inbuf) - 8;
      }
      *bufaddr = htolel(dlen);

      res = read(s->fd, s->inbuf+4, dlen+4);
      ast_mutex_unlock(&s->lock);
      if (res < 0) {
         ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
         return res;
      } else if (res != (dlen+4)) {
         ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
         return -1;
      }
      return res;
   }
   return 0;
}
static int handle_button_template_req_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 6094 of file chan_skinny.c.

References AST_LIST_TRAVERSE, 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, button_definition::instanceNumber, skinny_speeddial::isHint, skinny_device::lines, req_alloc(), SKINNY_DEBUG, skinny_device::speeddials, button_template_res_message::totalButtonCount, and transmit_response().

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l;
   int i;

   struct skinny_speeddial *sd;
   struct button_definition_template btn[42];
   int lineInstance = 1;
   int speeddialInstance = 1;
   int buttonCount = 0;

   if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
      return -1;

   SKINNY_DEBUG(DEBUG_TEMPLATE, 3, "Creating Button Template\n");

   memset(&btn, 0, sizeof(btn));
   get_button_template(s, btn);

   for (i=0; i<42; i++) {
      int btnSet = 0;
      switch (btn[i].buttonDefinition) {
         case BT_CUST_LINE:
            /* assume failure */
            req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
            req->data.buttontemplate.definition[i].instanceNumber = 0;

            AST_LIST_TRAVERSE(&d->lines, l, list) {
               if (l->instance == lineInstance) {
                  SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", BT_LINE, lineInstance);
                  req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
                  req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
                  lineInstance++;
                  buttonCount++;
                  btnSet = 1;
                  break;
               }
            }

            if (!btnSet) {
               AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
                  if (sd->isHint && sd->instance == lineInstance) {
                     SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", BT_LINE, lineInstance);
                     req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
                     req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
                     lineInstance++;
                     buttonCount++;
                     btnSet = 1;
                     break;
                  }
               }
            }
            break;
         case BT_CUST_LINESPEEDDIAL:
            /* assume failure */
            req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
            req->data.buttontemplate.definition[i].instanceNumber = 0;

            AST_LIST_TRAVERSE(&d->lines, l, list) {
               if (l->instance == lineInstance) {
                  SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", BT_LINE, lineInstance);
                  req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
                  req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
                  lineInstance++;
                  buttonCount++;
                  btnSet = 1;
                  break;
               }
            }

            if (!btnSet) {
               AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
                  if (sd->isHint && sd->instance == lineInstance) {
                     SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", BT_LINE, lineInstance);
                     req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
                     req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
                     lineInstance++;
                     buttonCount++;
                     btnSet = 1;
                     break;
                  } else if (!sd->isHint && sd->instance == speeddialInstance) {
                     SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
                     req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
                     req->data.buttontemplate.definition[i].instanceNumber = speeddialInstance;
                     speeddialInstance++;
                     buttonCount++;
                     btnSet = 1;
                     break;
                  }
               }
            }
            break;
         case BT_LINE:
            req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
            req->data.buttontemplate.definition[i].instanceNumber = htolel(0);

            AST_LIST_TRAVERSE(&d->lines, l, list) {
               if (l->instance == lineInstance) {
                  SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", BT_LINE, lineInstance);
                  req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
                  req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
                  lineInstance++;
                  buttonCount++;
                  btnSet = 1;
                  break;
               }
            }
            break;
         case BT_SPEEDDIAL:
            req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
            req->data.buttontemplate.definition[i].instanceNumber = 0;

            AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
               if (!sd->isHint && sd->instance == speeddialInstance) {
                  SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
                  req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
                  req->data.buttontemplate.definition[i].instanceNumber = speeddialInstance - 1;
                  speeddialInstance++;
                  buttonCount++;
                  btnSet = 1;
                  break;
               }
            }
            break;
         case BT_NONE:
            break;
         default:
            SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
            req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
            req->data.buttontemplate.definition[i].instanceNumber = 0;
            buttonCount++;
            btnSet = 1;
            break;
      }
   }

   req->data.buttontemplate.buttonOffset = 0;
   req->data.buttontemplate.buttonCount = htolel(buttonCount);
   req->data.buttontemplate.totalButtonCount = htolel(buttonCount);

   SKINNY_DEBUG(DEBUG_PACKET | DEBUG_TEMPLATE, 3, "Transmitting BUTTON_TEMPLATE_RES_MESSAGE to %s, type %d\n",
      d->name, d->type);
   transmit_response(d, req);
   return 1;
}
static int handle_callforward_button ( struct skinny_subchannel sub,
int  cfwdtype 
) [static]

Definition at line 5543 of file chan_skinny.c.

References ast_hangup(), ast_indicate(), ast_log(), ast_safe_sleep(), AST_STATE_UP, skinny_subchannel::callid, skinny_line::device, KEYDEF_ONHOOK, skinny_subchannel::line, LOG_WARNING, skinny_subchannel::owner, skinny_device::session, set_callforwards(), setsubstate(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, SUBSTATE_OFFHOOK, transmit_activatecallplane(), transmit_callstate(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_displaynotify(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_stopmediatransmission().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

{
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;
   struct ast_channel *c = sub->owner;

   if (!d->session) {
      ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
      return 0;
   }

   if (d->hookstate == SKINNY_ONHOOK) {
      d->hookstate = SKINNY_OFFHOOK;
      transmit_speaker_mode(d, SKINNY_SPEAKERON);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
      transmit_activatecallplane(d, l);
   }
   transmit_clear_display_message(d, l->instance, sub->callid);

   if (l->cfwdtype & cfwdtype) {
      set_callforwards(l, NULL, cfwdtype);
      ast_safe_sleep(c, 500);
      transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
      transmit_closereceivechannel(d, sub);
      transmit_stopmediatransmission(d, sub);
      transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
      transmit_clearpromptmessage(d, l->instance, sub->callid);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
      transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
      transmit_activatecallplane(d, l);
      transmit_displaynotify(d, "CFwd disabled", 10);
      if (sub->owner && ast_channel_state(sub->owner) != AST_STATE_UP) {
         ast_indicate(c, -1);
         ast_hangup(c);
      }
      transmit_cfwdstate(d, l);
   } else {
      l->getforward = cfwdtype;
      setsubstate(sub, SUBSTATE_OFFHOOK);
   }
   return 0;
}
static int handle_capabilities_res_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 6055 of file chan_skinny.c.

References ast_format_cap_add(), ast_format_cap_alloc(), ast_format_cap_destroy(), ast_format_cap_joint_copy(), ast_getformatname(), ast_getformatname_multiple(), AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock, ast_mutex_unlock, skinny_line::cap, skinny_device::cap, capabilities_res_message::caps, skinny_data::caps, station_capabilities::codec, codec_skinny2ast(), skinny_line::confcap, skinny_device::confcap, capabilities_res_message::count, skinny_req::data, skinnysession::device, letohl, skinny_device::lines, skinny_line::lock, LOG_WARNING, SKINNY_DEBUG, and SKINNY_MAX_CAPABILITIES.

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l;
   uint32_t count = 0;
   struct ast_format_cap *codecs = ast_format_cap_alloc();
   int i;

   if (!codecs) {
      return 0;
   }

   count = letohl(req->data.caps.count);
   if (count > SKINNY_MAX_CAPABILITIES) {
      count = SKINNY_MAX_CAPABILITIES;
      ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
   }

   for (i = 0; i < count; i++) {
      struct ast_format acodec;
      int scodec = 0;
      scodec = letohl(req->data.caps.caps[i].codec);
      codec_skinny2ast(scodec, &acodec);
      SKINNY_DEBUG(DEBUG_AUDIO, 4, "Adding codec capability %s (%d)\n", ast_getformatname(&acodec), scodec);
      ast_format_cap_add(codecs, &acodec);
   }

   ast_format_cap_joint_copy(d->confcap, codecs, d->cap);
   SKINNY_DEBUG(DEBUG_AUDIO, 4, "Device capability set to '%s'\n", ast_getformatname_multiple(dbgreg_buf, sizeof(dbgreg_buf), d->cap));
   AST_LIST_TRAVERSE(&d->lines, l, list) {
      ast_mutex_lock(&l->lock);
      ast_format_cap_joint_copy(l->confcap, d->cap, l->cap);
      ast_mutex_unlock(&l->lock);
   }

   codecs = ast_format_cap_destroy(codecs);
   return 1;
}
static int handle_enbloc_call_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 6316 of file chan_skinny.c.

References ast_channel_tech_pvt(), ast_log(), AST_STATE_DOWN, enbloc_call_message::calledParty, skinny_req::data, skinnysession::device, dialandactivatesub(), skinny_data::enbloccallmessage, find_line_by_instance(), find_subchannel_by_instance_reference(), skinny_subchannel::line, LOG_WARNING, skinny_new(), SKINNY_OFFHOOK, SKINNY_OUTGOING, and sub.

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l;
   struct skinny_subchannel *sub = NULL;
   struct ast_channel *c;

   sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);

   if (!sub) {
      l = find_line_by_instance(d, d->lastlineinstance);
      if (!l) {
         return 0;
      }
   } else {
      l = sub->line;
   }

   c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);

   if(!c) {
      ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
   } else {
      d->hookstate = SKINNY_OFFHOOK;

      sub = ast_channel_tech_pvt(c);
      dialandactivatesub(sub, req->data.enbloccallmessage.calledParty);
   }
   
   return 1;
}
static int handle_hold_button ( struct skinny_subchannel sub) [static]

Definition at line 5468 of file chan_skinny.c.

References activatesub(), skinny_subchannel::related, setsubstate(), skinny_subchannel::substate, SUBSTATE_CONNECTED, and SUBSTATE_HOLD.

Referenced by handle_stimulus_message().

{
   if (!sub)
      return -1;
   if (sub->related) {
      setsubstate(sub, SUBSTATE_HOLD);
      activatesub(sub->related, SUBSTATE_CONNECTED);
   } else {
      if (sub->substate == SUBSTATE_HOLD) {
         activatesub(sub, SUBSTATE_CONNECTED);
      } else {
         setsubstate(sub, SUBSTATE_HOLD);
      }
   }
   return 1;
}
static int handle_ip_port_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5585 of file chan_skinny.c.

Referenced by handle_message().

{
   /* no response necessary */
   return 1;
}
static int handle_keypad_button_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5591 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_LIST_NEXT, ast_log(), ast_queue_frame(), AST_STATE_UP, keypad_button_message::button, skinny_subchannel::callid, keypad_button_message::callReference, skinny_req::data, skinnysession::device, skinny_subchannel::dialer_sched, skinny_subchannel::exten, find_subchannel_by_instance_reference(), ast_frame::frametype, ast_frame_subclass::integer, KEYDEF_DADFD, skinny_data::keypad, len(), letohl, skinny_subchannel::line, keypad_button_message::lineInstance, LOG_WARNING, skinny_subchannel::owner, SKINNY_DEBUG, skinny_dialer(), skinny_sched_del(), ast_frame::src, sub, ast_frame::subclass, transmit_selectsoftkeys(), and transmit_stop_tone().

Referenced by handle_message().

{
   struct skinny_subchannel *sub = NULL;
   struct skinny_line *l;
   struct skinny_device *d = s->device;
   struct ast_frame f = { 0, };
   char dgt;
   int digit;
   int lineInstance;
   int callReference;
   size_t len;

   digit = letohl(req->data.keypad.button);
   lineInstance = letohl(req->data.keypad.lineInstance);
   callReference = letohl(req->data.keypad.callReference);

   if (lineInstance && callReference) {
      sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
   } else {
      sub = d->activeline->activesub;
   }

   if (!sub)
      return 0;

   l = sub->line;

   if (digit == 14) {
      dgt = '*';
   } else if (digit == 15) {
      dgt = '#';
   } else if (digit >= 0 && digit <= 9) {
      dgt = '0' + digit;
   } else {
      /* digit=10-13 (A,B,C,D ?), or
       * digit is bad value
       *
       * probably should not end up here, but set
       * value for backward compatibility, and log
       * a warning.
       */
      dgt = '0' + digit;
      ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
   }

   if ((sub->owner && ast_channel_state(sub->owner) <  AST_STATE_UP)) {
      if (sub->dialer_sched &&   !skinny_sched_del(sub->dialer_sched, sub)) {
         SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Got a digit and not timed out, so try dialing\n", sub->callid);
         sub->dialer_sched = 0;
         len = strlen(sub->exten);
         if (len == 0) {
            transmit_stop_tone(d, l->instance, sub->callid);
            transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD);
         }
         if (len < sizeof(sub->exten) - 1) {
            sub->exten[len] = dgt;
            sub->exten[len + 1] = '\0';
         }
         if (len == sizeof(sub->exten) - 1) {
            skinny_dialer(sub, 1);
         } else {
            skinny_dialer(sub, 0);
         }
      } else {
         SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d  Got a digit already timedout, ignore\n", sub->callid);
         /* Timed out so the call is being progressed elsewhere, to late for digits */
         return 0;
      }
   } else {
      SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Got a digit and sending as DTMF\n", sub->callid);
      f.subclass.integer = dgt;
      f.src = "skinny";
      if (sub->owner) {
         if (ast_channel_state(sub->owner) == 0) {
            f.frametype = AST_FRAME_DTMF_BEGIN;
            ast_queue_frame(sub->owner, &f);
         }
         /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
         f.frametype = AST_FRAME_DTMF_END;
         ast_queue_frame(sub->owner, &f);
         /* XXX This seriously needs to be fixed */
         if (AST_LIST_NEXT(sub, list) && AST_LIST_NEXT(sub, list)->owner) {
            if (ast_channel_state(sub->owner) == 0) {
               f.frametype = AST_FRAME_DTMF_BEGIN;
               ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
            }
            f.frametype = AST_FRAME_DTMF_END;
            ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
         }
      } else {
         ast_log(LOG_WARNING, "Got digit on %s, but not associated with channel\n", l->name);
      }
   }
   return 1;
}
static int handle_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 6669 of file chan_skinny.c.

References skinny_data::alarm, ALARM_MESSAGE, ast_atomic_fetchadd_int(), ast_free, ast_log(), ast_verb, keypad_button_message::button, BUTTON_TEMPLATE_REQ_MESSAGE, enbloc_call_message::calledParty, keypad_button_message::callReference, CAPABILITIES_RES_MESSAGE, skinny_data::caps, capabilities_res_message::count, skinny_req::data, skinnysession::device, alarm_message::displayMessage, skinny_req::e, ENBLOC_CALL_MESSAGE, skinny_data::enbloccallmessage, find_speeddial_by_instance(), handle_button_template_req_message(), handle_capabilities_res_message(), handle_enbloc_call_message(), handle_ip_port_message(), handle_keypad_button_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_soft_key_event_message(), handle_stimulus_message(), HEADSET_STATUS_MESSAGE, offhook_message::instance, IP_PORT_MESSAGE, KEEP_ALIVE_MESSAGE, KEYDEF_ONHOOK, skinny_data::keypad, KEYPAD_BUTTON_MESSAGE, letohl, skinny_data::line, LINE_STATE_REQ_MESSAGE, keypad_button_message::lineInstance, line_state_req_message::lineNumber, LOG_WARNING, register_message::name, skinny_data::offhook, OFFHOOK_MESSAGE, ONHOOK_MESSAGE, OPEN_RECEIVE_CHANNEL_ACK_MESSAGE, register_message::protocolVersion, offhook_message::reference, skinny_data::reg, REGISTER_AVAILABLE_LINES_MESSAGE, REGISTER_MESSAGE, SERVER_REQUEST_MESSAGE, SKINNY_DEBUG, skinny_register(), skinny_unregister(), SOFT_KEY_EVENT_MESSAGE, SOFT_KEY_SET_REQ_MESSAGE, SOFT_KEY_TEMPLATE_REQ_MESSAGE, SPEED_DIAL_STAT_REQ_MESSAGE, speed_dial_stat_req_message::speedDialNumber, skinny_data::speeddialreq, STIMULUS_MESSAGE, TIME_DATE_REQ_MESSAGE, transmit_capabilitiesreq(), transmit_definetimedate(), transmit_keepaliveack(), transmit_linestatres(), transmit_registerack(), transmit_registerrej(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speeddialstatres(), transmit_versionres(), register_message::type, UNREGISTER_MESSAGE, and VERSION_REQ_MESSAGE.

Referenced by skinny_session().

{
   int res = 0;
   struct skinny_speeddial *sd;
   struct skinny_device *d = s->device;

   if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
      ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
      ast_free(req);
      return 0;
   }

   switch(letohl(req->e)) {
   case KEEP_ALIVE_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received KEEP_ALIVE_MESSAGE from %s\n", d->name);
      transmit_keepaliveack(s->device);
      break;
   case REGISTER_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received REGISTER_MESSAGE from %s, name %s, type %d, protovers %d\n",
         d->name, req->data.reg.name, letohl(req->data.reg.type), letohl(req->data.reg.protocolVersion));
      if (skinny_register(req, s)) {
         ast_atomic_fetchadd_int(&unauth_sessions, -1);
         ast_verb(3, "Device '%s' successfully registered (protoVers %d)\n", s->device->name, s->device->protocolversion);
         transmit_registerack(s->device);
         transmit_capabilitiesreq(s->device);
      } else {
         transmit_registerrej(s);
         ast_free(req);
         return -1;
      }
   case IP_PORT_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received IP_PORT_MESSAGE from %s\n", d->name);
      res = handle_ip_port_message(req, s);
      break;
   case KEYPAD_BUTTON_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received KEYPAD_BUTTON_MESSAGE from %s, digit %d, inst %d, callref %d\n",
         d->name, letohl(req->data.keypad.button), letohl(req->data.keypad.lineInstance), letohl(req->data.keypad.callReference));
      res = handle_keypad_button_message(req, s);
      break;
   case ENBLOC_CALL_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received ENBLOC_CALL_MESSAGE from %s, calledParty %s\n",
         d->name, req->data.enbloccallmessage.calledParty);
      res = handle_enbloc_call_message(req, s);
      break;
   case STIMULUS_MESSAGE:
      /* SKINNY_PACKETDEBUG handled in handle_stimulus_message */
      res = handle_stimulus_message(req, s);
      break;
   case OFFHOOK_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received OFFHOOK_MESSAGE from %s, inst %d, ref %d\n",
         d->name, letohl(req->data.offhook.instance), letohl(req->data.offhook.reference));
      res = handle_offhook_message(req, s);
      break;
   case ONHOOK_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received ONHOOK_MESSAGE from %s, inst %d, ref %d\n",
         d->name, letohl(req->data.offhook.instance), letohl(req->data.offhook.reference));
      res = handle_onhook_message(req, s);
      break;
   case CAPABILITIES_RES_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET | DEBUG_AUDIO, 3, "Received CAPABILITIES_RES_MESSAGE from %s, count %d, codec data\n",
         d->name, letohl(req->data.caps.count));
      res = handle_capabilities_res_message(req, s);
      break;
   case SPEED_DIAL_STAT_REQ_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SPEED_DIAL_STAT_REQ_MESSAGE from %s, sdNum %d\n",
         d->name, letohl(req->data.speeddialreq.speedDialNumber));
      if ( (sd = find_speeddial_by_instance(s->device, letohl(req->data.speeddialreq.speedDialNumber), 0)) ) {
         transmit_speeddialstatres(d, sd);
      }
      break;
   case LINE_STATE_REQ_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received LINE_STATE_REQ_MESSAGE from %s, lineNum %d\n",
         d->name, letohl(req->data.line.lineNumber));
      transmit_linestatres(d, letohl(req->data.line.lineNumber));
      break;
   case TIME_DATE_REQ_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received TIME_DATE_REQ_MESSAGE from %s\n", d->name);
      transmit_definetimedate(d);
      break;
   case BUTTON_TEMPLATE_REQ_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received BUTTON_TEMPLATE_REQ_MESSAGE from %s\n", d->name);
      res = handle_button_template_req_message(req, s);
      break;
   case VERSION_REQ_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received VERSION_REQ_MESSAGE from %s\n", d->name);
      transmit_versionres(d);
      break;
   case SERVER_REQUEST_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SERVER_REQUEST_MESSAGE from %s\n", d->name);
      transmit_serverres(d);
      break;
   case ALARM_MESSAGE:
      /* no response necessary */
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received ALARM_MESSAGE from %s, alarm %s\n",
         d->name, req->data.alarm.displayMessage);
      break;
   case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
      /* SKINNY_PACKETDEBUG handled in handle_open_receive_channel_ack_message */
      res = handle_open_receive_channel_ack_message(req, s);
      break;
   case SOFT_KEY_SET_REQ_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFT_KEY_SET_REQ_MESSAGE from %s\n", d->name);
      transmit_softkeysetres(d);
      transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
      break;
   case SOFT_KEY_EVENT_MESSAGE:
      /* SKINNY_PACKETDEBUG handled in handle_soft_key_event_message */
      res = handle_soft_key_event_message(req, s);
      break;
   case UNREGISTER_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received UNREGISTER_MESSAGE from %s\n", d->name);
      res = skinny_unregister(req, s);
      break;
   case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFT_KEY_TEMPLATE_REQ_MESSAGE from %s\n", d->name);
      transmit_softkeytemplateres(d);
      break;
   case HEADSET_STATUS_MESSAGE:
      /* XXX umm...okay?  Why do I care? */
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received HEADSET_STATUS_MESSAGE from %s\n", d->name);
      break;
   case REGISTER_AVAILABLE_LINES_MESSAGE:
      /* XXX I have no clue what this is for, but my phone was sending it, so... */
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received REGISTER_AVAILABLE_LINES_MESSAGE from %s\n", d->name);
      break;
   default:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received UNKNOWN_MESSAGE(%x) from %s\n", letohl(req->e), d->name);
      break;
   }
   if (res >= 0 && req)
      ast_free(req);
   return res;
}
static int handle_offhook_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5941 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, ast_channel_name(), ast_channel_tech_pvt(), ast_debug, AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_log(), AST_STATE_DOWN, ast_verb, skinny_subchannel::calldirection, skinny_req::data, skinnysession::device, find_line_by_instance(), find_subchannel_by_instance_reference(), offhook_message::instance, letohl, skinny_subchannel::line, LOG_WARNING, skinny_data::offhook, skinny_subchannel::owner, offhook_message::reference, setsubstate(), SKINNY_INCOMING, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_OUTGOING, SKINNY_RING_OFF, STIMULUS_LINE, sub, skinny_subchannel::substate, SUBSTATE_CONNECTED, SUBSTATE_HOLD, SUBSTATE_OFFHOOK, transmit_definetimedate(), transmit_lamp_indication(), and transmit_ringer_mode().

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l = NULL;
   struct skinny_subchannel *sub = NULL;
   struct ast_channel *c;
   int instance;
   int reference;

   instance = letohl(req->data.offhook.instance);
   reference = letohl(req->data.offhook.reference);

   if (d->hookstate == SKINNY_OFFHOOK) {
      ast_verb(3, "Got offhook message when device (%s) already offhook\n", d->name);
      return 0;
   }

   if (reference) {
      sub = find_subchannel_by_instance_reference(d, instance, reference);
      if (sub) {
         l = sub->line;
      }
   }
   if (!sub) {
      if (instance) {
         l = find_line_by_instance(d, instance);
      } else {
         l = d->activeline;
      }
      sub = l->activesub;
   }

   transmit_ringer_mode(d, SKINNY_RING_OFF);
   d->hookstate = SKINNY_OFFHOOK;

   ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);

   if (sub && sub->substate == SUBSTATE_HOLD) {
      return 1;
   }

   transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);

   if (sub && sub->calldirection == SKINNY_INCOMING) {
      setsubstate(sub, SUBSTATE_CONNECTED);
   } else {
      /* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
      transmit_definetimedate(d);

      if (sub && sub->owner) {
         ast_debug(1, "Current sub [%s] already has owner\n", ast_channel_name(sub->owner));
      } else {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
         if (c) {
            setsubstate(ast_channel_tech_pvt(c), SUBSTATE_OFFHOOK);
         } else {
            ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
         }
      }
   }
   return 1;
}
static int handle_onhook_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 6004 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), AST_STATE_RING, skinny_req::data, skinnysession::device, dumpsub(), find_subchannel_by_instance_reference(), handle_transfer_button(), onhook_message::instance, letohl, skinny_subchannel::line, skinny_data::onhook, skinny_subchannel::owner, onhook_message::reference, SKINNY_ONHOOK, sub, transmit_definetimedate(), and skinny_subchannel::xferor.

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l;
   struct skinny_subchannel *sub;
   int instance;
   int reference;

   instance = letohl(req->data.onhook.instance);
   reference = letohl(req->data.onhook.reference);

   if (instance && reference) {
      sub = find_subchannel_by_instance_reference(d, instance, reference);
      if (!sub) {
         return 0;
      }
      l = sub->line;
   } else {
      l = d->activeline;
      sub = l->activesub;
      if (!sub) {
         return 0;
      }
   }

   if (d->hookstate == SKINNY_ONHOOK) {
      /* Something else already put us back on hook */
      /* Not ideal, but let's send updated time anyway, as it clears the display */
      transmit_definetimedate(d);
      return 0;
   }

   if (l->transfer && sub->xferor && ast_channel_state(sub->owner) >= AST_STATE_RING) {
      /* We're allowed to transfer, we have two active calls and
         we made at least one of the calls.  Let's try and transfer */
      handle_transfer_button(sub);
      return 0;
   }
   
   ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
   
   dumpsub(sub, 0);

   d->hookstate = SKINNY_ONHOOK;
   
   /* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
   transmit_definetimedate(d);

   return 1;
}
static int handle_open_receive_channel_ack_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 6241 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), ast_getformatname(), ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_local_address(), ast_rtp_instance_set_remote_address(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, skinny_subchannel::callid, open_receive_channel_ack_message_ip4::callReference, open_receive_channel_ack_message_ip6::callReference, skinny_line::cap, ast_format_list::cur_ms, skinny_req::data, skinnysession::device, find_subchannel_by_reference(), ast_format_list::format, open_receive_channel_ack_message_ip4::ipAddr, open_receive_channel_ack_message_ip6::ipAddr, letohl, skinny_subchannel::line, LOG_ERROR, skinny_data::openreceivechannelack_ip4, skinny_data::openreceivechannelack_ip6, skinny_device::ourip, open_receive_channel_ack_message_ip4::port, open_receive_channel_ack_message_ip6::port, skinny_subchannel::rtp, SKINNY_DEBUG, status, open_receive_channel_ack_message_ip4::status, open_receive_channel_ack_message_ip6::status, sub, and transmit_startmediatransmission().

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l;
   struct skinny_subchannel *sub;
   struct ast_format_list fmt;
   struct sockaddr_in sin = { 0, };
   struct sockaddr_in us = { 0, };
   struct ast_sockaddr sin_tmp;
   struct ast_sockaddr us_tmp;
   struct ast_format tmpfmt;
   uint32_t addr;
   int port;
   int status;
   int callid;

   status = (d->protocolversion<17) ? letohl(req->data.openreceivechannelack_ip4.status) : letohl(req->data.openreceivechannelack_ip6.status);

   if (status) {
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received OPEN_RECEIVE_CHANNEL_ACK_MESSAGE from %s, status %d\n",
         d->name, status);
      ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
      return 0;
   }

   if (d->protocolversion<17) {
      addr = req->data.openreceivechannelack_ip4.ipAddr;
      port = letohl(req->data.openreceivechannelack_ip4.port);
      callid = letohl(req->data.openreceivechannelack_ip4.callReference);
   } else {
      memcpy(&addr, &req->data.openreceivechannelack_ip6.ipAddr, sizeof(addr));
      port = letohl(req->data.openreceivechannelack_ip6.port);
      callid = letohl(req->data.openreceivechannelack_ip6.callReference);
   }

   sin.sin_family = AF_INET;
   sin.sin_addr.s_addr = addr;
   sin.sin_port = htons(port);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Received OPEN_RECEIVE_CHANNEL_ACK_MESSAGE from %s, status %d, callid %d, ip %s:%d\n",
      d->name, status, callid, ast_inet_ntoa(sin.sin_addr), port);

   sub = find_subchannel_by_reference(d, callid);

   if (!sub) {
      ast_log(LOG_ERROR, "Open Receive Channel Failure - can't find sub for %d\n", callid);
      return 0;
   }

   l = sub->line;

   if (sub->rtp) {
      ast_sockaddr_from_sin(&sin_tmp, &sin);
      ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
      ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
      ast_sockaddr_to_sin(&us_tmp, &us);
      us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
   } else {
      ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
      return 0;
   }

   SKINNY_DEBUG(DEBUG_PACKET, 4, "device ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
   SKINNY_DEBUG(DEBUG_PACKET, 4, "asterisk ipaddr = %s:%d\n", ast_inet_ntoa(us.sin_addr), ntohs(us.sin_port));

   ast_best_codec(l->cap, &tmpfmt);
   fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);

   SKINNY_DEBUG(DEBUG_PACKET, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);

   transmit_startmediatransmission(d, sub, us, fmt);

   return 1;
}
static char* handle_skinny_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3396 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli_entry::args, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, skinny_reload(), and ast_cli_entry::usage.

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "skinny reload";
      e->usage =
         "Usage: skinny reload\n"
         "       Reloads the chan_skinny configuration\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }
   
   if (a->argc != e->args)
      return CLI_SHOWUSAGE;

   skinny_reload();
   return CLI_SUCCESS;

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

Definition at line 3461 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli_args::argv, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_skinny_reset(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, skinny_device::session, transmit_reset(), ast_cli_entry::usage, and ast_cli_args::word.

{
   struct skinny_device *d;

   switch (cmd) {
   case CLI_INIT:
      e->command = "skinny reset";
      e->usage =
         "Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
         "       Causes a Skinny device to reset itself, optionally with a full restart\n";
      return NULL;
   case CLI_GENERATE:
      return complete_skinny_reset(a->line, a->word, a->pos, a->n);
   }

   if (a->argc < 3 || a->argc > 4)
      return CLI_SHOWUSAGE;

   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, d, list) {
      int fullrestart = 0;
      if (!strcasecmp(a->argv[2], d->id) || !strcasecmp(a->argv[2], d->name) || !strcasecmp(a->argv[2], "all")) {
         if (!(d->session))
            continue;

         if (a->argc == 4 && !strcasecmp(a->argv[3], "restart"))
            fullrestart = 1;
         
         transmit_reset(d, fullrestart);
      }
   }
   AST_LIST_UNLOCK(&devices);
   return CLI_SUCCESS;
}
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 3832 of file chan_skinny.c.

References _skinny_show_device(), ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, complete_skinny_show_device(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "skinny show device";
      e->usage =
         "Usage: skinny show device <DeviceId|DeviceName>\n"
         "       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
      return NULL;
   case CLI_GENERATE:
      return complete_skinny_show_device(a->line, a->word, a->pos, a->n);
   }

   return _skinny_show_device(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
}
static char* handle_skinny_show_devices ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3698 of file chan_skinny.c.

References _skinny_show_devices(), ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

{

   switch (cmd) {
   case CLI_INIT:
      e->command = "skinny show devices";
      e->usage =
         "Usage: skinny show devices\n"
         "       Lists all devices known to the Skinny subsystem.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   return _skinny_show_devices(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
}
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 4133 of file chan_skinny.c.

References _skinny_show_line(), ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, complete_skinny_show_line(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "skinny show line";
      e->usage =
         "Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
         "       List all lineinformation of a specific line known to the Skinny subsystem.\n";
      return NULL;
   case CLI_GENERATE:
      return complete_skinny_show_line(a->line, a->word, a->pos, a->n);
   }

   return _skinny_show_line(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
}
static char* handle_skinny_show_lines ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3946 of file chan_skinny.c.

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

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "skinny show lines [verbose]";
      e->usage =
         "Usage: skinny show lines\n"
         "       Lists all lines known to the Skinny subsystem.\n"
         "       If 'verbose' is specified, the output includes\n"
         "       information about subs for each line.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc == e->args) {
      if (strcasecmp(a->argv[e->args-1], "verbose")) {
         return CLI_SHOWUSAGE;
      }
   } else if (a->argc != e->args - 1) {
      return CLI_SHOWUSAGE;
   }

   return _skinny_show_lines(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
}
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 4150 of file chan_skinny.c.

References ast_cli_args::argc, ast_cli(), AST_CLI_YESNO, 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, ast_jb_conf::target_extra, and ast_cli_entry::usage.

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "skinny show settings";
      e->usage =
         "Usage: skinny show settings\n"
         "       Lists all global configuration settings of the Skinny subsystem.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }  

   if (a->argc != 3)
      return CLI_SHOWUSAGE;

   ast_cli(a->fd, "\nGlobal Settings:\n");
   ast_cli(a->fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
   ast_cli(a->fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
   ast_cli(a->fd, "  KeepAlive:              %d\n", keep_alive);
   ast_cli(a->fd, "  Date Format:            %s\n", date_format);
   ast_cli(a->fd, "  Voice Mail Extension:   %s\n", S_OR(vmexten, "(not set)"));
   ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
   ast_cli(a->fd, "  Jitterbuffer enabled:   %s\n", AST_CLI_YESNO(ast_test_flag(&global_jbconf, AST_JB_ENABLED)));
    if (ast_test_flag(&global_jbconf, AST_JB_ENABLED)) {
      ast_cli(a->fd, "  Jitterbuffer forced:    %s\n", AST_CLI_YESNO(ast_test_flag(&global_jbconf, AST_JB_FORCED)));
      ast_cli(a->fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
      ast_cli(a->fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
      ast_cli(a->fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
      if (!strcasecmp(global_jbconf.impl, "adaptive")) {
         ast_cli(a->fd, "  Jitterbuffer tgt extra: %ld\n", global_jbconf.target_extra);
      }
      ast_cli(a->fd, "  Jitterbuffer log:       %s\n", AST_CLI_YESNO(ast_test_flag(&global_jbconf, AST_JB_LOG)));
   }

   return CLI_SUCCESS;
}
static int handle_soft_key_event_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 6349 of file chan_skinny.c.

References activatesub(), skinny_line::activesub, ast_bridged_channel(), ast_channel_tech_pvt(), AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_log(), ast_masq_park_call(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::calldirection, skinny_subchannel::callid, soft_key_event_message::callreference, skinny_req::data, skinnysession::device, dialandactivatesub(), skinny_subchannel::dialer_sched, dumpsub(), skinny_subchannel::exten, skinny_subline::exten, find_line_by_instance(), find_subchannel_by_instance_reference(), find_subline_by_callid(), handle_callforward_button(), handle_transfer_button(), soft_key_event_message::instance, KEYDEF_OFFHOOK, len(), letohl, LOG_WARNING, skinny_subchannel::owner, setsubstate(), SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_DEBUG, skinny_dialer_cb(), SKINNY_DIALTONE, SKINNY_INCOMING, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_OUTGOING, SKINNY_RING_OFF, skinny_sched_add(), skinny_sched_del(), SKINNY_SPEAKERON, 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, STIMULUS_DND, STIMULUS_LINE, sub, skinny_subline::sub, skinny_subchannel::subline, SUBSTATE_CONNECTED, SUBSTATE_HOLD, SUBSTATE_OFFHOOK, ast_channel::tech_pvt, transmit_backspace(), transmit_definetimedate(), transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_start_tone(), and skinny_subchannel::xferor.

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l;
   struct skinny_subchannel *sub = NULL;
   struct ast_channel *c;
   int event;
   int instance;
   int callreference;

   event = letohl(req->data.softkeyeventmessage.softKeyEvent);
   instance = letohl(req->data.softkeyeventmessage.instance);
   callreference = letohl(req->data.softkeyeventmessage.callreference);

   if (instance) {
      l = find_line_by_instance(d, instance);
      if (callreference) {
         sub = find_subchannel_by_instance_reference(d, instance, callreference);
      } else {
         sub = find_subchannel_by_instance_reference(d, instance, d->lastcallreference);
      }
   } else {
      l = find_line_by_instance(d, d->lastlineinstance);
   }

   if (!l) {
      ast_log(LOG_WARNING,  "Received Softkey Event: %d(%d/%d) but can't find line\n", event, instance, callreference);
      return 0;
   }

   ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);

   switch(event) {
   case SOFTKEY_NONE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_NONE from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      break;
   case SOFTKEY_REDIAL:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_REDIAL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (ast_strlen_zero(l->lastnumberdialed)) {
         ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found. Ignoring button.\n");
         break;
      }

      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = ast_channel_tech_pvt(c);
         dialandactivatesub(sub, l->lastnumberdialed);
      }
      break;
   case SOFTKEY_NEWCALL:  /* Actually the DIAL softkey */
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_NEWCALL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      /* New Call ALWAYS gets a new sub-channel */
      c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      sub = ast_channel_tech_pvt(c);

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         activatesub(sub, SUBSTATE_OFFHOOK);
      }
      break;
   case SOFTKEY_HOLD:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_HOLD from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (sub) {
         setsubstate(sub, SUBSTATE_HOLD);
      } else { /* No sub, maybe an SLA call */
         struct skinny_subline *subline;
         if ((subline = find_subline_by_callid(d, callreference))) {
            setsubstate(subline->sub, SUBSTATE_HOLD);
         }
      }

      break;
   case SOFTKEY_TRNSFER:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_TRNSFER from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      if (l->transfer)
         handle_transfer_button(sub);
      else
         transmit_displaynotify(d, "Transfer disabled", 10);

      break;
   case SOFTKEY_DND:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_DND from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      /* Do not disturb */
      if (l->dnd != 0){
         ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
         l->dnd = 0;
         transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
         transmit_displaynotify(d, "DnD disabled", 10);
      } else {
         ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
         l->dnd = 1;
         transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
         transmit_displaynotify(d, "DnD enabled", 10);
      }
      break;
   case SOFTKEY_CFWDALL:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_CFWDALL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = ast_channel_tech_pvt(c);
         l->activesub = sub;
         handle_callforward_button(sub, SKINNY_CFWD_ALL);
      }
      break;
   case SOFTKEY_CFWDBUSY:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_CFWDBUSY from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = ast_channel_tech_pvt(c);
         l->activesub = sub;
         handle_callforward_button(sub, SKINNY_CFWD_BUSY);
      }
      break;
   case SOFTKEY_CFWDNOANSWER:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_CFWDNOANSWER from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

#if 0 /* Not sure how to handle this yet */
      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = c->tech_pvt;
         l->activesub = sub;
         handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
      }
#endif
      break;
   case SOFTKEY_BKSPC:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_BKSPC from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      if (sub->dialer_sched && !skinny_sched_del(sub->dialer_sched, sub)) {
         size_t len;
         sub->dialer_sched = 0;
         len = strlen(sub->exten);
         if (len > 0) {
            sub->exten[len-1] = '\0';
            if (len == 1) {
               transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
               transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
            }
            transmit_backspace(d, l->instance, sub->callid);
         }
         sub->dialer_sched = skinny_sched_add(gendigittimeout, skinny_dialer_cb, sub);
      }
      break;
   case SOFTKEY_ENDCALL:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_ENDCALL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (l->transfer && sub && sub->xferor && ast_channel_state(sub->owner) >= AST_STATE_RING) {
         /* We're allowed to transfer, we have two active calls and
             we made at least one of the calls.  Let's try and transfer */
         handle_transfer_button(sub);
         return 0;
      }
   
      ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);

      if (sub) {
         dumpsub(sub, 1);
      } else { /* No sub, maybe an SLA call */
         struct skinny_subline *subline;
         if ((subline = find_subline_by_callid(d, callreference))) {
            dumpsub(subline->sub, 1);
         }
      }

      d->hookstate = SKINNY_ONHOOK;
   
      /* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
      transmit_definetimedate(d);

      break;
   case SOFTKEY_RESUME:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_RESUME from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (sub) {
         activatesub(sub, SUBSTATE_CONNECTED);
      } else { /* No sub, maybe an inactive SLA call */
         struct skinny_subline *subline;
         subline = find_subline_by_callid(d, callreference);
         c = skinny_new(l, subline, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
         if (!c) {
            ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
         } else {
            sub = ast_channel_tech_pvt(c);
            dialandactivatesub(sub, subline->exten);
         }
      }
      break;
   case SOFTKEY_ANSWER:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_ANSWER from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      transmit_ringer_mode(d, SKINNY_RING_OFF);
      transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
      if (d->hookstate == SKINNY_ONHOOK) {
         transmit_speaker_mode(d, SKINNY_SPEAKERON);
         d->hookstate = SKINNY_OFFHOOK;
      }

      if (sub && sub->calldirection == SKINNY_INCOMING) {
         activatesub(sub, SUBSTATE_CONNECTED);
      }
      break;
   case SOFTKEY_INFO:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_INFO from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      break;
   case SOFTKEY_CONFRN:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_CONFRN from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      /* XXX determine the best way to pull off a conference.  Meetme? */
      break;
   case SOFTKEY_PARK:
      {
      int extout;
      char message[32];

      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_PARK from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if ((sub && sub->owner) && (ast_channel_state(sub->owner) ==  AST_STATE_UP)){
         c = sub->owner;
         if (ast_bridged_channel(c)) {
            if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
               snprintf(message, sizeof(message), "Call Parked at: %d", extout);
               transmit_displaynotify(d, message, 10);
            } else {
               transmit_displaynotify(d, "Call Park failed", 10);
            }
         } else {
            transmit_displaynotify(d, "Call Park not available", 10);
         }
      } else {
         transmit_displaynotify(d, "Call Park not available", 10);
      }
      break;
      }
   case SOFTKEY_JOIN:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_JOIN from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      /* this is SLA territory, should not get here unless there is a meetme at subline */
      {
         struct skinny_subline *subline;
         subline = find_subline_by_callid(d, callreference);
         c = skinny_new(l, subline, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
         if (!c) {
            ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
         } else {
            sub = ast_channel_tech_pvt(c);
            dialandactivatesub(sub, subline->exten);
         }
      }
      break;
   case SOFTKEY_MEETME:
      /* XXX How is this different from CONFRN? */
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_MEETME from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      break;
   case SOFTKEY_PICKUP:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_PICKUP from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      break;
   case SOFTKEY_GPICKUP:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_GPICKUP from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      break;
   default:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_UNKNOWN(%d) from %s, inst %d, callref %d\n",
         event, d->name, instance, callreference);
      break;
   }

   return 1;
}
static int handle_stimulus_message ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 5687 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, ast_bridged_channel(), ast_channel_name(), ast_channel_tech_pvt(), ast_debug, AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_log(), ast_masq_park_call(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::calldirection, stimulus_message::callreference, skinny_req::data, skinnysession::device, dialandactivatesub(), skinny_speeddial::exten, find_line_by_instance(), find_speeddial_by_instance(), find_subchannel_by_instance_reference(), handle_callforward_button(), handle_hold_button(), handle_transfer_button(), letohl, skinny_subchannel::line, LOG_WARNING, skinny_subchannel::owner, setsubstate(), SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_DEBUG, SKINNY_INCOMING, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_OUTGOING, SKINNY_RING_OFF, SKINNY_SPEAKERON, 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, sub, skinny_subchannel::substate, SUBSTATE_CONNECTED, SUBSTATE_OFFHOOK, SUBSTATE_UNSET, ast_channel::tech_pvt, transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), and transmit_speaker_mode().

Referenced by handle_message().

{
   struct skinny_device *d = s->device;
   struct skinny_line *l;
   struct skinny_subchannel *sub;
   /*struct skinny_speeddial *sd;*/
   struct ast_channel *c;
   int event;
   int instance;
   int callreference;
   /*int res = 0;*/

   event = letohl(req->data.stimulus.stimulus);
   instance = letohl(req->data.stimulus.stimulusInstance);
   callreference = letohl(req->data.stimulus.callreference);

   /*  Note that this call should be using the passed in instance and callreference */
   sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);

   if (!sub) {
      l = find_line_by_instance(d, d->lastlineinstance);
      if (!l) {
         return 0;
      }
      sub = l->activesub;
   } else {
      l = sub->line;
   }

   switch(event) {
   case STIMULUS_REDIAL:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_REDIAL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (ast_strlen_zero(l->lastnumberdialed)) {
         ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found. Ignoring button.\n");
         break;
      }

      c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = ast_channel_tech_pvt(c);
         l = sub->line;
         dialandactivatesub(sub, l->lastnumberdialed);
      }
      break;
   case STIMULUS_SPEEDDIAL:
       {
      struct skinny_speeddial *sd;

      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_SPEEDDIAL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (!(sd = find_speeddial_by_instance(d, instance, 0))) {
         return 0;
      }

      if (!sub || !sub->owner)
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      else
         c = sub->owner;

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = ast_channel_tech_pvt(c);
         dialandactivatesub(sub, sd->exten);
      }
       }
      break;
   case STIMULUS_HOLD:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_HOLD from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      handle_hold_button(sub);
      break;
   case STIMULUS_TRANSFER:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_TRANSFER from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      if (l->transfer)
         handle_transfer_button(sub);
      else
         transmit_displaynotify(d, "Transfer disabled", 10);
      break;
   case STIMULUS_CONFERENCE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_CONFERENCE from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      /* XXX determine the best way to pull off a conference.  Meetme? */
      break;
   case STIMULUS_VOICEMAIL:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_VOICEMAIL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }
      
      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
         break;
      }
      
      sub = ast_channel_tech_pvt(c);
      if (sub->substate == SUBSTATE_UNSET || sub->substate == SUBSTATE_OFFHOOK){
         dialandactivatesub(sub, l->vmexten);
      }
      break;
   case STIMULUS_CALLPARK:
      {
      int extout;
      char message[32];

      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_CALLPARK from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if ((sub && sub->owner) && (ast_channel_state(sub->owner) ==  AST_STATE_UP)){
         c = sub->owner;
         if (ast_bridged_channel(c)) {
            if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
               snprintf(message, sizeof(message), "Call Parked at: %d", extout);
               transmit_displaynotify(d, message, 10);
            } else {
               transmit_displaynotify(d, "Call Park failed", 10);
            }
         } else {
            transmit_displaynotify(d, "Call Park not available", 10);
         }
      } else {
         transmit_displaynotify(d, "Call Park not available", 10);
      }
      break;
      }
   case STIMULUS_DND:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_DND from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      /* Do not disturb */
      if (l->dnd != 0){
         ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
         l->dnd = 0;
         transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
         transmit_displaynotify(d, "DnD disabled", 10);
      } else {
         ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
         l->dnd = 1;
         transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
         transmit_displaynotify(d, "DnD enabled", 10);
      }
      break;
   case STIMULUS_FORWARDALL:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_FORWARDALL from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = ast_channel_tech_pvt(c);
         handle_callforward_button(sub, SKINNY_CFWD_ALL);
      }
      break;
   case STIMULUS_FORWARDBUSY:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_FORWARDBUSY from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = ast_channel_tech_pvt(c);
         handle_callforward_button(sub, SKINNY_CFWD_BUSY);
      }
      break;
   case STIMULUS_FORWARDNOANSWER:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_FORWARDNOANSWER from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

#if 0 /* Not sure how to handle this yet */
      if (!sub || !sub->owner) {
         c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      } else {
         c = sub->owner;
      }

      if (!c) {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      } else {
         sub = c->tech_pvt;
         handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
      }
#endif
      break;
   case STIMULUS_DISPLAY:
      /* Not sure what this is */
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_DISPLAY from %s, inst %d, callref %d\n",
         d->name, instance, callreference);
      break;
   case STIMULUS_LINE:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received STIMULUS_LINE from %s, inst %d, callref %d\n",
         d->name, instance, callreference);

      l = find_line_by_instance(d, instance);

      if (!l) {
         return 0;
      }

      d->activeline = l;

      /* turn the speaker on */
      transmit_speaker_mode(d, SKINNY_SPEAKERON);
      transmit_ringer_mode(d, SKINNY_RING_OFF);
      transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);

      d->hookstate = SKINNY_OFFHOOK;

      if (sub && sub->calldirection == SKINNY_INCOMING) {
         setsubstate(sub, SUBSTATE_CONNECTED);
      } else {
         if (sub && sub->owner) {
            ast_debug(1, "Current subchannel [%s] already has owner\n", ast_channel_name(sub->owner));
         } else {
            c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
            if (c) {
               setsubstate(ast_channel_tech_pvt(c), SUBSTATE_OFFHOOK);
            } else {
               ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
            }
         }
      }
      break;
   default:
      SKINNY_DEBUG(DEBUG_PACKET, 3, "Received UNKNOWN_STIMULUS(%d) from %s, inst %d, callref %d\n",
         event, d->name, instance, callreference);
      break;
   }
   ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);

   return 1;
}
static int handle_transfer_button ( struct skinny_subchannel sub) [static]

Definition at line 5485 of file chan_skinny.c.

References ast_channel_tech_pvt(), ast_log(), AST_STATE_DOWN, ast_verbose(), skinny_subchannel::blindxfer, skinny_line::device, skinny_subchannel::line, LOG_WARNING, skinny_subchannel::owner, skinny_subchannel::related, skinny_device::session, setsubstate(), skinny_new(), SKINNY_OUTGOING, skinny_transfer(), sub, skinny_subchannel::substate, SUBSTATE_HOLD, SUBSTATE_OFFHOOK, and skinny_subchannel::xferor.

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

{
   struct skinny_line *l;
   struct skinny_device *d;
   struct skinny_subchannel *newsub;
   struct ast_channel *c;

   if (!sub) {
      ast_verbose("Transfer: No subchannel to transfer\n");
      return -1;
   }

   l = sub->line;
   d = l->device;

   if (!d->session) {
      ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
      return -1;
   }

   if (!sub->related) {
      /* Another sub has not been created so this must be first XFER press */
      if (!(sub->substate == SUBSTATE_HOLD)) {
         setsubstate(sub, SUBSTATE_HOLD);
      }
      c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_OUTGOING);
      if (c) {
         newsub = ast_channel_tech_pvt(c);
         /* point the sub and newsub at each other so we know they are related */
         newsub->related = sub;
         sub->related = newsub;
         newsub->xferor = 1;
         setsubstate(newsub, SUBSTATE_OFFHOOK);
      } else {
         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
      }
   } else {
      /* We already have a related sub so we can either complete XFER or go into BLINDXFER (or cancel BLINDXFER */
      if (sub->blindxfer) {
         /* toggle blindxfer off */
         sub->blindxfer = 0;
         sub->related->blindxfer = 0;
         /* we really need some indications */
      } else {
         /* We were doing attended transfer */
         if (ast_channel_state(sub->owner) == AST_STATE_DOWN || ast_channel_state(sub->related->owner) == AST_STATE_DOWN) {
            /* one of the subs so we cant transfer yet, toggle blindxfer on */
            sub->blindxfer = 1;
            sub->related->blindxfer = 1;
         } else {
            /* big assumption we have two channels, lets transfer */
            skinny_transfer(sub);
         }
      }
   }
   return 0;
}
static int load_module ( void  ) [static]

Definition at line 7952 of file chan_skinny.c.

References ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_add_all_by_type(), ast_format_cap_alloc(), ast_format_set(), AST_FORMAT_TYPE_AUDIO, AST_FORMAT_ULAW, ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_sched_context_create(), ast_sched_context_destroy(), ast_sched_start_thread(), ast_channel_tech::capabilities, cli_skinny, config_load(), EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, htolel, LOG_ERROR, LOG_WARNING, manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), skinny_rtp_glue, skinny_tech, and soft_key_template_definition::softKeyEvent.

{
   int res = 0;
   struct ast_format tmpfmt;
   if (!(default_cap = ast_format_cap_alloc())) {
      return AST_MODULE_LOAD_DECLINE;
   }
   if (!(skinny_tech.capabilities = ast_format_cap_alloc())) {
      return AST_MODULE_LOAD_DECLINE;
   }

   ast_format_cap_add_all_by_type(skinny_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
   ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
   ast_format_cap_add(default_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));

   for (; res < ARRAY_LEN(soft_key_template_default); res++) {
      soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
   }
   /* load and parse config */
   res = config_load();
   if (res == -1) {
      return AST_MODULE_LOAD_DECLINE;
   }

   /* Make sure we can register our skinny channel type */
   if (ast_channel_register(&skinny_tech)) {
      ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
      return -1;
   }

   ast_rtp_glue_register(&skinny_rtp_glue);
   ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));

   ast_manager_register_xml("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices);
   ast_manager_register_xml("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device);
   ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
   ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);

   sched = ast_sched_context_create();
   if (!sched) {
      ast_log(LOG_WARNING, "Unable to create schedule context\n");
      return AST_MODULE_LOAD_FAILURE;
   }
   if (ast_sched_start_thread(sched)) {
      ast_sched_context_destroy(sched);
      sched = NULL;
      return AST_MODULE_LOAD_FAILURE;
   }

   return AST_MODULE_LOAD_SUCCESS;
}
static int manager_skinny_show_device ( struct mansession s,
const struct message m 
) [static]

Definition at line 3811 of file chan_skinny.c.

References _skinny_show_device(), ast_strlen_zero(), astman_append(), astman_get_header(), and astman_send_error().

Referenced by load_module().

{
   const char *a[4];
   const char *device;

   device = astman_get_header(m, "Device");
   if (ast_strlen_zero(device)) {
      astman_send_error(s, m, "Device: <name> missing.");
      return 0;
   }
   a[0] = "skinny";
   a[1] = "show";
   a[2] = "device";
   a[3] = device;

   _skinny_show_device(1, -1, s, m, 4, a);
   astman_append(s, "\r\n\r\n" );
   return 0;
}
static int manager_skinny_show_devices ( struct mansession s,
const struct message m 
) [static]

Show SKINNY devices in the manager API.

Definition at line 3675 of file chan_skinny.c.

References _skinny_show_devices(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_listack(), and total.

Referenced by load_module().

{
   const char *id = astman_get_header(m, "ActionID");
   const char *a[] = {"skinny", "show", "devices"};
   char idtext[256] = "";
   int total = 0;

   if (!ast_strlen_zero(id))
      snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);

   astman_send_listack(s, m, "Device status list will follow", "start");
   /* List the devices in separate manager events */
   _skinny_show_devices(-1, &total, s, m, 3, a);
   /* Send final confirmation */
   astman_append(s,
   "Event: DevicelistComplete\r\n"
   "EventList: Complete\r\n"
   "ListItems: %d\r\n"
   "%s"
   "\r\n", total, idtext);
   return 0;
}
static int manager_skinny_show_line ( struct mansession s,
const struct message m 
) [static]

Definition at line 4112 of file chan_skinny.c.

References _skinny_show_line(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), and skinny_subchannel::line.

Referenced by load_module().

{
   const char *a[4];
   const char *line;

   line = astman_get_header(m, "Line");
   if (ast_strlen_zero(line)) {
      astman_send_error(s, m, "Line: <name> missing.");
      return 0;
   }
   a[0] = "skinny";
   a[1] = "show";
   a[2] = "line";
   a[3] = line;

   _skinny_show_line(1, -1, s, m, 4, a);
   astman_append(s, "\r\n\r\n" );
   return 0;
}
static int manager_skinny_show_lines ( struct mansession s,
const struct message m 
) [static]

Show Skinny lines in the manager API.

Definition at line 3923 of file chan_skinny.c.

References _skinny_show_lines(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_listack(), and total.

Referenced by load_module().

{
   const char *id = astman_get_header(m, "ActionID");
   const char *a[] = {"skinny", "show", "lines"};
   char idtext[256] = "";
   int total = 0;

   if (!ast_strlen_zero(id))
      snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);

   astman_send_listack(s, m, "Line status list will follow", "start");
   /* List the lines in separate manager events */
   _skinny_show_lines(-1, &total, s, m, 3, a);
   /* Send final confirmation */
   astman_append(s,
   "Event: LinelistComplete\r\n"
   "EventList: Complete\r\n"
   "ListItems: %d\r\n"
   "%s"
   "\r\n", total, idtext);
   return 0;
}
static void mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 3113 of file chan_skinny.c.

References ast_event_get_ie_uint(), AST_EVENT_IE_NEWMSGS, AST_LIST_TRAVERSE, ast_verb, skinny_line::device, skinny_device::lines, skinny_line::newmsgs, skinny_device::session, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, STIMULUS_VOICEMAIL, and transmit_lamp_indication().

Referenced by config_line(), and skinny_register().

{
   struct skinny_line *l = userdata;
   struct skinny_device *d = l->device;
   struct skinny_line *l2;
   int dev_msgs = 0;
   
   if (!d || !d->session) {
      return;
   }

   if (event) {
      l->newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
   }

   if (l->newmsgs) {
      transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
   } else {
      transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
   }

   /* find out wether the device lamp should be on or off */
   AST_LIST_TRAVERSE(&d->lines, l2, list) {
      if (l2->newmsgs) {
         dev_msgs++;
      }
   }

   if (dev_msgs) {
      transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, d->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
   } else {
      transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, SKINNY_LAMP_OFF);
   }
   ast_verb(3, "Skinny mwi_event_cb found %d new messages\n", l->newmsgs);
}
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 3586 of file chan_skinny.c.

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

Referenced by _skinny_show_line().

{
   int x;
   struct ast_format tmpfmt;

   for(x = 0; x < 32 ; x++) {
      ast_codec_pref_index(pref, x, &tmpfmt);
      if (!tmpfmt.id)
         break;
      ast_cli(fd, "%s", ast_getformatname(&tmpfmt));
      ast_cli(fd, ":%d", pref->framing[x]);
      if (x < 31 && ast_codec_pref_index(pref, x + 1, &tmpfmt))
         ast_cli(fd, ",");
   }
   if (!x)
      ast_cli(fd, "none");
}
static void push_callinfo ( struct skinny_subline subline,
struct skinny_subchannel sub 
) [static]

Definition at line 2368 of file chan_skinny.c.

References ast_channel_caller(), ast_channel_connected(), ast_verb, skinny_subchannel::calldirection, skinny_subline::callid, skinny_line::device, skinny_subchannel::line, skinny_subline::line, skinny_subchannel::owner, S_COR, SKINNY_INCOMING, SKINNY_OUTGOING, and transmit_callinfo().

Referenced by setsubstate().

{
   struct ast_channel *ast;
   struct skinny_device *d;
   struct skinny_line *l;
   char *fromname;
   char *fromnum;
   char *toname;
   char *tonum;

   if (!sub || !sub->owner || !sub->line || !sub->line->device) {
      return;
   }
   
   ast = sub->owner;
   l = sub->line;
   d = l->device;
   
   if (sub->calldirection == SKINNY_INCOMING) {
      fromname = S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, "");
      fromnum = S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, "");
      toname = S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, "");
      tonum = S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, "");
   } else if (sub->calldirection == SKINNY_OUTGOING) {
      fromname = S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, "");
      fromnum = S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, "");
      toname = S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, l->lastnumberdialed);
      tonum = S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, l->lastnumberdialed);
   } else {
      ast_verb(1, "Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance);
      return;
   }
   transmit_callinfo(subline->line->device, subline->line->instance, subline->callid, fromname, fromnum, toname, tonum, sub->calldirection);
}
static void register_exten ( struct skinny_line l) [static]

Definition at line 2045 of file chan_skinny.c.

References ast_add_extension(), ast_context_find(), ast_copy_string(), ast_free_ptr(), ast_log(), ast_strdup, ast_strlen_zero(), context, ext, LOG_WARNING, regcontext, and S_OR.

Referenced by skinny_register().

{
   char multi[256];
   char *stringp, *ext, *context;

   if (ast_strlen_zero(regcontext))
      return;

   ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
   stringp = multi;
   while ((ext = strsep(&stringp, "&"))) {
      if ((context = strchr(ext, '@'))) {
         *context++ = '\0'; /* split ext@context */
         if (!ast_context_find(context)) {
            ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
            continue;
         }
      } else {
         context = regcontext;
      }
      ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
          ast_strdup(l->name), ast_free_ptr, "Skinny");
   }
}
static int reload ( void  ) [static]

Definition at line 8074 of file chan_skinny.c.

References skinny_reload().

{
   skinny_reload();
   return 0;
}
static void send_callinfo ( struct skinny_subchannel sub) [static]

Definition at line 2333 of file chan_skinny.c.

References ast_channel_caller(), ast_channel_connected(), ast_verb, skinny_subchannel::calldirection, skinny_subchannel::callid, skinny_line::device, skinny_subchannel::line, skinny_subchannel::owner, S_COR, SKINNY_INCOMING, SKINNY_OUTGOING, and transmit_callinfo().

Referenced by setsubstate(), and update_connectedline().

{
   struct ast_channel *ast;
   struct skinny_device *d;
   struct skinny_line *l;
   char *fromname;
   char *fromnum;
   char *toname;
   char *tonum;

   if (!sub || !sub->owner || !sub->line || !sub->line->device) {
      return;
   }
   
   ast = sub->owner;
   l = sub->line;
   d = l->device;
   
   if (sub->calldirection == SKINNY_INCOMING) {
      fromname = S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, "");
      fromnum = S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, "");
      toname = S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, "");
      tonum = S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, "");
   } else if (sub->calldirection == SKINNY_OUTGOING) {
      fromname = S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, "");
      fromnum = S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, "");
      toname = S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, l->lastnumberdialed);
      tonum = S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, l->lastnumberdialed);
   } else {
      ast_verb(1, "Error sending Callinfo to %s(%d) - No call direction in sub\n", d->name, l->instance);
      return;
   }
   transmit_callinfo(d, l->instance, sub->callid, fromname, fromnum, toname, tonum, sub->calldirection);
}
static int set_callforwards ( struct skinny_line l,
const char *  cfwd,
int  cfwdtype 
) [static]

Definition at line 1987 of file chan_skinny.c.

References ast_copy_string(), ast_strlen_zero(), SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, and SKINNY_CFWD_NOANSWER.

Referenced by dialandactivatesub(), handle_callforward_button(), and skinny_register().

{
   if (!l)
      return 0;

   if (!ast_strlen_zero(cfwd)) {
      if (cfwdtype & SKINNY_CFWD_ALL) {
         l->cfwdtype |= SKINNY_CFWD_ALL;
         ast_copy_string(l->call_forward_all, cfwd, sizeof(l->call_forward_all));
      }
      if (cfwdtype & SKINNY_CFWD_BUSY) {
         l->cfwdtype |= SKINNY_CFWD_BUSY;
         ast_copy_string(l->call_forward_busy, cfwd, sizeof(l->call_forward_busy));
      }
      if (cfwdtype & SKINNY_CFWD_NOANSWER) {
         l->cfwdtype |= SKINNY_CFWD_NOANSWER;
         ast_copy_string(l->call_forward_noanswer, cfwd, sizeof(l->call_forward_noanswer));
      }
   } else {
      if (cfwdtype & SKINNY_CFWD_ALL) {
         l->cfwdtype &= ~SKINNY_CFWD_ALL;
         memset(l->call_forward_all, 0, sizeof(l->call_forward_all));
      }
      if (cfwdtype & SKINNY_CFWD_BUSY) {
         l->cfwdtype &= ~SKINNY_CFWD_BUSY;
         memset(l->call_forward_busy, 0, sizeof(l->call_forward_busy));
      }
      if (cfwdtype & SKINNY_CFWD_NOANSWER) {
         l->cfwdtype &= ~SKINNY_CFWD_NOANSWER;
         memset(l->call_forward_noanswer, 0, sizeof(l->call_forward_noanswer));
      }
   }
   return l->cfwdtype;
}
static void setsubstate ( struct skinny_subchannel sub,
int  state 
) [static]

Definition at line 4965 of file chan_skinny.c.

References skinny_subchannel::aa_beep, skinny_subchannel::aa_mute, skinny_subchannel::aa_sched, skinny_line::activesub, skinny_line::all, ast_channel_context(), ast_channel_context_set(), ast_channel_exten_set(), AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_exists_extension(), ast_hangup(), AST_LIST_FIRST, AST_LIST_NEXT, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_log(), ast_pthread_create, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::callid, skinny_subline::callid, skinny_subline::container, skinny_subchannel::cxmode, destroy_rtp(), skinny_line::device, skinny_subchannel::dialer_sched, errno, skinny_subchannel::exten, skinny_subline::exten, ast_state_cb_info::exten_state, skinny_subline::extenstate, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_ONHOLD, KEYDEF_RINGIN, KEYDEF_RINGOUT, KEYDEF_SLACONNECTEDNOTACTIVE, skinny_subchannel::line, skinny_subline::line, skinny_subline::lnname, LOG_WARNING, skinny_subchannel::owner, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), push_callinfo(), skinny_subchannel::related, skinny_subchannel::rtp, S_OR, send_callinfo(), SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CALLREMOTEMULTILINE, SKINNY_CALLWAIT, SKINNY_CALLWAITTONE, SKINNY_CONGESTION, SKINNY_CONNECTED, SKINNY_CX_RECVONLY, SKINNY_DEBUG, skinny_dialer_cb(), SKINNY_DIALTONE, skinny_extensionstate_cb(), SKINNY_HOLD, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_WINK, SKINNY_MICOFF, skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RING_INSIDE, SKINNY_RING_OFF, SKINNY_RINGIN, SKINNY_RINGOUT, skinny_sched_add(), skinny_sched_del(), SKINNY_SPEAKERON, SKINNY_ZIP, start_rtp(), state, STIMULUS_LINE, skinny_subline::stname, sub, skinny_line::sub, skinny_subline::sub, skinny_subchannel::subline, skinny_line::sublines, skinny_subchannel::substate, substate2str(), SUBSTATE_BUSY, SUBSTATE_CALLWAIT, SUBSTATE_CONGESTION, SUBSTATE_CONNECTED, SUBSTATE_DIALING, SUBSTATE_HOLD, SUBSTATE_OFFHOOK, SUBSTATE_ONHOOK, SUBSTATE_PROGRESS, SUBSTATE_RINGIN, SUBSTATE_RINGOUT, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_microphone_mode(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_start_tone(), transmit_stop_tone(), and transmit_stopmediatransmission().

Referenced by activatesub(), dumpsub(), handle_callforward_button(), handle_hold_button(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), handle_transfer_button(), skinny_answer(), skinny_autoanswer_cb(), skinny_call(), and skinny_indicate().

{
   struct skinny_line *l = sub->line;
   struct skinny_subline *subline = sub->subline;
   struct skinny_device *d = l->device;
   struct ast_channel *c = sub->owner;
   pthread_t t;
   int actualstate = state;

   if (sub->substate == SUBSTATE_ONHOOK) {
      return;
   }

   if (sub->dialer_sched) {
      skinny_sched_del(sub->dialer_sched, sub);
      sub->dialer_sched = 0;
   }

   if (state != SUBSTATE_RINGIN && sub->aa_sched) {
      skinny_sched_del(sub->aa_sched, sub);
      sub->aa_sched = 0;
      sub->aa_beep = 0;
      sub->aa_mute = 0;
   }

   if ((state == SUBSTATE_RINGIN) && ((d->hookstate == SKINNY_OFFHOOK) || (AST_LIST_NEXT(AST_LIST_FIRST(&l->sub), list)))) {
      actualstate = SUBSTATE_CALLWAIT;
   }

   if ((state == SUBSTATE_CONNECTED) && (!subline) && (AST_LIST_FIRST(&l->sublines))) {
      const char *slastation;
      struct skinny_subline *tmpsubline;
      slastation = pbx_builtin_getvar_helper(c, "SLASTATION");
      ast_verb(3, "Connecting %s to subline\n", slastation);
      if (slastation) {
         AST_LIST_TRAVERSE(&l->sublines, tmpsubline, list) {
            if (!strcasecmp(tmpsubline->stname, slastation)) {
               subline = tmpsubline;
               break;
            }
         }
         if (subline) {
            struct skinny_line *tmpline;
            subline->sub = sub;
            sub->subline = subline;
            subline->callid = sub->callid;
            send_callinfo(sub);
            AST_LIST_TRAVERSE(&lines, tmpline, all) {
               AST_LIST_TRAVERSE(&tmpline->sublines, tmpsubline, list) {
                  if (!(subline == tmpsubline)) {
                     if (!strcasecmp(subline->lnname, tmpsubline->lnname)) {
                        struct ast_state_cb_info info = {
                           .exten_state = tmpsubline->extenstate,
                        };
                        tmpsubline->callid = callnums++;
                        transmit_callstate(tmpsubline->line->device, tmpsubline->line->instance, tmpsubline->callid, SKINNY_OFFHOOK);
                        push_callinfo(tmpsubline, sub);
                        skinny_extensionstate_cb(NULL, NULL, &info, tmpsubline->container);
                     }
                  }
               }
            }
         }
      }
   }

   if (subline) { /* Different handling for subs under a subline, indications come through hints */
      switch (actualstate) {
      case SUBSTATE_ONHOOK:
         AST_LIST_REMOVE(&l->sub, sub, list);
         if (sub->related) {
            sub->related->related = NULL;
         }

         if (sub == l->activesub) {
            l->activesub = NULL;
            transmit_closereceivechannel(d, sub);
            transmit_stopmediatransmission(d, sub);
         }

         if (subline->callid) {
            transmit_stop_tone(d, l->instance, sub->callid);
            transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
            transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
            transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
         }

         sub->cxmode = SKINNY_CX_RECVONLY;
         sub->substate = SUBSTATE_ONHOOK;
         destroy_rtp(sub);
         sub->substate = SUBSTATE_ONHOOK;
         if (sub->owner) {
            ast_queue_hangup(sub->owner);
         }
         return;
      case SUBSTATE_CONNECTED:
         transmit_activatecallplane(d, l);
         transmit_stop_tone(d, l->instance, sub->callid);
         transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED);
         transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
         if (!sub->rtp) {
            start_rtp(sub);
         }
         if (sub->substate == SUBSTATE_RINGIN || sub->substate == SUBSTATE_CALLWAIT) {
            ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
         }
         if (sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_RINGOUT) {
            transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
         }
         if (ast_channel_state(sub->owner) != AST_STATE_UP) {
            ast_setstate(sub->owner, AST_STATE_UP);
         }
         sub->substate = SUBSTATE_CONNECTED;
         l->activesub = sub;
         return; 
      case SUBSTATE_HOLD:
         if (sub->substate != SUBSTATE_CONNECTED) {
            ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
            return;
         }
         transmit_activatecallplane(d, l);
         transmit_closereceivechannel(d, sub);
         transmit_stopmediatransmission(d, sub);

         transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
         transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
         transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
         
         sub->substate = SUBSTATE_HOLD;

         ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
            S_OR(l->mohsuggest, NULL),
            !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);

         return;
      default:
         ast_log(LOG_WARNING, "Substate handling under subline for state %d not implemented on Sub-%d\n", state, sub->callid);
      }
   }

   if ((d->hookstate == SKINNY_ONHOOK) && ((actualstate == SUBSTATE_OFFHOOK) || (actualstate == SUBSTATE_DIALING)
      || (actualstate == SUBSTATE_RINGOUT) || (actualstate == SUBSTATE_CONNECTED) || (actualstate == SUBSTATE_BUSY)
      || (actualstate == SUBSTATE_CONGESTION) || (actualstate == SUBSTATE_PROGRESS))) {
         d->hookstate = SKINNY_OFFHOOK;
         transmit_speaker_mode(d, SKINNY_SPEAKERON);
   }

   SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - change state from %s to %s\n",
      sub->callid, substate2str(sub->substate), substate2str(actualstate));

   if (actualstate == sub->substate) {
      send_callinfo(sub);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_HOLD);
      return;
   }

   switch (actualstate) {
   case SUBSTATE_OFFHOOK:
      ast_verb(1, "Call-id: %d\n", sub->callid);
      l->activesub = sub;
      transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
      transmit_activatecallplane(d, l);
      transmit_clear_display_message(d, l->instance, sub->callid);
      transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
      transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
      transmit_displaypromptstatus(d, "Enter number", 0, l->instance, sub->callid);

      sub->substate = SUBSTATE_OFFHOOK;
      sub->dialer_sched = skinny_sched_add(firstdigittimeout, skinny_dialer_cb, sub);
      break;
   case SUBSTATE_ONHOOK:
      AST_LIST_REMOVE(&l->sub, sub, list);
      if (sub->related) {
         sub->related->related = NULL;
      }

      if (sub == l->activesub) {
         l->activesub = NULL;
         transmit_closereceivechannel(d, sub);
         transmit_stopmediatransmission(d, sub);
         transmit_stop_tone(d, l->instance, sub->callid);
         transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
         transmit_clearpromptmessage(d, l->instance, sub->callid);
         transmit_ringer_mode(d, SKINNY_RING_OFF);
         transmit_definetimedate(d); 
         transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
      } else {
         transmit_stop_tone(d, l->instance, sub->callid);
         transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
         transmit_clearpromptmessage(d, l->instance, sub->callid);
      }

      sub->cxmode = SKINNY_CX_RECVONLY;
      destroy_rtp(sub);
      if (sub->owner) {
         if (sub->substate == SUBSTATE_OFFHOOK) {
            sub->substate = SUBSTATE_ONHOOK;
            ast_hangup(sub->owner);
         } else {
            sub->substate = SUBSTATE_ONHOOK;
            ast_queue_hangup(sub->owner);
         }
      } else {
         sub->substate = SUBSTATE_ONHOOK;
      }
      break;
   case SUBSTATE_DIALING:
      if (ast_strlen_zero(sub->exten) || !ast_exists_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
         ast_log(LOG_WARNING, "Exten (%s)@(%s) does not exist, unable to set substate DIALING on sub %d\n", sub->exten, ast_channel_context(c), sub->callid);
         return;
      }

      if (d->hookstate == SKINNY_ONHOOK) {
         d->hookstate = SKINNY_OFFHOOK;
         transmit_speaker_mode(d, SKINNY_SPEAKERON);
         transmit_activatecallplane(d, l);
      }

      if (!sub->subline) {
         transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
         transmit_stop_tone(d, l->instance, sub->callid);
         transmit_clear_display_message(d, l->instance, sub->callid);
         transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
         transmit_displaypromptstatus(d, "Dialing", 0, l->instance, sub->callid);
      }

      if  (AST_LIST_FIRST(&l->sublines)) {
         if (subline) {
            ast_channel_exten_set(c, subline->exten);
            ast_channel_context_set(c, "sla_stations");
         } else {
            pbx_builtin_setvar_helper(c, "_DESTEXTEN", sub->exten);
            pbx_builtin_setvar_helper(c, "_DESTCONTEXT", ast_channel_context(c));
            ast_channel_exten_set(c, l->dialoutexten);
            ast_channel_context_set(c, l->dialoutcontext);
            ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed));
         }
      } else {
         ast_channel_exten_set(c, sub->exten);
         ast_copy_string(l->lastnumberdialed, sub->exten, sizeof(l->lastnumberdialed));
      }
      
      sub->substate = SUBSTATE_DIALING;
   
      if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
         ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
         ast_hangup(c);
      }
      break;
   case SUBSTATE_RINGOUT:
      if (!(sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_PROGRESS)) {
         ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_RINGOUT from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
         return;
      }
      if (sub->substate != SUBSTATE_PROGRESS) {
         transmit_callstate(d, l->instance, sub->callid, SKINNY_PROGRESS);
      }
   
      if (!d->earlyrtp) {
         transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid);
      }
      transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGOUT);
      transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
      transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
      send_callinfo(sub);
      sub->substate = SUBSTATE_RINGOUT;
      break;
   case SUBSTATE_RINGIN:
      transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
      transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
      transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
      send_callinfo(sub);
      transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
      transmit_ringer_mode(d, SKINNY_RING_INSIDE);
      transmit_activatecallplane(d, l);

      if (d->hookstate == SKINNY_ONHOOK) {
         l->activesub = sub;
      }
   
      if (sub->substate != SUBSTATE_RINGIN || sub->substate != SUBSTATE_CALLWAIT) {
         ast_setstate(c, AST_STATE_RINGING);
         ast_queue_control(c, AST_CONTROL_RINGING);
      }
      sub->substate = SUBSTATE_RINGIN;
      break;
   case SUBSTATE_CALLWAIT:
      transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_CALLWAIT);
      transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
      transmit_displaypromptstatus(d, "Callwaiting", 0, l->instance, sub->callid);
      send_callinfo(sub);
      transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
      transmit_start_tone(d, SKINNY_CALLWAITTONE, l->instance, sub->callid);
   
      ast_setstate(c, AST_STATE_RINGING);
      ast_queue_control(c, AST_CONTROL_RINGING);
      sub->substate = SUBSTATE_CALLWAIT;
      break;
   case SUBSTATE_CONNECTED:
      if (sub->substate == SUBSTATE_RINGIN) {
         transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
      }
      if (sub->substate == SUBSTATE_HOLD) {
         ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
         transmit_connect(d, sub);
      }
      transmit_ringer_mode(d, SKINNY_RING_OFF);
      transmit_activatecallplane(d, l);
      transmit_stop_tone(d, l->instance, sub->callid);
      send_callinfo(sub);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
      transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
      transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
      if (!sub->rtp) {
         start_rtp(sub);
      }
      if (sub->aa_beep) {
         transmit_start_tone(d, SKINNY_ZIP, l->instance, sub->callid);
      }
      if (sub->aa_mute) {
         transmit_microphone_mode(d, SKINNY_MICOFF);
      }
      if (sub->substate == SUBSTATE_RINGIN || sub->substate == SUBSTATE_CALLWAIT) {
         ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
      }
      if (sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_RINGOUT) {
         transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
      }
      if (ast_channel_state(sub->owner) != AST_STATE_UP) {
         ast_setstate(sub->owner, AST_STATE_UP);
      }
      sub->substate = SUBSTATE_CONNECTED;
      l->activesub = sub;
      break;
   case SUBSTATE_BUSY:
      if (!(sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_PROGRESS || sub->substate == SUBSTATE_RINGOUT)) {
         ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_BUSY from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
         return;
      }

      if (!d->earlyrtp) {
         transmit_start_tone(d, SKINNY_BUSYTONE, l->instance, sub->callid);
      }
      send_callinfo(sub);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_BUSY);
      transmit_displaypromptstatus(d, "Busy", 0, l->instance, sub->callid);
      sub->substate = SUBSTATE_BUSY;
      break;
   case SUBSTATE_CONGESTION:
      if (!(sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_PROGRESS || sub->substate == SUBSTATE_RINGOUT)) {
         ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_CONGESTION from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
         return;
      }

      if (!d->earlyrtp) {
         transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
      }
      send_callinfo(sub);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_CONGESTION);
      transmit_displaypromptstatus(d, "Congestion", 0, l->instance, sub->callid);
      sub->substate = SUBSTATE_CONGESTION;
      break;
   case SUBSTATE_PROGRESS:
      if (sub->substate != SUBSTATE_DIALING) {
         ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_PROGRESS from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
         return;
      }

      if (!d->earlyrtp) {
         transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid);
      }
      send_callinfo(sub);
      transmit_callstate(d, l->instance, sub->callid, SKINNY_PROGRESS);
      transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
      sub->substate = SUBSTATE_PROGRESS;
      break;
   case SUBSTATE_HOLD:
      if (sub->substate != SUBSTATE_CONNECTED) {
         ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
         return;
      }
      ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
         S_OR(l->mohsuggest, NULL),
         !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);

      transmit_activatecallplane(d, l);
      transmit_closereceivechannel(d, sub);
      transmit_stopmediatransmission(d, sub);

      transmit_callstate(d, l->instance, sub->callid, SKINNY_HOLD);
      transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
      transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD);
      sub->substate = SUBSTATE_HOLD;
      break;
   default:
      ast_log(LOG_WARNING, "Was asked to change to nonexistant substate %d on Sub-%d\n", state, sub->callid);
   }
}
static int skinny_answer ( struct ast_channel ast) [static]

Definition at line 4432 of file chan_skinny.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_setstate(), AST_STATE_UP, skinny_subchannel::blindxfer, skinny_subchannel::callid, skinny_subchannel::cxmode, skinny_line::device, skinny_subchannel::line, setsubstate(), SKINNY_CX_SENDRECV, SKINNY_DEBUG, skinny_transfer(), sub, and SUBSTATE_CONNECTED.

{
   int res = 0;
   struct skinny_subchannel *sub = ast_channel_tech_pvt(ast);

   if (sub->blindxfer) {
      SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_answer(%s) on %s@%s-%d with BlindXFER, transferring\n",
         ast_channel_name(ast), sub->line->name, sub->line->device->name, sub->callid);
      ast_setstate(ast, AST_STATE_UP);
      skinny_transfer(sub);
      return 0;
   }

   sub->cxmode = SKINNY_CX_SENDRECV;

   SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_answer(%s) on %s@%s-%d\n",
      ast_channel_name(ast), sub->line->name, sub->line->device->name, sub->callid);

   setsubstate(sub, SUBSTATE_CONNECTED);

   return res;
}
static int skinny_autoanswer_cb ( const void *  data) [static]

Definition at line 4334 of file chan_skinny.c.

References skinny_subchannel::aa_sched, setsubstate(), SKINNY_CONNECTED, and sub.

Referenced by skinny_call().

{
   struct skinny_subchannel *sub = (struct skinny_subchannel *)data;
   sub->aa_sched = 0;
   setsubstate(sub, SKINNY_CONNECTED);
   return 0;
}
static int skinny_call ( struct ast_channel ast,
const char *  dest,
int  timeout 
) [static]

Definition at line 4342 of file chan_skinny.c.

References skinny_subchannel::aa_beep, skinny_subchannel::aa_mute, skinny_subchannel::aa_sched, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_varshead(), AST_CONTROL_BUSY, ast_copy_string(), AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_log(), ast_queue_control(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_var_name(), ast_var_value(), skinny_subchannel::callid, skinny_line::device, ast_var_t::entries, skinny_subchannel::line, LOG_WARNING, skinny_device::session, setsubstate(), skinny_autoanswer_cb(), SKINNY_DEBUG, SKINNY_ONHOOK, skinny_sched_add(), sub, SUBSTATE_CONNECTED, and SUBSTATE_RINGIN.

{
   int res = 0;
   struct skinny_subchannel *sub = ast_channel_tech_pvt(ast);
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;
   struct ast_var_t *current;
   int doautoanswer = 0;

   if (!d || !d->session) {
      ast_log(LOG_WARNING, "Device not registered, cannot call %s\n", dest);
      return -1;
   }

   if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
      ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
      return -1;
   }

   SKINNY_DEBUG(DEBUG_SUB, 3, "Skinny Call (%s) - Sub %d\n",
      ast_channel_name(ast), sub->callid);

   if (l->dnd) {
      ast_queue_control(ast, AST_CONTROL_BUSY);
      return -1;
   }

   if (AST_LIST_NEXT(sub,list) && !l->callwaiting) {
      ast_queue_control(ast, AST_CONTROL_BUSY);
      return -1;
   }

   AST_LIST_TRAVERSE(ast_channel_varshead(ast), current, entries) {
      if (!(strcasecmp(ast_var_name(current),"SKINNY_AUTOANSWER"))) {
         if (d->hookstate == SKINNY_ONHOOK && !sub->aa_sched) {
            char buf[24];
            int aatime;
            char *stringp = buf, *curstr;
            ast_copy_string(buf, ast_var_value(current), sizeof(buf));
            curstr = strsep(&stringp, ":");
            aatime = atoi(curstr);
            while ((curstr = strsep(&stringp, ":"))) {
               if (!(strcasecmp(curstr,"BEEP"))) {
                  sub->aa_beep = 1;
               } else if (!(strcasecmp(curstr,"MUTE"))) {
                  sub->aa_mute = 1;
               }
            }
            SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - setting autoanswer time=%dms %s%s\n",
               sub->callid, aatime, sub->aa_beep ? "BEEP " : "", sub->aa_mute ? "MUTE" : "");
            if (aatime) {
               //sub->aa_sched = ast_sched_add(sched, aatime, skinny_autoanswer_cb, sub);
               sub->aa_sched = skinny_sched_add(aatime, skinny_autoanswer_cb, sub);
            } else {
               doautoanswer = 1;
            }
         }
      }
   }

   setsubstate(sub, SUBSTATE_RINGIN);
   if (doautoanswer) {
      setsubstate(sub, SUBSTATE_CONNECTED);
   }
   return res;
}
static struct skinny_device* skinny_device_alloc ( void  ) [static, read]

Definition at line 1557 of file chan_skinny.c.

References ast_calloc, ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_free, skinny_device::cap, and skinny_device::confcap.

Referenced by config_device().

{
   struct skinny_device *d;
   if (!(d = ast_calloc(1, sizeof(*d)))) {
      return NULL;
   }

   d->cap = ast_format_cap_alloc_nolock();
   d->confcap = ast_format_cap_alloc_nolock();
   if (!d->cap || !d->confcap) {
      d->cap = ast_format_cap_destroy(d->cap);
      d->confcap = ast_format_cap_destroy(d->confcap);
      ast_free(d);
      return NULL;
   }
   return d;
}
static struct skinny_device* skinny_device_destroy ( struct skinny_device d) [static, read]
static int skinny_devicestate ( const char *  data) [static]

Definition at line 7048 of file chan_skinny.c.

References find_line_by_name(), and get_devicestate().

{
   struct skinny_line *l;
   char *tmp;

   tmp = ast_strdupa(data);

   l = find_line_by_name(tmp);

   return get_devicestate(l);
}
static void skinny_dialer ( struct skinny_subchannel sub,
int  timedout 
) [static]

Definition at line 4296 of file chan_skinny.c.

References ast_channel_context(), ast_exists_extension(), ast_matchmore_extension(), skinny_subchannel::callid, skinny_line::device, dialandactivatesub(), skinny_subchannel::dialer_sched, dumpsub(), skinny_subchannel::exten, skinny_subchannel::line, skinny_subchannel::owner, SKINNY_DEBUG, skinny_dialer_cb(), SKINNY_OFFHOOK, SKINNY_REORDER, skinny_sched_add(), skinny_subchannel::substate, SUBSTATE_OFFHOOK, and transmit_start_tone().

Referenced by handle_keypad_button_message(), and skinny_dialer_cb().

{
   struct ast_channel *c = sub->owner;
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;

   if (timedout || !ast_matchmore_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
      SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Force dialing '%s'\n", sub->callid, sub->exten);
      if (ast_exists_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
         if (sub->substate == SUBSTATE_OFFHOOK) {
            dialandactivatesub(sub, sub->exten);
         }
      } else {
         if (d->hookstate == SKINNY_OFFHOOK) {
            // FIXME: redundant because below will onhook before the sound plays, but it correct to send it.
            transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
         }
         dumpsub(sub, 0);
      }
   } else {
      SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Wait for more digits\n", sub->callid);
      if (ast_exists_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
         sub->dialer_sched = skinny_sched_add(matchdigittimeout, skinny_dialer_cb, sub);
      } else {
         sub->dialer_sched = skinny_sched_add(gendigittimeout, skinny_dialer_cb, sub);
      }
   }
}
static int skinny_dialer_cb ( const void *  data) [static]

Definition at line 4325 of file chan_skinny.c.

References skinny_subchannel::callid, skinny_subchannel::dialer_sched, SKINNY_DEBUG, skinny_dialer(), and sub.

Referenced by handle_soft_key_event_message(), setsubstate(), and skinny_dialer().

{
   struct skinny_subchannel *sub = (struct skinny_subchannel *)data;
   SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Dialer called from SCHED %d\n", sub->callid, sub->dialer_sched);
   sub->dialer_sched = 0;
   skinny_dialer(sub, 1);
   return 0;
}
static int skinny_extensionstate_cb ( char *  context,
char *  id,
struct ast_state_cb_info info,
void *  data 
) [static]

Definition at line 2981 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_state2str(), AST_EXTENSION_UNAVAILABLE, ast_get_hint(), AST_HINT_UPDATE_DEVICE, ast_log(), AST_MAX_EXTENSION, skinny_subline::callid, skinny_speeddial::context, skinny_container::data, skinny_line::device, skinny_speeddial::exten, ast_state_cb_info::exten_state, skinny_subline::extenstate, skinny_speeddial::instance, KEYDEF_CONNECTED, KEYDEF_ONHOOK, KEYDEF_SLACONNECTEDNOTACTIVE, KEYDEF_SLAHOLD, skinny_speeddial::label, skinny_speeddial::laststate, skinny_subline::line, LOG_WARNING, skinny_subline::name, skinny_speeddial::parent, ast_state_cb_info::reason, SKINNY_CALLREMOTEMULTILINE, SKINNY_CONNECTED, SKINNY_DEBUG, SKINNY_HOLD, SKINNY_LAMP_BLINK, SKINNY_LAMP_FLASH, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_LAMP_WINK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_RINGIN, SKINNY_SDCONTAINER, SKINNY_SUBLINECONTAINER, state, skinny_speeddial::stateid, STIMULUS_LINE, skinny_subline::sub, skinny_subchannel::substate, transmit_activatecallplane(), transmit_callstate(), transmit_clearpromptmessage(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), and skinny_container::type.

Referenced by setsubstate(), and skinny_register().

{
   struct skinny_container *container = data;
   struct skinny_device *d = NULL;
   char hint[AST_MAX_EXTENSION];
   int state = info->exten_state;

   /* only interested in device state here */
   if (info->reason != AST_HINT_UPDATE_DEVICE) {
      return 0;
   }

   if (container->type == SKINNY_SDCONTAINER) {
      struct skinny_speeddial *sd = container->data;
      d = sd->parent;

      SKINNY_DEBUG(DEBUG_HINT, 3, "Got hint %s on speeddial %s\n", ast_extension_state2str(state), sd->label);

      if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
         /* If they are not registered, we will override notification and show no availability */
         if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
            transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_FLASH);
            transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
            return 0;
         }
         switch (state) {
         case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
         case AST_EXTENSION_REMOVED:     /* Extension is gone */
            SKINNY_DEBUG(DEBUG_HINT, 3, "Extension state: Watcher for hint %s %s. Notify Device %s\n",
               exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
            sd->stateid = -1;
            transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
            transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
            break;
         case AST_EXTENSION_RINGING:
         case AST_EXTENSION_UNAVAILABLE:
            transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_BLINK);
            transmit_callstate(d, sd->instance, 0, SKINNY_RINGIN);
            break;
         case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
         case AST_EXTENSION_INUSE:
            transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_ON);
            transmit_callstate(d, sd->instance, 0, SKINNY_CALLREMOTEMULTILINE);
            break;
         case AST_EXTENSION_ONHOLD:
            transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_WINK);
            transmit_callstate(d, sd->instance, 0, SKINNY_HOLD);
            break;
         case AST_EXTENSION_NOT_INUSE:
         default:
            transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
            transmit_callstate(d, sd->instance, 0, SKINNY_ONHOOK);
            break;
         }
      }
      sd->laststate = state;
   } else if (container->type == SKINNY_SUBLINECONTAINER) {
      struct skinny_subline *subline = container->data;
      struct skinny_line *l = subline->line;
      d = l->device;

      SKINNY_DEBUG(DEBUG_HINT, 3, "Got hint %s on subline %s (%s@%s)\n", ast_extension_state2str(state), subline->name, exten, context);

      subline->extenstate = state;

      if (subline->callid == 0) {
         return 0;
      }

      switch (state) {
      case AST_EXTENSION_RINGING: /* Handled by normal ringin */
         break;
      case AST_EXTENSION_INUSE:
         if (subline->sub && (subline->sub->substate == SKINNY_CONNECTED)) { /* Device has a real call */
            transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
            transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED);
            transmit_displaypromptstatus(d, "Connected", 0, l->instance, subline->callid);
         } else { /* Some other device has active call */
            transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
            transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE);
            transmit_displaypromptstatus(d, "In Use", 0, l->instance, subline->callid);
         }
         transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
         transmit_ringer_mode(d, SKINNY_RING_OFF);
         transmit_activatecallplane(d, l);
         break;
      case AST_EXTENSION_ONHOLD:
         transmit_callstate(d, l->instance, subline->callid, SKINNY_HOLD);
         transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLAHOLD);
         transmit_displaypromptstatus(d, "Hold", 0, l->instance, subline->callid);
         transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
         transmit_activatecallplane(d, l);
         break;
      case AST_EXTENSION_NOT_INUSE:
         transmit_callstate(d, l->instance, subline->callid, SKINNY_ONHOOK);
         transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_ONHOOK);
         transmit_clearpromptmessage(d, l->instance, subline->callid);
         transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
         transmit_activatecallplane(d, l);
         subline->callid = 0;
         break;
      default:
         ast_log(LOG_WARNING, "AST_EXTENSION_STATE %s not configured\n", ast_extension_state2str(state));
      }
   } else {
      ast_log(LOG_WARNING, "Invalid data supplied to skinny_extensionstate_cb\n");
   }

   return 0;
}
static int skinny_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 4545 of file chan_skinny.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_log(), LOG_NOTICE, LOG_WARNING, skinny_subchannel::owner, and sub.

{
   struct skinny_subchannel *sub = ast_channel_tech_pvt(newchan);
   ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", ast_channel_name(oldchan), ast_channel_name(newchan));
   if (sub->owner != oldchan) {
      ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
      return -1;
   }
   sub->owner = newchan;
   return 0;
}
static enum ast_rtp_glue_result skinny_get_rtp_peer ( struct ast_channel c,
struct ast_rtp_instance **  instance 
) [static]

Definition at line 3165 of file chan_skinny.c.

References ao2_ref, ast_channel_name(), ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, skinny_subchannel::line, skinny_subchannel::lock, skinny_subchannel::rtp, SKINNY_DEBUG, and sub.

{
   struct skinny_subchannel *sub = NULL;
   struct skinny_line *l;
   enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;

   SKINNY_DEBUG(DEBUG_AUDIO, 4, "skinny_get_rtp_peer() Channel = %s\n", ast_channel_name(c));

   if (!(sub = ast_channel_tech_pvt(c)))
      return AST_RTP_GLUE_RESULT_FORBID;

   ast_mutex_lock(&sub->lock);

   if (!(sub->rtp)){
      ast_mutex_unlock(&sub->lock);
      return AST_RTP_GLUE_RESULT_FORBID;
   }

   ao2_ref(sub->rtp, +1);
   *instance = sub->rtp;

   l = sub->line;

   if (!l->directmedia || l->nat){
      res = AST_RTP_GLUE_RESULT_LOCAL;
      SKINNY_DEBUG(DEBUG_AUDIO, 4, "skinny_get_rtp_peer() Using AST_RTP_GLUE_RESULT_LOCAL \n");
   }

   ast_mutex_unlock(&sub->lock);

   return res;

}
static enum ast_rtp_glue_result skinny_get_vrtp_peer ( struct ast_channel c,
struct ast_rtp_instance **  instance 
) [static]

Definition at line 3152 of file chan_skinny.c.

References ao2_ref, ast_channel_tech_pvt(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_REMOTE, sub, and skinny_subchannel::vrtp.

{
   struct skinny_subchannel *sub = NULL;

   if (!(sub = ast_channel_tech_pvt(c)) || !(sub->vrtp))
      return AST_RTP_GLUE_RESULT_FORBID;

   ao2_ref(sub->vrtp, +1);
   *instance = sub->vrtp;

   return AST_RTP_GLUE_RESULT_REMOTE;
}
static int skinny_hangup ( struct ast_channel ast) [static]

Definition at line 4409 of file chan_skinny.c.

References ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), ast_debug, ast_free, ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, skinny_subchannel::callid, destroy_rtp(), dumpsub(), skinny_subchannel::lock, skinny_subchannel::owner, ast_module_info::self, SKINNY_DEBUG, and sub.

{
   struct skinny_subchannel *sub = ast_channel_tech_pvt(ast);

   if (!sub) {
      ast_debug(1, "Asked to hangup channel not connected\n");
      return 0;
   }

   dumpsub(sub, 1);

   SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Destroying\n", sub->callid);

   ast_mutex_lock(&sub->lock);
   sub->owner = NULL;
   ast_channel_tech_pvt_set(ast, NULL);
   destroy_rtp(sub);
   ast_mutex_unlock(&sub->lock);
   ast_free(sub);
   ast_module_unref(ast_module_info->self);
   return 0;
}
static int skinny_indicate ( struct ast_channel ast,
int  ind,
const void *  data,
size_t  datalen 
) [static]

Definition at line 4734 of file chan_skinny.c.

References ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), skinny_subchannel::blindxfer, skinny_subchannel::callid, control2str(), skinny_line::device, skinny_subchannel::line, LOG_NOTICE, LOG_WARNING, skinny_subchannel::rtp, skinny_device::session, setsubstate(), SKINNY_DEBUG, skinny_transfer(), sub, SUBSTATE_BUSY, SUBSTATE_CONGESTION, SUBSTATE_PROGRESS, SUBSTATE_RINGOUT, transmit_stop_tone(), and update_connectedline().

{
   struct skinny_subchannel *sub = ast_channel_tech_pvt(ast);
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;
   struct skinnysession *s = d->session;

   if (!s) {
      ast_log(LOG_NOTICE, "Asked to indicate '%s' condition on channel %s, but session does not exist.\n", control2str(ind), ast_channel_name(ast));
      return -1;
   }

   SKINNY_DEBUG(DEBUG_SUB, 3, "Asked to indicate '%s' condition on channel %s (Sub %d)\n",
      control2str(ind), ast_channel_name(ast), sub->callid);
   switch(ind) {
   case AST_CONTROL_RINGING:
      if (sub->blindxfer) {
         SKINNY_DEBUG(DEBUG_SUB, 3, "Channel %s (Sub %d) set up for Blind Xfer, so Xfer rather than ring device\n",
            ast_channel_name(ast), sub->callid);
         skinny_transfer(sub);
         break;
      }
      setsubstate(sub, SUBSTATE_RINGOUT);
      return (d->earlyrtp ? -1 : 0); /* Tell asterisk to provide inband signalling if rtp started */
   case AST_CONTROL_BUSY:
      setsubstate(sub, SUBSTATE_BUSY);
      return (d->earlyrtp ? -1 : 0); /* Tell asterisk to provide inband signalling if rtp started */
   case AST_CONTROL_INCOMPLETE:
      /* Support for incomplete not supported for chan_skinny; treat as congestion */
   case AST_CONTROL_CONGESTION:
      setsubstate(sub, SUBSTATE_CONGESTION);
      return (d->earlyrtp ? -1 : 0); /* Tell asterisk to provide inband signalling if rtp started */
   case AST_CONTROL_PROGRESS:
      setsubstate(sub, SUBSTATE_PROGRESS);
      return (d->earlyrtp ? -1 : 0); /* Tell asterisk to provide inband signalling if rtp started */
   case -1:  /* STOP_TONE */
      transmit_stop_tone(d, l->instance, sub->callid);
      break;
   case AST_CONTROL_HOLD:
      ast_moh_start(ast, data, l->mohinterpret);
      break;
   case AST_CONTROL_UNHOLD:
      ast_moh_stop(ast);
      break;
   case AST_CONTROL_PROCEEDING:
      break;
   case AST_CONTROL_SRCUPDATE:
      if (sub->rtp) {
         ast_rtp_instance_update_source(sub->rtp);
      }
      break;
   case AST_CONTROL_SRCCHANGE:
      if (sub->rtp) {
         ast_rtp_instance_change_source(sub->rtp);
      }
      break;
   case AST_CONTROL_CONNECTED_LINE:
      update_connectedline(sub, data, datalen);
      break;
   default:
      ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
      /* fallthrough */
   case AST_CONTROL_PVT_CAUSE_CODE:
      return -1; /* Tell asterisk to provide inband signalling */
   }
   return 0;
}
static struct skinny_line* skinny_line_alloc ( void  ) [static, read]

Definition at line 1532 of file chan_skinny.c.

References ast_calloc, ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_free, skinny_line::cap, and skinny_line::confcap.

Referenced by config_line().

{
   struct skinny_line *l;
   if (!(l = ast_calloc(1, sizeof(*l)))) {
      return NULL;
   }

   l->cap = ast_format_cap_alloc_nolock();
   l->confcap = ast_format_cap_alloc_nolock();
   if (!l->cap || !l->confcap) {
      l->cap = ast_format_cap_destroy(l->cap);
      l->confcap = ast_format_cap_destroy(l->confcap);
      ast_free(l);
      return NULL;
   }
   return l;
}
static struct ast_channel* skinny_new ( struct skinny_line l,
struct skinny_subline subline,
int  state,
const char *  linkedid,
int  direction 
) [static, read]

Definition at line 4802 of file chan_skinny.c.

References skinny_subchannel::aa_sched, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_adsicpe_set(), ast_channel_alloc(), ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_pickupgroup_set(), ast_channel_priority_set(), ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_channel_readformat(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_writeformat(), AST_DEVICE_NOT_INUSE, ast_format_cap_copy(), ast_format_cap_is_empty(), ast_format_copy(), ast_getformatname(), ast_getformatname_multiple(), ast_hangup(), ast_jb_configure(), AST_LIST_INSERT_HEAD, ast_log(), ast_module_ref(), ast_mutex_init, ast_pbx_start(), ast_rtp_instance_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), skinny_subchannel::blindxfer, skinny_subchannel::calldirection, skinny_subchannel::callid, skinny_line::cap, skinny_line::chanvars, skinny_subline::context, skinny_subchannel::cxmode, skinny_line::device, skinny_subchannel::dialer_sched, get_devicestate(), global_jbconf, skinny_subchannel::line, skinny_subchannel::lock, LOG_WARNING, ast_variable::name, skinny_subchannel::nat, ast_variable::next, ast_party_id::number, skinny_subchannel::owner, pbx_builtin_setvar_helper(), skinny_subchannel::related, skinny_subchannel::rtp, ast_module_info::self, skinny_device::session, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CX_INACTIVE, SKINNY_DEBUG, skinny_tech, ast_party_number::str, sub, skinny_line::sub, skinny_subline::sub, skinny_subchannel::subline, ast_party_number::valid, ast_variable::value, 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().

{
   struct ast_channel *tmp;
   struct skinny_subchannel *sub;
   struct skinny_device *d = l->device;
   struct ast_variable *v = NULL;
   struct ast_format tmpfmt;

   if (!l->device || !l->device->session) {
      ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
      return NULL;
   }

   tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, linkedid, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
   if (!tmp) {
      ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
      return NULL;
   } else {
      sub = ast_calloc(1, sizeof(*sub));
      if (!sub) {
         ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
         return NULL;
      } else {
         ast_mutex_init(&sub->lock);

         sub->owner = tmp;
         sub->callid = callnums++;
         d->lastlineinstance = l->instance;
         d->lastcallreference = sub->callid;
         sub->cxmode = SKINNY_CX_INACTIVE;
         sub->nat = l->nat;
         sub->line = l;
         sub->blindxfer = 0;
         sub->xferor = 0;
         sub->related = NULL;
         sub->calldirection = direction;
         sub->aa_sched = 0;
         sub->dialer_sched = 0;

         if (subline) {
            sub->subline = subline;
            subline->sub = sub;
         } else {
            sub->subline = NULL;
         }
         
         AST_LIST_INSERT_HEAD(&l->sub, sub, list);
         //l->activesub = sub;
      }
      ast_channel_tech_set(tmp, &skinny_tech);
      ast_channel_tech_pvt_set(tmp, sub);
      ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
      if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
         // Should throw an error
         ast_format_cap_copy(ast_channel_nativeformats(tmp), default_cap);
      }
      ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
      SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_new: tmp->nativeformats=%s fmt=%s\n",
         ast_getformatname_multiple(dbgsub_buf, sizeof(dbgsub_buf), ast_channel_nativeformats(tmp)),
         ast_getformatname(&tmpfmt));
      if (sub->rtp) {
         ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
      }
      if (state == AST_STATE_RING) {
         ast_channel_rings_set(tmp, 1);
      }
      ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
      ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
      ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
      ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);

      if (!ast_strlen_zero(l->language))
         ast_channel_language_set(tmp, l->language);
      if (!ast_strlen_zero(l->accountcode))
         ast_channel_accountcode_set(tmp, l->accountcode);
      if (!ast_strlen_zero(l->parkinglot))
         ast_channel_parkinglot_set(tmp, l->parkinglot);
      if (l->amaflags)
         ast_channel_amaflags_set(tmp, l->amaflags);

      ast_module_ref(ast_module_info->self);
      ast_channel_callgroup_set(tmp, l->callgroup);
      ast_channel_pickupgroup_set(tmp, l->pickupgroup);

      /* XXX Need to figure out how to handle CFwdNoAnswer */
      if (l->cfwdtype & SKINNY_CFWD_ALL) {
         ast_channel_call_forward_set(tmp, l->call_forward_all);
      } else if (l->cfwdtype & SKINNY_CFWD_BUSY) {
         if (get_devicestate(l) != AST_DEVICE_NOT_INUSE) {
            ast_channel_call_forward_set(tmp, l->call_forward_busy);
         }
      }

      if (subline) {
         ast_channel_context_set(tmp, subline->context);
      } else {
         ast_channel_context_set(tmp, l->context);
      }
      ast_channel_exten_set(tmp, l->exten);

      /* Don't use ast_set_callerid() here because it will
       * generate a needless NewCallerID event */
      if (!ast_strlen_zero(l->cid_num)) {
         ast_channel_caller(tmp)->ani.number.valid = 1;
         ast_channel_caller(tmp)->ani.number.str = ast_strdup(l->cid_num);
      }

      ast_channel_priority_set(tmp, 1);
      ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);

      if (sub->rtp)
         ast_jb_configure(tmp, &global_jbconf);

      /* Set channel variables for this call from configuration */
      for (v = l->chanvars ; v ; v = v->next)
         pbx_builtin_setvar_helper(tmp, v->name, v->value);

      if (state != AST_STATE_DOWN) {
         if (ast_pbx_start(tmp)) {
            ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
            ast_hangup(tmp);
            tmp = NULL;
         }
      }
   }
   return tmp;
}
static void* skinny_newcall ( void *  data) [static]

Definition at line 4263 of file chan_skinny.c.

References ast_channel_caller(), ast_channel_connected(), ast_channel_context(), ast_channel_exten(), ast_channel_tech_pvt(), ast_log(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strdup, ast_verb, skinny_subchannel::callid, ast_channel::data, skinny_line::device, ast_party_connected_line::id, skinny_subchannel::line, LOG_WARNING, ast_party_id::number, skinny_subchannel::rtp, SKINNY_REORDER, start_rtp(), ast_party_number::str, sub, transmit_start_tone(), and ast_party_number::valid.

Referenced by setsubstate().

{
   struct ast_channel *c = data;
   struct skinny_subchannel *sub = ast_channel_tech_pvt(c);
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;
   int res = 0;

   ast_set_callerid(c,
      l->hidecallerid ? "" : l->cid_num,
      l->hidecallerid ? "" : l->cid_name,
      ast_channel_caller(c)->ani.number.valid ? NULL : l->cid_num);
#if 1 /* XXX This code is probably not necessary */
   ast_party_number_free(&ast_channel_connected(c)->id.number);
   ast_party_number_init(&ast_channel_connected(c)->id.number);
   ast_channel_connected(c)->id.number.valid = 1;
   ast_channel_connected(c)->id.number.str = ast_strdup(ast_channel_exten(c));
   ast_party_name_free(&ast_channel_connected(c)->id.name);
   ast_party_name_init(&ast_channel_connected(c)->id.name);
#endif
   ast_setstate(c, AST_STATE_RING);
   if (!sub->rtp) {
      start_rtp(sub);
   }
   ast_verb(3, "Sub %d - Calling %s@%s\n", sub->callid, ast_channel_exten(c), ast_channel_context(c));
   res = ast_pbx_run(c);
   if (res) {
      ast_log(LOG_WARNING, "PBX exited non-zero\n");
      transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
   }
   return NULL;
}
static struct ast_frame * skinny_read ( struct ast_channel ast) [static, read]
static int skinny_register ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 2094 of file chan_skinny.c.

References __ourip, ast_app_has_voicemail(), ast_apply_ha(), ast_copy_string(), AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_extension_state_add(), ast_format_cap_joint_copy(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_sockaddr_from_sin, ast_strlen_zero(), skinny_line::cap, skinny_device::cap, skinny_line::confcap, skinny_subline::container, skinny_speeddial::container, skinny_subline::context, skinny_speeddial::context, skinny_req::data, skinnysession::device, EVENT_FLAG_SYSTEM, skinny_subline::exten, skinny_speeddial::exten, skinnysession::fd, skinny_device::ha, letohl, skinny_device::lines, LOG_WARNING, manager_event, mwi_event_cb(), register_message::name, skinny_line::newmsgs, skinny_device::ourip, register_message::protocolVersion, skinny_data::reg, register_exten(), skinny_device::session, set_callforwards(), skinnysession::sin, skinny_extensionstate_cb(), skinny_device::speeddials, skinny_speeddial::stateid, skinny_subchannel::subline, skinny_line::sublines, and register_message::type.

Referenced by handle_message().

{
   struct skinny_device *d;
   struct skinny_line *l;
   struct skinny_subline *subline;
   struct skinny_speeddial *sd;
   struct sockaddr_in sin;
   socklen_t slen;
   int instance;

   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, d, list){
      struct ast_sockaddr addr;
      ast_sockaddr_from_sin(&addr, &s->sin);
      if (!d->session && !strcasecmp(req->data.reg.name, d->id)
            && ast_apply_ha(d->ha, &addr)) {
         s->device = d;
         d->type = letohl(req->data.reg.type);
         d->protocolversion = letohl(req->data.reg.protocolVersion);
         if (ast_strlen_zero(d->version_id)) {
            ast_copy_string(d->version_id, version_id, sizeof(d->version_id));
         }
         d->session = s;

         slen = sizeof(sin);
         if (getsockname(s->fd, (struct sockaddr *)&sin, &slen)) {
            ast_log(LOG_WARNING, "Cannot get socket name\n");
            sin.sin_addr = __ourip;
         }
         d->ourip = sin.sin_addr;

         AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
            sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd->container);
         }
         instance = 0;
         AST_LIST_TRAVERSE(&d->lines, l, list) {
            instance++;
         }
         AST_LIST_TRAVERSE(&d->lines, l, list) {
            ast_format_cap_joint_copy(l->confcap, d->cap, l->cap);
            l->prefs = l->confprefs;
            if (!l->prefs.order[0]) {
               l->prefs = d->confprefs;
            }
            /* l->capability = d->capability;
            l->prefs = d->prefs; */
            l->instance = instance;
            l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
            set_callforwards(l, NULL, 0);
            manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Registered\r\n", l->name, d->name);
            register_exten(l);
            /* initialize MWI on line and device */
            mwi_event_cb(0, l);
            AST_LIST_TRAVERSE(&l->sublines, subline, list) {
               ast_extension_state_add(subline->context, subline->exten, skinny_extensionstate_cb, subline->container);
            }
            ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
            --instance;
         }
         break;
      }
   }
   AST_LIST_UNLOCK(&devices);
   if (!d) {
      return 0;
   }
   return 1;
}
int skinny_reload ( void  ) [static]

Definition at line 7874 of file chan_skinny.c.

References skinny_device::addons, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verb, config_load(), free, skinny_device::lines, skinny_device::session, skinny_device_destroy(), skinny_line_destroy(), skinny_device::speeddials, and transmit_reset().

Referenced by handle_skinny_reload(), and reload().

{
   struct skinny_device *d;
   struct skinny_line *l;
   struct skinny_speeddial *sd;
   struct skinny_addon *a;

   if (skinnyreload) {
      ast_verb(3, "Chan_skinny is already reloading.\n");
      return 0;
   }

   skinnyreload = 1;

   /* Mark all devices and lines as candidates to be pruned */
   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE(&devices, d, list) {
      d->prune = 1;
   }
   AST_LIST_UNLOCK(&devices);

   AST_LIST_LOCK(&lines);
   AST_LIST_TRAVERSE(&lines, l, all) {
      l->prune = 1;
   }
   AST_LIST_UNLOCK(&lines);

        config_load();

   /* Remove any devices that no longer exist in the config */
   AST_LIST_LOCK(&devices);
   AST_LIST_TRAVERSE_SAFE_BEGIN(&devices, d, list) {
      if (!d->prune) {
         continue;
      }
      ast_verb(3, "Removing device '%s'\n", d->name);
      /* Delete all lines for this device. 
         We do not want to free the line here, that
         will happen below. */
      while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
      }
      /* Delete all speeddials for this device */
      while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
         free(sd);
      }
      /* Delete all addons for this device */
      while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
         free(a);
      }
      AST_LIST_REMOVE_CURRENT(list);
      d = skinny_device_destroy(d);
   }
   AST_LIST_TRAVERSE_SAFE_END;
   AST_LIST_UNLOCK(&devices);

   AST_LIST_LOCK(&lines);  
   AST_LIST_TRAVERSE_SAFE_BEGIN(&lines, l, all) {
      if (l->prune) {
         AST_LIST_REMOVE_CURRENT(all);
         l = skinny_line_destroy(l);
      }
   }
   AST_LIST_TRAVERSE_SAFE_END;
   AST_LIST_UNLOCK(&lines);  

   AST_LIST_TRAVERSE(&devices, d, list) {
      /* Do a soft reset to re-register the devices after
         cleaning up the removed devices and lines */
      if (d->session) {
         ast_verb(3, "Restarting device '%s'\n", d->name);
         transmit_reset(d, 1);
      }
   }

   skinnyreload = 0;
        return 0;
}
static struct skinny_req* skinny_req_parse ( struct skinnysession s) [static, read]

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

{
   struct skinny_req *req;
   int *bufaddr;

   if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
      return NULL;

   ast_mutex_lock(&s->lock);
   memcpy(req, s->inbuf, skinny_header_size);
   bufaddr = (int *)(s->inbuf);
   memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);

   ast_mutex_unlock(&s->lock);

   if (letohl(req->e) < 0) {
      ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
      ast_free(req);
      return NULL;
   }

   return req;
}
static struct ast_channel * skinny_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_channel requestor,
const char *  dest,
int *  cause 
) [static, read]

Definition at line 7060 of file chan_skinny.c.

References ast_channel_linkedid(), ast_channel_tech_pvt(), ast_copy_string(), ast_format_cap_has_type(), AST_FORMAT_TYPE_AUDIO, ast_getformatname_multiple(), ast_log(), AST_STATE_DOWN, ast_strlen_zero(), ast_verb, skinny_subline::calldirection, skinny_subchannel::callid, skinny_subline::callid, find_line_by_name(), find_subline_by_name(), skinny_subline::line, LOG_NOTICE, LOG_WARNING, SKINNY_INCOMING, skinny_new(), sub, skinny_subline::sub, skinny_subchannel::subline, skinny_subline::substate, and SUBSTATE_UNSET.

{
   struct skinny_line *l;
   struct skinny_subline *subline = NULL;
   struct ast_channel *tmpc = NULL;
   char tmp[256];

   if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
      ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
      return NULL;
   }

   ast_copy_string(tmp, dest, sizeof(tmp));
   if (ast_strlen_zero(tmp)) {
      ast_log(LOG_NOTICE, "Skinny channels require a device\n");
      return NULL;
   }
   l = find_line_by_name(tmp);
   if (!l) {
      subline = find_subline_by_name(tmp);
      if (!subline) {
         ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
         return NULL;
      }
      l = subline->line;
   }
   ast_verb(3, "skinny_request(%s)\n", tmp);
   tmpc = skinny_new(l, subline, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL, SKINNY_INCOMING);
   if (!tmpc) {
      ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
   } else if (subline) {
      struct skinny_subchannel *sub = ast_channel_tech_pvt(tmpc);
      subline->sub = sub;
      subline->calldirection = SKINNY_INCOMING;
      subline->substate = SUBSTATE_UNSET;
      subline->callid = sub->callid;
      sub->subline = subline;
   }
   return tmpc;
}
static struct ast_frame* skinny_rtp_read ( struct skinny_subchannel sub) [static, read]

Definition at line 4456 of file chan_skinny.c.

References ast_channel_fdno(), ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_writeformat(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_set(), AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), ast_udptl_read(), f, ast_frame_subclass::format, ast_frame::frametype, skinny_subchannel::owner, skinny_subchannel::rtp, ast_frame::subclass, and skinny_subchannel::vrtp.

Referenced by skinny_read().

{
   struct ast_channel *ast = sub->owner;
   struct ast_frame *f;

   if (!sub->rtp) {
      /* We have no RTP allocated for this channel */
      return &ast_null_frame;
   }

   switch(ast_channel_fdno(ast)) {
   case 0:
      f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
      break;
   case 1:
      f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
      break;
   case 2:
      f = ast_rtp_instance_read(sub->vrtp, 0); /* RTP Video */
      break;
   case 3:
      f = ast_rtp_instance_read(sub->vrtp, 1); /* RTCP Control Channel for video */
      break;
#if 0
   case 5:
      /* Not yet supported */
      f = ast_udptl_read(sub->udptl); /* UDPTL for T.38 */
      break;
#endif
   default:
      f = &ast_null_frame;
   }

   if (ast) {
      /* We already hold the channel lock */
      if (f->frametype == AST_FRAME_VOICE) {
         if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
            ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
            ast_format_cap_set(ast_channel_nativeformats(ast), &f->subclass.format);
            ast_set_read_format(ast, ast_channel_readformat(ast));
            ast_set_write_format(ast, ast_channel_writeformat(ast));
         }
      }
   }
   return f;
}
static int skinny_sched_add ( int  when,
ast_sched_cb  callback,
struct skinny_subchannel sub 
) [static]

Definition at line 1866 of file chan_skinny.c.

References ast_sched_add(), skinny_subchannel::callid, and SKINNY_DEBUG.

Referenced by handle_soft_key_event_message(), setsubstate(), skinny_call(), and skinny_dialer().

{
   int ret;
   ret = ast_sched_add(sched, when, callback, sub);
   SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Added SCHED %d\n",
      sub->callid, ret);
   return ret;
}
static int skinny_sched_del ( int  sched_id,
struct skinny_subchannel sub 
) [static]

Definition at line 1859 of file chan_skinny.c.

References ast_sched_del(), skinny_subchannel::callid, and SKINNY_DEBUG.

Referenced by handle_keypad_button_message(), handle_soft_key_event_message(), and setsubstate().

{
   SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Deleting SCHED %d\n",
      sub->callid, sched_id);
   return ast_sched_del(sched, sched_id);
}
static int skinny_senddigit_begin ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 4557 of file chan_skinny.c.

{
   return -1; /* Start inband indications */
}
static int skinny_senddigit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 4562 of file chan_skinny.c.

References skinny_line::device, skinny_subchannel::line, sub, and ast_channel::tech_pvt.

{
#if 0
   struct skinny_subchannel *sub = ast->tech_pvt;
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;
   int tmp;
   /* not right */
   sprintf(tmp, "%d", digit);
   //transmit_tone(d, digit, l->instance, sub->callid);
#endif
   return -1; /* Stop inband indications */
}
static void* skinny_session ( void *  data) [static]

Definition at line 6950 of file chan_skinny.c.

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

Referenced by accept_thread().

{
   int res;
   struct skinny_req *req;
   struct skinnysession *s = data;

   ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));

   for (;;) {
      res = get_input(s);
      if (res < 0) {
         ast_verb(3, "Ending Skinny session from %s (bad input)\n", ast_inet_ntoa(s->sin.sin_addr));
         destroy_session(s);
         return NULL;
      }

      if (res > 0)
      {
         if (!(req = skinny_req_parse(s))) {
            ast_verb(3, "Ending Skinny session from %s (failed parse)\n", ast_inet_ntoa(s->sin.sin_addr));
            destroy_session(s);
            return NULL;
         }

         res = handle_message(req, s);
         if (res < 0) {
            ast_verb(3, "Ending Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
            destroy_session(s);
            return NULL;
         }
      }
   }
   ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));

   if (s)
      destroy_session(s);

   return 0;
}
static int skinny_set_rtp_peer ( struct ast_channel c,
struct ast_rtp_instance rtp,
struct ast_rtp_instance vrtp,
struct ast_rtp_instance trtp,
const struct ast_format_cap codecs,
int  nat_active 
) [static]

Definition at line 3199 of file chan_skinny.c.

References ast_best_codec(), ast_channel_tech_pvt(), ast_codec_pref_getsize(), ast_getformatname(), ast_inet_ntoa(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_sockaddr_to_sin, AST_STATE_UP, skinny_line::cap, ast_format_list::cur_ms, skinny_line::device, ast_format_list::format, skinny_device::ourip, SKINNY_DEBUG, sub, transmit_startmediatransmission(), and transmit_stopmediatransmission().

{
   struct skinny_subchannel *sub;
   struct skinny_line *l;
   struct skinny_device *d;
   struct ast_format_list fmt;
   struct sockaddr_in us = { 0, };
   struct sockaddr_in them = { 0, };
   struct ast_sockaddr them_tmp;
   struct ast_sockaddr us_tmp;
   
   sub = ast_channel_tech_pvt(c);

   if (ast_channel_state(c) != AST_STATE_UP)
      return 0;

   if (!sub) {
      return -1;
   }

   l = sub->line;
   d = l->device;

   if (rtp){
      struct ast_format tmpfmt;
      ast_rtp_instance_get_remote_address(rtp, &them_tmp);
      ast_sockaddr_to_sin(&them_tmp, &them);

      /* Shutdown any early-media or previous media on re-invite */
      transmit_stopmediatransmission(d, sub);

      SKINNY_DEBUG(DEBUG_AUDIO, 4, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port));

      ast_best_codec(l->cap, &tmpfmt);
      fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);

      SKINNY_DEBUG(DEBUG_AUDIO, 4, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(&fmt.format), fmt.cur_ms);

      if (!(l->directmedia) || (l->nat)){
         ast_rtp_instance_get_local_address(rtp, &us_tmp);
         ast_sockaddr_to_sin(&us_tmp, &us);
         us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
         transmit_startmediatransmission(d, sub, us, fmt);
      } else {
         transmit_startmediatransmission(d, sub, them, fmt);
      }

      return 0;
   }
   /* Need a return here to break the bridge */
   return 0;
}
static int skinny_transfer ( struct skinny_subchannel sub) [static]

Definition at line 4671 of file chan_skinny.c.

References ast_bridged_channel(), ast_channel_masquerade(), ast_channel_name(), ast_channel_zone(), AST_CONTROL_UNHOLD, ast_debug, ast_get_indication_tone(), ast_log(), ast_playtones_start(), ast_queue_control(), AST_STATE_RING, ast_tone_zone_sound_unref(), ast_tone_zone_sound::data, LOG_WARNING, skinny_subchannel::owner, skinny_subchannel::related, SKINNY_DEBUG, sub, and skinny_subchannel::xferor.

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

{
   struct skinny_subchannel *xferor; /* the sub doing the transferring */
   struct skinny_subchannel *xferee; /* the sub being transferred */
   struct ast_tone_zone_sound *ts = NULL;

   if (ast_bridged_channel(sub->owner) || ast_bridged_channel(sub->related->owner)) {
      if (sub->xferor) {
         xferor = sub;
         xferee = sub->related;
      } else {
         xferor = sub;
         xferee = sub->related;
      }

      SKINNY_DEBUG(DEBUG_SUB, 3, "Transferee channels (local/remote): %s and %s\n",
         ast_channel_name(xferee->owner), ast_bridged_channel(xferee->owner) ? ast_channel_name(ast_bridged_channel(xferee->owner)) : "");
      SKINNY_DEBUG(DEBUG_SUB, 3, "Transferor channels (local/remote): %s and %s\n",
         ast_channel_name(xferor->owner), ast_bridged_channel(xferor->owner) ? ast_channel_name(ast_bridged_channel(xferor->owner)) : "");

      if (ast_bridged_channel(xferor->owner)) {
         if (ast_bridged_channel(xferee->owner)) {
            ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
         }
         if (ast_channel_state(xferor->owner) == AST_STATE_RING) {
            /* play ringing inband */
            if ((ts = ast_get_indication_tone(ast_channel_zone(xferor->owner), "ring"))) {
               ast_playtones_start(xferor->owner, 0, ts->data, 1);
               ts = ast_tone_zone_sound_unref(ts);
            }
         }
         SKINNY_DEBUG(DEBUG_SUB, 3, "Transfer Masquerading %s to %s\n",
            ast_channel_name(xferee->owner), ast_bridged_channel(xferor->owner) ? ast_channel_name(ast_bridged_channel(xferor->owner)) : "");
         if (ast_channel_masquerade(xferee->owner, ast_bridged_channel(xferor->owner))) {
            ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
               ast_channel_name(ast_bridged_channel(xferor->owner)), ast_channel_name(xferee->owner));
            return -1;
         }
      } else if (ast_bridged_channel(xferee->owner)) {
         ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
         if (ast_channel_state(xferor->owner) == AST_STATE_RING) {
            /* play ringing inband */
            if ((ts = ast_get_indication_tone(ast_channel_zone(xferor->owner), "ring"))) {
               ast_playtones_start(xferor->owner, 0, ts->data, 1);
               ts = ast_tone_zone_sound_unref(ts);
            }
         }
         SKINNY_DEBUG(DEBUG_SUB, 3, "Transfer Masquerading %s to %s\n",
            ast_channel_name(xferor->owner), ast_bridged_channel(xferee->owner) ? ast_channel_name(ast_bridged_channel(xferee->owner)) : "");
         if (ast_channel_masquerade(xferor->owner, ast_bridged_channel(xferee->owner))) {
            ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
               ast_channel_name(ast_bridged_channel(xferee->owner)), ast_channel_name(xferor->owner));
            return -1;
         }
         return 0;
      } else {
         ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
            ast_channel_name(xferor->owner), ast_channel_name(xferee->owner));
      }
   }
   return 0;
}
static int skinny_unregister ( struct skinny_req req,
struct skinnysession s 
) [static]

Definition at line 2163 of file chan_skinny.c.

References AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_extension_state_del(), ast_format_cap_remove_all(), AST_LIST_TRAVERSE, ast_parse_allow_disallow(), skinny_line::cap, skinny_line::device, skinnysession::device, EVENT_FLAG_SYSTEM, skinny_device::lines, manager_event, skinny_device::session, skinny_device::speeddials, skinny_speeddial::stateid, and unregister_exten().

Referenced by get_input(), handle_message(), and transmit_response_bysession().

{
   struct skinny_device *d;
   struct skinny_line *l;
   struct skinny_speeddial *sd;

   d = s->device;

   if (d) {
      d->session = NULL;

      AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
         if (sd->stateid > -1)
            ast_extension_state_del(sd->stateid, NULL);
      }
      AST_LIST_TRAVERSE(&d->lines, l, list) {
         if (l->device == d) {
            ast_format_cap_remove_all(l->cap);
            ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0);
            l->instance = 0;
            manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
            unregister_exten(l);
            ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
         }
      }
   }

   return -1; /* main loop will destroy the session */
}
static int skinny_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]
static void start_rtp ( struct skinny_subchannel sub) [static]

Definition at line 4201 of file chan_skinny.c.

References ast_channel_set_fd(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_codecs_packetization_set(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, AST_RTP_PROPERTY_RTCP, ast_sockaddr_from_sin, bindaddr, skinny_line::device, skinny_subchannel::line, skinny_subchannel::lock, skinny_subchannel::owner, qos, skinny_subchannel::rtp, transmit_connect(), and skinny_subchannel::vrtp.

Referenced by setsubstate(), and skinny_newcall().

{
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;
   int hasvideo = 0;
   struct ast_sockaddr bindaddr_tmp;

   ast_mutex_lock(&sub->lock);
   /* Allocate the RTP */
   ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
   sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
   if (hasvideo)
      sub->vrtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);

   if (sub->rtp) {
      ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
   }
   if (sub->vrtp) {
      ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_RTCP, 1);
   }

   if (sub->rtp && sub->owner) {
      ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
      ast_channel_set_fd(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
   }
   if (hasvideo && sub->vrtp && sub->owner) {
      ast_channel_set_fd(sub->owner, 2, ast_rtp_instance_fd(sub->vrtp, 0));
      ast_channel_set_fd(sub->owner, 3, ast_rtp_instance_fd(sub->vrtp, 1));
   }
   if (sub->rtp) {
      ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
      ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat);
   }
   if (sub->vrtp) {
      ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
      ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat);
   }
   /* Set Frame packetization */
   if (sub->rtp)
      ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs);

   /* Create the RTP connection */
   transmit_connect(d, sub);
   ast_mutex_unlock(&sub->lock);
}
static char* substate2str ( int  ind) [static]

Definition at line 4929 of file chan_skinny.c.

References ast_threadstorage_get(), SUBSTATE2STR_BUFSIZE, substate2str_threadbuf, SUBSTATE_BUSY, SUBSTATE_CALLWAIT, SUBSTATE_CONGESTION, SUBSTATE_CONNECTED, SUBSTATE_DIALING, SUBSTATE_HOLD, SUBSTATE_OFFHOOK, SUBSTATE_ONHOOK, SUBSTATE_PROGRESS, SUBSTATE_RINGIN, SUBSTATE_RINGOUT, and SUBSTATE_UNSET.

Referenced by setsubstate().

                                   {
   char *tmp;

   switch (ind) {
   case SUBSTATE_UNSET:
      return "SUBSTATE_UNSET";
   case SUBSTATE_OFFHOOK:
      return "SUBSTATE_OFFHOOK";
   case SUBSTATE_ONHOOK:
      return "SUBSTATE_ONHOOK";
   case SUBSTATE_RINGOUT:
      return "SUBSTATE_RINGOUT";
   case SUBSTATE_RINGIN:
      return "SUBSTATE_RINGIN";
   case SUBSTATE_CONNECTED:
      return "SUBSTATE_CONNECTED";
   case SUBSTATE_BUSY:
      return "SUBSTATE_BUSY";
   case SUBSTATE_CONGESTION:
      return "SUBSTATE_CONGESTION";
   case SUBSTATE_PROGRESS:
      return "SUBSTATE_PROGRESS";
   case SUBSTATE_HOLD:
      return "SUBSTATE_HOLD";
   case SUBSTATE_CALLWAIT:
      return "SUBSTATE_CALLWAIT";
   case SUBSTATE_DIALING:
      return "SUBSTATE_DIALING";
   default:
      if (!(tmp = ast_threadstorage_get(&substate2str_threadbuf, SUBSTATE2STR_BUFSIZE)))
                        return "Unknown";
      snprintf(tmp, SUBSTATE2STR_BUFSIZE, "UNKNOWN-%d", ind);
      return tmp;
   }
}
static void transmit_activatecallplane ( struct skinny_device d,
struct skinny_line l 
) [static]

Definition at line 2673 of file chan_skinny.c.

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

Referenced by handle_callforward_button(), setsubstate(), and skinny_extensionstate_cb().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
      return;

   req->data.activatecallplane.lineInstance = htolel(l->instance);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting ACTIVATE_CALL_PLANE_MESSAGE to %s, inst %d\n",
      d->name, l->instance);
   transmit_response(d, req);
}
static void transmit_backspace ( struct skinny_device d,
int  instance,
unsigned  callid 
) [static]

Definition at line 2966 of file chan_skinny.c.

References BKSP_REQ_MESSAGE, skinny_data::bkspmessage, bksp_req_message::callreference, skinny_req::data, htolel, bksp_req_message::instance, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by handle_soft_key_event_message().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct bksp_req_message), BKSP_REQ_MESSAGE)))
      return;

   req->data.bkspmessage.instance = htolel(instance);
   req->data.bkspmessage.callreference = htolel(callid);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting BKSP_REQ_MESSAGE to %s, inst %d, callid %d \n",
      d->name, instance, callid);
   transmit_response(d, req);
}
static void transmit_callinfo ( struct skinny_device d,
int  instance,
int  callid,
char *  fromname,
char *  fromnum,
char *  toname,
char *  tonum,
int  calldirection 
) [static]

Definition at line 2313 of file chan_skinny.c.

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

Referenced by push_callinfo(), and send_callinfo().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
      return;

   ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
   ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
   ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
   ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
   req->data.callinfo.instance = htolel(instance);
   req->data.callinfo.reference = htolel(callid);
   req->data.callinfo.type = htolel(calldirection);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting CALL_INFO_MESSAGE to %s, to %s(%s) from %s(%s) (dir=%d) on %s(%d)\n",
      d->name, toname, tonum, fromname, fromnum, calldirection, d->name, instance);
   transmit_response(d, req);
}
static void transmit_callstate ( struct skinny_device d,
int  buttonInstance,
unsigned  callid,
int  state 
) [static]

Definition at line 2687 of file chan_skinny.c.

References CALL_STATE_MESSAGE, call_state_message::callReference, call_state_message::callState, skinny_data::callstate, skinny_req::data, htolel, call_state_message::lineInstance, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by handle_callforward_button(), setsubstate(), and skinny_extensionstate_cb().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
      return;

   req->data.callstate.callState = htolel(state);
   req->data.callstate.lineInstance = htolel(buttonInstance);
   req->data.callstate.callReference = htolel(callid);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting CALL_STATE_MESSAGE to %s, state %s, inst %d, callid %d\n",
      d->name, callstate2str(state), buttonInstance, callid);
   transmit_response(d, req);
}
static void transmit_capabilitiesreq ( struct skinny_device d) [static]

Definition at line 2955 of file chan_skinny.c.

References CAPABILITIES_REQ_MESSAGE, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by handle_message().

{
   struct skinny_req *req;

   if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
      return;

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting CAPABILITIES_REQ_MESSAGE to %s\n", d->name);
   transmit_response(d, req);
}
static void transmit_cfwdstate ( struct skinny_device d,
struct skinny_line l 
) [static]

Definition at line 2703 of file chan_skinny.c.

References forward_stat_message::activeforward, ast_copy_string(), ast_strlen_zero(), 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, forward_stat_message::lineNumber, req_alloc(), SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_DEBUG, and transmit_response().

Referenced by dialandactivatesub(), and handle_callforward_button().

{
   struct skinny_req *req;
   int anyon = 0;

   if (!(req = req_alloc(sizeof(struct forward_stat_message), FORWARD_STAT_MESSAGE)))
      return;

   if (l->cfwdtype & SKINNY_CFWD_ALL) {
      if (!ast_strlen_zero(l->call_forward_all)) {
         ast_copy_string(req->data.forwardstat.fwdallnum, l->call_forward_all, sizeof(req->data.forwardstat.fwdallnum));
         req->data.forwardstat.fwdall = htolel(1);
         anyon++;
      } else {
         req->data.forwardstat.fwdall = htolel(0);
      }
   }
   if (l->cfwdtype & SKINNY_CFWD_BUSY) {
      if (!ast_strlen_zero(l->call_forward_busy)) {
         ast_copy_string(req->data.forwardstat.fwdbusynum, l->call_forward_busy, sizeof(req->data.forwardstat.fwdbusynum));
         req->data.forwardstat.fwdbusy = htolel(1);
         anyon++;
      } else {
         req->data.forwardstat.fwdbusy = htolel(0);
      }
   }
   if (l->cfwdtype & SKINNY_CFWD_NOANSWER) {
      if (!ast_strlen_zero(l->call_forward_noanswer)) {
         ast_copy_string(req->data.forwardstat.fwdnoanswernum, l->call_forward_noanswer, sizeof(req->data.forwardstat.fwdnoanswernum));
         req->data.forwardstat.fwdnoanswer = htolel(1);
         anyon++;
      } else {
         req->data.forwardstat.fwdnoanswer = htolel(0);
      }
   }
   req->data.forwardstat.lineNumber = htolel(l->instance);
   if (anyon)
      req->data.forwardstat.activeforward = htolel(7);
   else
      req->data.forwardstat.activeforward = htolel(0);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting FORWARD_STAT_MESSAGE to %s, inst %d, all %s, busy %s, noans %s, acitve %d\n",
      d->name, l->instance, l->call_forward_all, l->call_forward_busy, l->call_forward_noanswer, anyon ? 7 : 0);
   transmit_response(d, req);
}
static void transmit_clear_display_message ( struct skinny_device d,
int  instance,
int  reference 
) [static]

Definition at line 2512 of file chan_skinny.c.

References CLEAR_DISPLAY_MESSAGE, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by handle_callforward_button(), and setsubstate().

{
   struct skinny_req *req;
   if (!(req = req_alloc(sizeof(struct clear_display_message), CLEAR_DISPLAY_MESSAGE)))
      return;

   //what do we want hear CLEAR_DISPLAY_MESSAGE or CLEAR_PROMPT_STATUS???
   //if we are clearing the display, it appears there is no instance and refernece info (size 0)
   //req->data.clearpromptstatus.lineInstance = instance;
   //req->data.clearpromptstatus.callReference = reference;

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting CLEAR_DISPLAY_MESSAGE to %s\n", d->name);
   transmit_response(d, req);
}
static void transmit_clearpromptmessage ( struct skinny_device d,
int  instance,
int  callid 
) [static]

Definition at line 2575 of file chan_skinny.c.

References clear_prompt_message::callReference, CLEAR_PROMPT_MESSAGE, skinny_data::clearpromptstatus, skinny_req::data, htolel, clear_prompt_message::lineInstance, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by handle_callforward_button(), setsubstate(), and skinny_extensionstate_cb().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
      return;

   req->data.clearpromptstatus.lineInstance = htolel(instance);
   req->data.clearpromptstatus.callReference = htolel(callid);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting CLEAR_PROMPT_MESSAGE to %s, inst %d, callid %d\n",
      d->name, instance, callid);
   transmit_response(d, req);
}
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]

Definition at line 2403 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), open_receive_channel_message::bitrate, skinny_subchannel::callid, skinny_line::cap, open_receive_channel_message::capability, codec_ast2skinny(), open_receive_channel_message::conferenceId, ast_format_list::cur_ms, skinny_req::data, open_receive_channel_message::echo, ast_format_list::format, htolel, skinny_subchannel::line, OPEN_RECEIVE_CHANNEL_MESSAGE, skinny_data::openreceivechannel, open_receive_channel_message::packets, open_receive_channel_message::partyId, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by setsubstate(), and start_rtp().

{
   struct skinny_req *req;
   struct skinny_line *l = sub->line;
   struct ast_format_list fmt;
   struct ast_format tmpfmt;

   if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
      return;
   ast_best_codec(l->cap, &tmpfmt);
   fmt = ast_codec_pref_getsize(&l->prefs, &tmpfmt);

   req->data.openreceivechannel.conferenceId = htolel(sub->callid);
   req->data.openreceivechannel.partyId = htolel(sub->callid);
   req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
   req->data.openreceivechannel.capability = htolel(codec_ast2skinny(&fmt.format));
   req->data.openreceivechannel.echo = htolel(0);
   req->data.openreceivechannel.bitrate = htolel(0);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting OPEN_RECEIVE_CHANNEL_MESSAGE to %s, confid %d, partyid %d, ms %d, fmt %d, echo %d, brate %d\n",
      d->name, sub->callid, sub->callid, fmt.cur_ms, codec_ast2skinny(&fmt.format), 0, 0);
   transmit_response(d, req);
}
static void transmit_definetimedate ( struct skinny_device d) [static]

Definition at line 2790 of file chan_skinny.c.

References ast_localtime(), ast_tvnow(), skinny_req::data, definetimedate_message::day, definetimedate_message::dayofweek, skinny_data::definetimedate, DEFINETIMEDATE_MESSAGE, definetimedate_message::hour, htolel, definetimedate_message::milliseconds, definetimedate_message::minute, definetimedate_message::month, req_alloc(), definetimedate_message::seconds, SKINNY_DEBUG, 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 handle_message(), handle_offhook_message(), handle_onhook_message(), handle_soft_key_event_message(), and setsubstate().

{
   struct skinny_req *req;
   struct timeval now = ast_tvnow();
   struct ast_tm cmtime;

   if (!(req = req_alloc(sizeof(struct definetimedate_message), DEFINETIMEDATE_MESSAGE)))
      return;

   ast_localtime(&now, &cmtime, NULL);
   req->data.definetimedate.year = htolel(cmtime.tm_year+1900);
   req->data.definetimedate.month = htolel(cmtime.tm_mon+1);
   req->data.definetimedate.dayofweek = htolel(cmtime.tm_wday);
   req->data.definetimedate.day = htolel(cmtime.tm_mday);
   req->data.definetimedate.hour = htolel(cmtime.tm_hour);
   req->data.definetimedate.minute = htolel(cmtime.tm_min);
   req->data.definetimedate.seconds = htolel(cmtime.tm_sec);
   req->data.definetimedate.milliseconds = htolel(cmtime.tm_usec / 1000);
   req->data.definetimedate.timestamp = htolel(now.tv_sec);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting DEFINETIMEDATE_MESSAGE to %s, date %d %d %d dow %d time %d:%d:%d.%d\n",
      d->name, req->data.definetimedate.year, req->data.definetimedate.month, req->data.definetimedate.day, req->data.definetimedate.dayofweek,
      req->data.definetimedate.hour, req->data.definetimedate.minute, req->data.definetimedate.seconds, req->data.definetimedate.milliseconds);
   transmit_response(d, req);
}
static void transmit_dialednumber ( struct skinny_device d,
const char *  text,
int  instance,
int  callid 
) [static]

Definition at line 2590 of file chan_skinny.c.

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

Referenced by setsubstate().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct dialed_number_message), DIALED_NUMBER_MESSAGE)))
      return;

   ast_copy_string(req->data.dialednumber.dialedNumber, text, sizeof(req->data.dialednumber.dialedNumber));
   req->data.dialednumber.lineInstance = htolel(instance);
   req->data.dialednumber.callReference = htolel(callid);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting DIALED_NUMBER_MESSAGE to %s, num %s, inst %d, callid %d\n",
      d->name, text, instance, callid);
   transmit_response(d, req);
}
static void transmit_keepaliveack ( struct skinny_device d) [static]

Definition at line 2917 of file chan_skinny.c.

References KEEP_ALIVE_ACK_MESSAGE, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by handle_message().

{
   struct skinny_req *req;

   if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
      return;

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting KEEP_ALIVE_ACK_MESSAGE to %s\n", d->name);
   transmit_response(d, req);
}
static void transmit_lamp_indication ( struct skinny_device d,
int  stimulus,
int  instance,
int  indication 
) [static]

Definition at line 2471 of file chan_skinny.c.

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

Referenced by dialandactivatesub(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), mwi_event_cb(), setsubstate(), and skinny_extensionstate_cb().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
      return;

   req->data.setlamp.stimulus = htolel(stimulus);
   req->data.setlamp.stimulusInstance = htolel(instance);
   req->data.setlamp.deviceStimulus = htolel(indication);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting SET_LAMP_MESSAGE to %s, stim %d, inst %d, ind %d\n",
      d->name, stimulus, instance, indication);
   transmit_response(d, req);
}
static void transmit_linestatres ( struct skinny_device d,
int  instance 
) [static]

Definition at line 2766 of file chan_skinny.c.

References skinny_req::data, find_line_by_instance(), find_speeddial_by_instance(), skinny_speeddial::instance, skinny_speeddial::label, letohl, LINE_STAT_RES_MESSAGE, line_stat_res_message::lineDirNumber, line_stat_res_message::lineDisplayName, line_stat_res_message::lineNumber, skinny_data::linestat, req_alloc(), SKINNY_DEBUG, and transmit_response().

Referenced by handle_message().

{
   struct skinny_req *req;
   struct skinny_line *l;
   struct skinny_speeddial *sd;

   if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
      return;

   if ((l = find_line_by_instance(d, instance))) {
      req->data.linestat.lineNumber = letohl(l->instance);
      memcpy(req->data.linestat.lineDirNumber, l->name, sizeof(req->data.linestat.lineDirNumber));
      memcpy(req->data.linestat.lineDisplayName, l->label, sizeof(req->data.linestat.lineDisplayName));
   } else if ((sd = find_speeddial_by_instance(d, instance, 1))) {
      req->data.linestat.lineNumber = letohl(sd->instance);
      memcpy(req->data.linestat.lineDirNumber, sd->label, sizeof(req->data.linestat.lineDirNumber));
      memcpy(req->data.linestat.lineDisplayName, sd->label, sizeof(req->data.linestat.lineDisplayName));
   }

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting LINE_STAT_RES_MESSAGE to %s, inst %d, num %s, label %s\n",
      d->name, l->instance, req->data.linestat.lineDirNumber, req->data.linestat.lineDisplayName);
   transmit_response(d, req);
}
static void transmit_microphone_mode ( struct skinny_device d,
int  mode 
) [static]

Definition at line 2299 of file chan_skinny.c.

References skinny_req::data, htolel, set_microphone_message::mode, req_alloc(), SET_MICROPHONE_MESSAGE, skinny_data::setmicrophone, SKINNY_DEBUG, and transmit_response().

Referenced by setsubstate().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct set_microphone_message), SET_MICROPHONE_MESSAGE)))
      return;

   req->data.setmicrophone.mode = htolel(mode);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting SET_MICROPHONE_MESSAGE to %s, mode %d\n", d->name, mode);
   transmit_response(d, req);
}
static void transmit_registerack ( struct skinny_device d) [static]

Definition at line 2928 of file chan_skinny.c.

References skinny_req::data, register_ack_message::dateTemplate, htolel, register_ack_message::keepAlive, skinny_data::regack, REGISTER_ACK_MESSAGE, req_alloc(), register_ack_message::res, skinny_req::res, register_ack_message::res2, register_ack_message::secondaryKeepAlive, SKINNY_DEBUG, and transmit_response().

Referenced by handle_message().

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
      return;

   req->data.regack.res[0] = '0';
   req->data.regack.res[1] = '\0';
   req->data.regack.keepAlive = htolel(keep_alive);
   memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
   req->data.regack.res2[0] = '0';
   req->data.regack.res2[1] = '\0';
   req->data.regack.secondaryKeepAlive = htolel(keep_alive);

#ifdef AST_DEVMODE
   {
   short res = req->data.regack.res[0] << 8 | req->data.regack.res[1];
   int res2 = req->data.regack.res2[0] << 24 | req->data.regack.res2[1] << 16 | req->data.regack.res2[2] << 8 | req->data.regack.res2[3];
   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting REGISTER_ACK_MESSAGE to %s, keepalive %d, datetemplate %s, seckeepalive %d, res 0x%04x, res2 0x%08x\n",
      d->name, keep_alive, date_format, keep_alive, res, res2);
   }
#endif

   transmit_response(d, req);
}
static void transmit_registerrej ( struct skinnysession s) [static]

Definition at line 2271 of file chan_skinny.c.

References skinny_req::data, register_rej_message::errMsg, register_message::name, skinny_data::reg, REGISTER_REJ_MESSAGE, skinny_data::regrej, req_alloc(), SKINNY_DEBUG, and transmit_response_bysession().

Referenced by handle_message().

{
   struct skinny_req *req;
   char name[16];

   if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
      return;

   memcpy(&name, req->data.reg.name, sizeof(name));
   snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting REGISTER_REJ_MESSAGE to UNKNOWN_DEVICE\n");
   transmit_response_bysession(s, req);
}
static void transmit_reset ( struct skinny_device d,
int  fullrestart 
) [static]

Definition at line 2900 of file chan_skinny.c.

References skinny_req::data, req_alloc(), skinny_data::reset, RESET_MESSAGE, reset_message::resetType, SKINNY_DEBUG, and transmit_response().

Referenced by handle_skinny_reset(), and skinny_reload().

{
   struct skinny_req *req;
  
   if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
      return;
  
   if (fullrestart)
      req->data.reset.resetType = 2;
   else
      req->data.reset.resetType = 1;

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting RESET_MESSAGE to %s, type %s\n",
      d->name, (fullrestart) ? "Restarting" : "Resetting");
   transmit_response(d, req);
}
static int transmit_response_bysession ( struct skinnysession s,
struct skinny_req req 
) [static]

Definition at line 2229 of file chan_skinny.c.

References ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, skinny_req::data, errno, skinnysession::fd, skinny_req::len, letohl, skinnysession::lock, LOG_WARNING, skinnysession::outbuf, SKINNY_MAX_PACKET, and skinny_unregister().

Referenced by transmit_registerrej(), and transmit_response().

{
   int res = 0;

   if (!s) {
      ast_log(LOG_WARNING, "Asked to transmit to a non-existent session!\n");
      return -1;
   }

   ast_mutex_lock(&s->lock);

   if ((letohl(req->len) > SKINNY_MAX_PACKET) || (letohl(req->len) < 0)) {
      ast_log(LOG_WARNING, "transmit_response: the length of the request (%d) is out of bounds (%d)\n", letohl(req->len), SKINNY_MAX_PACKET);
      ast_mutex_unlock(&s->lock);
      return -1;
   }

   memset(s->outbuf, 0, sizeof(s->outbuf));
   memcpy(s->outbuf, req, skinny_header_size);
   memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));

   res = write(s->fd, s->outbuf, letohl(req->len)+8);

   if (res != letohl(req->len)+8) {
      ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
      if (res == -1) {
         ast_log(LOG_WARNING, "Transmit: Skinny Client was lost, unregistering\n");
         skinny_unregister(NULL, s);
      }

   }

   ast_free(req);
   ast_mutex_unlock(&s->lock);
   return 1;
}
static void transmit_ringer_mode ( struct skinny_device d,
int  mode 
) [static]

Definition at line 2487 of file chan_skinny.c.

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

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

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct set_ringer_message), SET_RINGER_MESSAGE)))
      return;

   req->data.setringer.ringerMode = htolel(mode);
   /* XXX okay, I don't quite know what this is, but here's what happens (on a 7960).
      Note: The phone will always show as ringing on the display.

      1: phone will audibly ring over and over
      2: phone will audibly ring only once
      any other value, will NOT cause the phone to audibly ring
   */
   req->data.setringer.unknown1 = htolel(1);
   /* XXX the value here doesn't seem to change anything.  Must be higher than 0.
      Perhaps a packet capture can shed some light on this. */
   req->data.setringer.unknown2 = htolel(1);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting SET_RINGER_MESSAGE to %s, mode %d, unk1 1, unk2 1\n",
      d->name, mode);
   transmit_response(d, req);
}
static void transmit_selectsoftkeys ( struct skinny_device d,
int  instance,
int  callid,
int  softkey 
) [static]
static void transmit_softkeysetres ( struct skinny_device d) [static]

Definition at line 2844 of file chan_skinny.c.

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

Referenced by handle_message().

{
   struct skinny_req *req;
   int i;
   int x;
   int y;
   const struct soft_key_definitions *softkeymode = soft_key_default_definitions;

   if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
      return;

   SKINNY_DEBUG(DEBUG_TEMPLATE, 3, "Creating Softkey Template\n");

   req->data.softkeysets.softKeySetOffset = htolel(0);
   req->data.softkeysets.softKeySetCount = htolel(13);
   req->data.softkeysets.totalSoftKeySetCount = htolel(13);
   for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
      const uint8_t *defaults = softkeymode->defaults;
      /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
         This will have to do for now. */
      for (y = 0; y < softkeymode->count; y++) {
         for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
            if (defaults[y] == i+1) {
               req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = (i+1);
               req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htoles(i+301);
               SKINNY_DEBUG(DEBUG_TEMPLATE, 4, "softKeySetDefinition : softKeyTemplateIndex: %d softKeyInfoIndex: %d\n",
                  i+1, i+301);
            }
         }
      }
      softkeymode++;
   }

   SKINNY_DEBUG(DEBUG_PACKET | DEBUG_TEMPLATE, 3, "Transmitting SOFT_KEY_SET_RES_MESSAGE to %s, template data\n",
      d->name);
   transmit_response(d, req);
}
static void transmit_speaker_mode ( struct skinny_device d,
int  mode 
) [static]

Definition at line 2286 of file chan_skinny.c.

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

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

{
   struct skinny_req *req;

   if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
      return;

   req->data.setspeaker.mode = htolel(mode);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting SET_SPEAKER_MESSAGE to %s, mode %d\n", d->name, mode);
   transmit_response(d, req);
}
static void transmit_start_tone ( struct skinny_device d,
int  tone,
int  instance,
int  reference 
) [static]

Definition at line 2427 of file chan_skinny.c.

References skinny_req::data, htolel, start_tone_message::instance, start_tone_message::reference, req_alloc(), SKINNY_DEBUG, START_TONE_MESSAGE, skinny_data::starttone, start_tone_message::tone, and transmit_response().

Referenced by dialandactivatesub(), handle_soft_key_event_message(), setsubstate(), skinny_dialer(), and skinny_newcall().

{
   struct skinny_req *req;
   if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
      return;
   req->data.starttone.tone = htolel(tone);
   req->data.starttone.instance = htolel(instance);
   req->data.starttone.reference = htolel(reference);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting START_TONE_MESSAGE to %s, tone %d, inst %d, ref %d\n",
      d->name, tone, instance, reference);
   transmit_response(d, req);
}
static void transmit_startmediatransmission ( struct skinny_device d,
struct skinny_subchannel sub,
struct sockaddr_in  dest,
struct ast_format_list  fmt 
) [static]

Definition at line 2636 of file chan_skinny.c.

References ast_inet_ntoa(), media_qualifier::bitRate, skinny_subchannel::callid, codec_ast2skinny(), start_media_transmission_message_ip4::conferenceId, start_media_transmission_message_ip6::conferenceId, ast_format_list::cur_ms, skinny_req::data, ast_format_list::format, htolel, media_qualifier::packets, start_media_transmission_message_ip4::packetSize, start_media_transmission_message_ip6::packetSize, start_media_transmission_message_ip4::passThruPartyId, start_media_transmission_message_ip6::passThruPartyId, start_media_transmission_message_ip4::payloadType, start_media_transmission_message_ip6::payloadType, media_qualifier::precedence, start_media_transmission_message_ip4::qualifier, start_media_transmission_message_ip6::qualifier, start_media_transmission_message_ip4::remoteIp, start_media_transmission_message_ip6::remoteIp, start_media_transmission_message_ip4::remotePort, start_media_transmission_message_ip6::remotePort, req_alloc(), SKINNY_DEBUG, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia_ip4, skinny_data::startmedia_ip6, transmit_response(), and media_qualifier::vad.

Referenced by handle_open_receive_channel_ack_message(), and skinny_set_rtp_peer().

{
   struct skinny_req *req;

   if (d->protocolversion < 17) {
      if (!(req = req_alloc(sizeof(struct start_media_transmission_message_ip4), START_MEDIA_TRANSMISSION_MESSAGE)))
         return;
      req->data.startmedia_ip4.conferenceId = htolel(sub->callid);
      req->data.startmedia_ip4.passThruPartyId = htolel(sub->callid);
      req->data.startmedia_ip4.remoteIp = dest.sin_addr.s_addr;
      req->data.startmedia_ip4.remotePort = htolel(ntohs(dest.sin_port));
      req->data.startmedia_ip4.packetSize = htolel(fmt.cur_ms);
      req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(&fmt.format));
      req->data.startmedia_ip4.qualifier.precedence = htolel(127);
      req->data.startmedia_ip4.qualifier.vad = htolel(0);
      req->data.startmedia_ip4.qualifier.packets = htolel(0);
      req->data.startmedia_ip4.qualifier.bitRate = htolel(0);
   } else {
      if (!(req = req_alloc(sizeof(struct start_media_transmission_message_ip6), START_MEDIA_TRANSMISSION_MESSAGE)))
         return;
      req->data.startmedia_ip6.conferenceId = htolel(sub->callid);
      req->data.startmedia_ip6.passThruPartyId = htolel(sub->callid);
      memcpy(req->data.startmedia_ip6.remoteIp, &dest.sin_addr.s_addr, sizeof(dest.sin_addr.s_addr));
      req->data.startmedia_ip6.remotePort = htolel(ntohs(dest.sin_port));
      req->data.startmedia_ip6.packetSize = htolel(fmt.cur_ms);
      req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(&fmt.format));
      req->data.startmedia_ip6.qualifier.precedence = htolel(127);
      req->data.startmedia_ip6.qualifier.vad = htolel(0);
      req->data.startmedia_ip6.qualifier.packets = htolel(0);
      req->data.startmedia_ip6.qualifier.bitRate = htolel(0);
   }

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting START_MEDIA_TRANSMISSION_MESSAGE to %s, callid %d, passthrupartyid %d, ip %s:%d, ms %d, fmt %d, prec 127\n",
      d->name, sub->callid, sub->callid, ast_inet_ntoa(dest.sin_addr), dest.sin_port, fmt.cur_ms, codec_ast2skinny(&fmt.format));
   transmit_response(d, req);
}
static void transmit_stop_tone ( struct skinny_device d,
int  instance,
int  reference 
) [static]

Definition at line 2441 of file chan_skinny.c.

References skinny_req::data, htolel, stop_tone_message::instance, stop_tone_message::reference, req_alloc(), SKINNY_DEBUG, STOP_TONE_MESSAGE, skinny_data::stoptone, and transmit_response().

Referenced by handle_keypad_button_message(), setsubstate(), and skinny_indicate().

{
   struct skinny_req *req;
   if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
      return;
   req->data.stoptone.instance = htolel(instance);
   req->data.stoptone.reference = htolel(reference);

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting STOP_TONE_MESSAGE to %s, inst %d, ref %d\n",
      d->name, instance, reference);
   transmit_response(d, req);
}
static void transmit_stopmediatransmission ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
static void transmit_versionres ( struct skinny_device d) [static]

Definition at line 2816 of file chan_skinny.c.

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

Referenced by handle_message().

{
   struct skinny_req *req;
   if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
      return;

   ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));

   SKINNY_DEBUG(DEBUG_PACKET, 3, "Transmitting VERSION_RES_MESSAGE to %s, version %s\n", d->name, d->version_id);
   transmit_response(d, req);
}
static int unload_module ( void  ) [static]

Definition at line 8004 of file chan_skinny.c.

References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_context_destroy(), ast_context_find(), ast_event_unsubscribe(), ast_format_cap_destroy(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_STOP, ast_rtp_glue_unregister(), ast_sched_context_destroy(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_channel_tech::capabilities, cli_skinny, delete_devices(), skinnysession::device, EVENT_FLAG_SYSTEM, skinnysession::fd, free, skinny_device::lines, skinny_subchannel::lock, skinny_line::lock, manager_event, skinny_line::mwi_event_sub, netlock, skinny_subchannel::owner, skinny_rtp_glue, skinny_tech, sub, skinny_line::sub, skinnysession::t, and unregister_exten().

{
   struct skinnysession *s;
   struct skinny_device *d;
   struct skinny_line *l;
   struct skinny_subchannel *sub;
   struct ast_context *con;

   ast_rtp_glue_unregister(&skinny_rtp_glue);
   ast_channel_unregister(&skinny_tech);
   ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));

   ast_manager_unregister("SKINNYdevices");
   ast_manager_unregister("SKINNYshowdevice");
   ast_manager_unregister("SKINNYlines");
   ast_manager_unregister("SKINNYshowline");
   
   AST_LIST_LOCK(&sessions);
   /* Destroy all the interfaces and free their memory */
   while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
      d = s->device;
      AST_LIST_TRAVERSE(&d->lines, l, list){
         ast_mutex_lock(&l->lock);
         AST_LIST_TRAVERSE(&l->sub, sub, list) {
            ast_mutex_lock(&sub->lock);
            if (sub->owner) {
               ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
            }
            ast_mutex_unlock(&sub->lock);
         }
         if (l->mwi_event_sub)
            ast_event_unsubscribe(l->mwi_event_sub);
         ast_mutex_unlock(&l->lock);
         manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
         unregister_exten(l);
      }
      if (s->fd > -1)
         close(s->fd);
      pthread_cancel(s->t);
      pthread_kill(s->t, SIGURG);
      pthread_join(s->t, NULL);
      free(s);
   }
   AST_LIST_UNLOCK(&sessions);

   delete_devices();

   ast_mutex_lock(&netlock);
   if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
      pthread_cancel(accept_t);
      pthread_kill(accept_t, SIGURG);
      pthread_join(accept_t, NULL);
   }
   accept_t = AST_PTHREADT_STOP;
   ast_mutex_unlock(&netlock);

   close(skinnysock);
   if (sched) {
      ast_sched_context_destroy(sched);
   }

   con = ast_context_find(used_context);
   if (con)
      ast_context_destroy(con, "Skinny");

   default_cap = ast_format_cap_destroy(default_cap);
   skinny_tech.capabilities = ast_format_cap_destroy(skinny_tech.capabilities);
   return 0;
}
static void unregister_exten ( struct skinny_line l) [static]

Definition at line 2070 of file chan_skinny.c.

References ast_context_find(), ast_context_remove_extension(), ast_copy_string(), ast_log(), ast_strlen_zero(), context, ext, LOG_WARNING, regcontext, and S_OR.

Referenced by skinny_unregister(), and unload_module().

{
   char multi[256];
   char *stringp, *ext, *context;

   if (ast_strlen_zero(regcontext))
      return;

   ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
   stringp = multi;
   while ((ext = strsep(&stringp, "&"))) {
      if ((context = strchr(ext, '@'))) {
         *context++ = '\0'; /* split ext@context */
         if (!ast_context_find(context)) {
            ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
            continue;
         }
      } else {
         context = regcontext;
      }
      ast_context_remove_extension(context, ext, 1, NULL);
   }
}
static void update_connectedline ( struct skinny_subchannel sub,
const void *  data,
size_t  datalen 
) [static]

Definition at line 3092 of file chan_skinny.c.

References ast_channel_caller(), ast_channel_connected(), ast_strlen_zero(), skinny_subchannel::callid, skinny_line::device, skinny_subchannel::line, skinny_subchannel::owner, send_callinfo(), skinny_device::session, and SKINNY_DEBUG.

Referenced by skinny_indicate().

{
   struct ast_channel *c = sub->owner;
   struct skinny_line *l = sub->line;
   struct skinny_device *d = l->device;

   if (!d->session) {
      return;
   }

   if (!ast_channel_caller(c)->id.number.valid
      || ast_strlen_zero(ast_channel_caller(c)->id.number.str)
      || !ast_channel_connected(c)->id.number.valid
      || ast_strlen_zero(ast_channel_connected(c)->id.number.str))
      return;

   SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Updating\n", sub->callid);

   send_callinfo(sub);
}

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 8085 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 1121 of file chan_skinny.c.

Referenced by config_load(), and skinny_register().

pthread_t accept_t [static]

Definition at line 1125 of file chan_skinny.c.

struct ast_hostent ahp [static]

Definition at line 1122 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

Definition at line 8085 of file chan_skinny.c.

Definition at line 194 of file chan_skinny.c.

Definition at line 193 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 1118 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 1126 of file chan_skinny.c.

struct ast_threadstorage callstate2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_callstate2str_threadbuf , .custom_init = NULL , } [static]

Definition at line 268 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 4188 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

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

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

Referenced by control2str().

unsigned int cos

Definition at line 187 of file chan_skinny.c.

unsigned int cos_audio

Definition at line 188 of file chan_skinny.c.

unsigned int cos_video

Definition at line 189 of file chan_skinny.c.

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

Definition at line 199 of file chan_skinny.c.

struct ast_format_cap* default_cap [static]

Definition at line 164 of file chan_skinny.c.

Definition at line 1473 of file chan_skinny.c.

Referenced by config_device(), and config_load().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Note:
Values shown here match the defaults shown in skinny.conf.sample

Definition at line 244 of file chan_skinny.c.

Definition at line 1370 of file chan_skinny.c.

Referenced by config_line(), and config_load().

struct ast_codec_pref default_prefs [static]

Definition at line 165 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

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

Definition at line 259 of file chan_skinny.c.

Referenced by device2str().

struct devices devices [static]
int firstdigittimeout = 16000 [static]

Definition at line 1244 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1247 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 192 of file chan_skinny.c.

struct lines lines [static]
int matchdigittimeout = 3000 [static]

Definition at line 1250 of file chan_skinny.c.

ast_mutex_t netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 1241 of file chan_skinny.c.

Referenced by config_load(), and unload_module().

char ourhost[256] [static]

Definition at line 1119 of file chan_skinny.c.

int ourport [static]

Definition at line 1120 of file chan_skinny.c.

struct { ... } qos [static]
char regcontext[AST_MAX_CONTEXT] [static]

Definition at line 198 of file chan_skinny.c.

Referenced by register_exten(), and unregister_exten().

struct ast_sched_context* sched = NULL [static]

Definition at line 1238 of file chan_skinny.c.

int skinny_header_size = 12 [static]

Definition at line 1109 of file chan_skinny.c.

struct ast_rtp_glue skinny_rtp_glue [static]

Definition at line 3252 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1511 of file chan_skinny.c.

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

int skinnyreload = 0 [static]

Definition at line 1115 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 1124 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 886 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]
Initial value:

Definition at line 930 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 916 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]
Initial value:

Definition at line 925 of file chan_skinny.c.

Definition at line 961 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 908 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]
Initial value:

Definition at line 939 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 895 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 876 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]
Initial value:

Definition at line 902 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]
Initial value:

Definition at line 934 of file chan_skinny.c.

const uint8_t soft_key_default_SLAconnectednotactive[] [static]
Initial value:

Definition at line 955 of file chan_skinny.c.

const uint8_t soft_key_default_SLAhold[] [static]
Initial value:

Definition at line 949 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]
Initial value:

Definition at line 945 of file chan_skinny.c.

Definition at line 713 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

struct ast_threadstorage substate2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_substate2str_threadbuf , .custom_init = NULL , } [static]

Definition at line 265 of file chan_skinny.c.

Referenced by substate2str().

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

Definition at line 161 of file chan_skinny.c.

unsigned int tos

Definition at line 184 of file chan_skinny.c.

unsigned int tos_audio

Definition at line 185 of file chan_skinny.c.

unsigned int tos_video

Definition at line 186 of file chan_skinny.c.

int unauth_sessions = 0 [static]

Definition at line 195 of file chan_skinny.c.

Definition at line 197 of file chan_skinny.c.

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

Definition at line 200 of file chan_skinny.c.

char vmexten[AST_MAX_EXTENSION] [static]

Definition at line 196 of file chan_skinny.c.

Referenced by build_peer(), set_peer_defaults(), and sip_send_mwi_to_peer().